mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
cpp: C++11 for(auto x: v) now supported
git-svn-id: svn://ultimatepp.org/upp/trunk@8705 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
117c9ffdca
commit
241d02d67a
5 changed files with 224 additions and 212 deletions
211
uppsrc/CppBase/Body.cpp
Normal file
211
uppsrc/CppBase/Body.cpp
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
#include "CppBase.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
bool Parser::TryDecl()
|
||||
{ // attempt to interpret code as local variable declaration
|
||||
for(;;) {
|
||||
if(lex[0] == tk_static || lex[0] == tk_const ||
|
||||
lex[0] == tk_register || lex[0] == tk_volatile)
|
||||
++lex;
|
||||
else
|
||||
if(!VCAttribute())
|
||||
break;
|
||||
}
|
||||
int t = lex[0];
|
||||
int q = 0;
|
||||
if(t == tk_int || t == tk_bool || t == tk_float || t == tk_double || t == tk_void ||
|
||||
t == tk_long || t == tk_signed || t == tk_unsigned || t == tk_short ||
|
||||
t == tk_char || t == tk___int8 || t == tk___int16 || t == tk___int32 || t == tk___int64 ||
|
||||
t == tk_auto) {
|
||||
q++;
|
||||
while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and || lex[q] == tk_const) // t_and is r-value here
|
||||
q++;
|
||||
if(!lex.IsId(q))
|
||||
return false;
|
||||
static String aut("*"), empty;
|
||||
Locals(t == tk_auto ? aut : empty);
|
||||
return true;
|
||||
}
|
||||
String type;
|
||||
if(lex[q] == t_dblcolon) {
|
||||
type << "::";
|
||||
q++;
|
||||
}
|
||||
if(lex.IsId(q)) {
|
||||
type << lex.Id(q++);
|
||||
type << Tparam(q);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
while(lex[q] == t_dblcolon) {
|
||||
type << "::";
|
||||
if(lex.IsId(++q))
|
||||
type << lex.Id(q++);
|
||||
else
|
||||
return false;
|
||||
type << Tparam(q);
|
||||
}
|
||||
while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and) // t_and is r-value here
|
||||
q++;
|
||||
if(!lex.IsId(q))
|
||||
return false;
|
||||
type = Qualify(*base, current_scope, type, context.namespace_using);
|
||||
if(base->Find(NoTemplatePars(type)) >= 0) {
|
||||
Locals(type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Parser::MatchPars()
|
||||
{
|
||||
int level = 1;
|
||||
while(level && lex != t_eof) {
|
||||
if(Key('(')) level++;
|
||||
else
|
||||
if(Key(')')) level--;
|
||||
else
|
||||
++lex;
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::Statement()
|
||||
{
|
||||
RecursionCounter recursionCounter(currentScopeDepth, lex == '{' ? 0 : 1);
|
||||
maxScopeDepth = max(maxScopeDepth, currentScopeDepth);
|
||||
|
||||
if(Key(tk_case)) {
|
||||
if(lex.IsId())
|
||||
++lex;
|
||||
Key(':');
|
||||
}
|
||||
if(Key(tk_default))
|
||||
Key(':');
|
||||
if(lex.IsId() && lex[1] == ':') {
|
||||
++lex;
|
||||
++lex;
|
||||
}
|
||||
if(Key('{')) {
|
||||
Context cc;
|
||||
cc <<= context;
|
||||
int l = local.GetCount();
|
||||
while(!Key('}')) {
|
||||
if(lex == t_eof)
|
||||
ThrowError("eof");
|
||||
Statement();
|
||||
}
|
||||
context <<= cc;
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_if)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
if(Key(tk_else))
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_for)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_while)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_try))
|
||||
Statement();
|
||||
else
|
||||
if(Key(tk_catch)) {
|
||||
Key('(');
|
||||
MatchPars();
|
||||
Statement();
|
||||
}
|
||||
else
|
||||
if(Key(tk_do)) {
|
||||
Statement();
|
||||
Key(tk_while);
|
||||
Key('(');
|
||||
MatchPars();
|
||||
}
|
||||
else
|
||||
if(Key(tk_switch)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(UsingNamespace())
|
||||
;
|
||||
else
|
||||
if(TryDecl())
|
||||
Key(';');
|
||||
else
|
||||
for(;;) {
|
||||
if(lex == t_eof)
|
||||
ThrowError("");
|
||||
if(Key(';') || lex == '{' || lex == '}' || lex >= tk_if && lex <= tk_do)
|
||||
break;
|
||||
++lex;
|
||||
}
|
||||
}
|
||||
|
||||
bool Parser::EatBody()
|
||||
{
|
||||
if(lex != '{') {
|
||||
local.Clear();
|
||||
return false;
|
||||
}
|
||||
lex.BeginBody();
|
||||
maxScopeDepth = currentScopeDepth = dobody ? 0 : 1;
|
||||
if(dobody) {
|
||||
inbody = true;
|
||||
Statement();
|
||||
inbody = false;
|
||||
local.Clear();
|
||||
}
|
||||
else {
|
||||
Key('{');
|
||||
int level = 1;
|
||||
while(level && lex != t_eof) {
|
||||
if(Key('{')) level++;
|
||||
else
|
||||
if(Key('}')) level--;
|
||||
else
|
||||
++lex;
|
||||
maxScopeDepth = max(level, maxScopeDepth);
|
||||
}
|
||||
}
|
||||
lex.EndBody();
|
||||
return true;
|
||||
}
|
||||
|
||||
String Parser::ResolveAutoType()
|
||||
{
|
||||
Vector<String> xp = MakeXP(lex.Pos());
|
||||
if(lex == ':') // resolve for declaration, like 'for(auto i: vector)'
|
||||
xp << "." << "begin" << "()" << "->"; // incorrect, should rather use operator*(), but sufficient for now
|
||||
Index<String> s = GetExpressionType(*base, *this, xp);
|
||||
int i = FindMin(s); // Ugly hack: we are not resolving overloading at all, so just choose stable type if there are more
|
||||
return i < 0 ? String() : s[i];
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -512,6 +512,7 @@ struct Parser {
|
|||
|
||||
bool Key(int code);
|
||||
bool EatBody();
|
||||
String ResolveAutoType();
|
||||
|
||||
void Cv();
|
||||
String TType();
|
||||
|
|
@ -667,7 +668,7 @@ String ResolveTParam(const CppBase& codebase, const String& type,
|
|||
void ResolveTParam(const CppBase& codebase, Vector<String>& type, const Vector<String>& tparam);
|
||||
|
||||
Index<String> GetExpressionType(const CppBase& codebase, const Parser& parser, const Vector<String>& xp);
|
||||
Index<String> GetExpressionType(const CppBase& codebase, const Parser& parser, const char *s);
|
||||
Vector<String> MakeXP(const char *s);
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ file
|
|||
Pre.cpp,
|
||||
cpplex.cpp,
|
||||
Parser.cpp,
|
||||
Body.cpp,
|
||||
Base.cpp,
|
||||
ScopeInfo.cpp,
|
||||
Qualify.cpp,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ String ParseTemplatedType(const String& type, Vector<String>& tparam)
|
|||
}
|
||||
}
|
||||
tparam.Add(t);
|
||||
break;
|
||||
}
|
||||
else
|
||||
r.Cat(*s++);
|
||||
|
|
@ -213,6 +212,8 @@ void ExpressionTyper::ExpressionType(const String& ttype, int ii,
|
|||
String t = ResolveReturnType(m, tparam);
|
||||
if(done.Find(t) < 0) {
|
||||
bool skipfnpars = m.IsCode() && ii + 1 < xp.GetCount() && xp[ii + 1] == "()";
|
||||
if(t.StartsWith(type + "::")) // Resolve Vector::Iterator -> Vector<String>::Iterator
|
||||
t.Insert(type.GetCount(), "<" + Join(tparam, ",") + ">");
|
||||
ExpressionType(ResolveTParam(codebase, t, tparam), ii + skipfnpars + 1,
|
||||
m.IsData() && !m.isptr, lvl + 1);
|
||||
}
|
||||
|
|
@ -361,9 +362,4 @@ Vector<String> MakeXP(const char *s)
|
|||
return xp;
|
||||
}
|
||||
|
||||
Index<String> GetExpressionType(const CppBase& codebase, const Parser& parser, const char *s)
|
||||
{
|
||||
return GetExpressionType(codebase, parser, MakeXP(s));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -821,10 +821,10 @@ void Parser::Declarator(Decl& d, const char *p)
|
|||
// else
|
||||
if(lex.IsId() || lex == t_dblcolon || lex == tk_operator) {
|
||||
d.name = Name(d.castoper, d.oper);
|
||||
bool dummy;
|
||||
if(Key(':'))
|
||||
if(!Key(t_integer))
|
||||
Name(dummy, dummy);
|
||||
if(IsNull(d.type) && lex == ':' && lex[1] == t_integer) { // Bitfield, like 'unsigned x:5'
|
||||
++lex;
|
||||
++lex;
|
||||
}
|
||||
}
|
||||
if(Key('(')) {
|
||||
if(inbody || (lex < 256 || lex == tk_true || lex == tk_false)
|
||||
|
|
@ -852,12 +852,10 @@ void Parser::Declarator(Decl& d, const char *p)
|
|||
++lex;
|
||||
}
|
||||
}
|
||||
if(*d.type == '*') { // C++11 auto declaration
|
||||
Index<String> s = GetExpressionType(*base, *this, lex.Pos());
|
||||
int i = FindMin(s); // Ugly hack: we are not resolving overloading at all, so just choose stable type if there are more
|
||||
d.type = i < 0 ? String() : s[i];
|
||||
}
|
||||
EatInitializers();
|
||||
if(*d.type == '*') // C++11 auto declaration
|
||||
d.type = ResolveAutoType();
|
||||
else
|
||||
EatInitializers();
|
||||
while(Key('[')) {
|
||||
d.isptr = true;
|
||||
int level = 1;
|
||||
|
|
@ -1098,201 +1096,6 @@ bool Parser::VCAttribute()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Parser::TryDecl()
|
||||
{ // attempt to interpret code as local variable declaration
|
||||
for(;;) {
|
||||
if(lex[0] == tk_static || lex[0] == tk_const ||
|
||||
lex[0] == tk_register || lex[0] == tk_volatile)
|
||||
++lex;
|
||||
else
|
||||
if(!VCAttribute())
|
||||
break;
|
||||
}
|
||||
int t = lex[0];
|
||||
int q = 0;
|
||||
if(t == tk_int || t == tk_bool || t == tk_float || t == tk_double || t == tk_void ||
|
||||
t == tk_long || t == tk_signed || t == tk_unsigned || t == tk_short ||
|
||||
t == tk_char || t == tk___int8 || t == tk___int16 || t == tk___int32 || t == tk___int64 ||
|
||||
t == tk_auto) {
|
||||
q++;
|
||||
while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and || lex[q] == tk_const) // t_and is r-value here
|
||||
q++;
|
||||
if(!lex.IsId(q))
|
||||
return false;
|
||||
Locals(t == tk_auto ? "*" : String());
|
||||
return true;
|
||||
}
|
||||
String type;
|
||||
if(lex[q] == t_dblcolon) {
|
||||
type << "::";
|
||||
q++;
|
||||
}
|
||||
if(lex.IsId(q)) {
|
||||
type << lex.Id(q++);
|
||||
type << Tparam(q);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
while(lex[q] == t_dblcolon) {
|
||||
type << "::";
|
||||
if(lex.IsId(++q))
|
||||
type << lex.Id(q++);
|
||||
else
|
||||
return false;
|
||||
type << Tparam(q);
|
||||
}
|
||||
while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and) // t_and is r-value here
|
||||
q++;
|
||||
if(!lex.IsId(q))
|
||||
return false;
|
||||
type = Qualify(*base, current_scope, type, context.namespace_using);
|
||||
if(base->Find(NoTemplatePars(type)) >= 0) {
|
||||
Locals(type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Parser::MatchPars()
|
||||
{
|
||||
int level = 1;
|
||||
while(level && lex != t_eof) {
|
||||
if(Key('(')) level++;
|
||||
else
|
||||
if(Key(')')) level--;
|
||||
else
|
||||
++lex;
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::Statement()
|
||||
{
|
||||
RecursionCounter recursionCounter(currentScopeDepth, lex == '{' ? 0 : 1);
|
||||
maxScopeDepth = max(maxScopeDepth, currentScopeDepth);
|
||||
|
||||
if(Key(tk_case)) {
|
||||
if(lex.IsId())
|
||||
++lex;
|
||||
Key(':');
|
||||
}
|
||||
if(Key(tk_default))
|
||||
Key(':');
|
||||
if(lex.IsId() && lex[1] == ':') {
|
||||
++lex;
|
||||
++lex;
|
||||
}
|
||||
if(Key('{')) {
|
||||
Context cc;
|
||||
cc <<= context;
|
||||
int l = local.GetCount();
|
||||
while(!Key('}')) {
|
||||
if(lex == t_eof)
|
||||
ThrowError("eof");
|
||||
Statement();
|
||||
}
|
||||
context <<= cc;
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_if)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
if(Key(tk_else))
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_for)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_while)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(Key(tk_try))
|
||||
Statement();
|
||||
else
|
||||
if(Key(tk_catch)) {
|
||||
Key('(');
|
||||
MatchPars();
|
||||
Statement();
|
||||
}
|
||||
else
|
||||
if(Key(tk_do)) {
|
||||
Statement();
|
||||
Key(tk_while);
|
||||
Key('(');
|
||||
MatchPars();
|
||||
}
|
||||
else
|
||||
if(Key(tk_switch)) {
|
||||
int l = local.GetCount();
|
||||
Key('(');
|
||||
TryDecl();
|
||||
MatchPars();
|
||||
Statement();
|
||||
local.Trim(l);
|
||||
}
|
||||
else
|
||||
if(UsingNamespace())
|
||||
;
|
||||
else
|
||||
if(TryDecl())
|
||||
Key(';');
|
||||
else
|
||||
for(;;) {
|
||||
if(lex == t_eof)
|
||||
ThrowError("");
|
||||
if(Key(';') || lex == '{' || lex == '}' || lex >= tk_if && lex <= tk_do)
|
||||
break;
|
||||
++lex;
|
||||
}
|
||||
}
|
||||
|
||||
bool Parser::EatBody()
|
||||
{
|
||||
if(lex != '{') {
|
||||
local.Clear();
|
||||
return false;
|
||||
}
|
||||
lex.BeginBody();
|
||||
maxScopeDepth = currentScopeDepth = dobody ? 0 : 1;
|
||||
if(dobody) {
|
||||
inbody = true;
|
||||
Statement();
|
||||
inbody = false;
|
||||
local.Clear();
|
||||
}
|
||||
else {
|
||||
Key('{');
|
||||
int level = 1;
|
||||
while(level && lex != t_eof) {
|
||||
if(Key('{')) level++;
|
||||
else
|
||||
if(Key('}')) level--;
|
||||
else
|
||||
++lex;
|
||||
maxScopeDepth = max(level, maxScopeDepth);
|
||||
}
|
||||
}
|
||||
lex.EndBody();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Parser::SetScopeCurrent()
|
||||
{
|
||||
current_scope = context.scope;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue