parser.cc
来自「这个程序是关于OpenC++的反射植入机制的编译器」· CC 代码 · 共 3,111 行 · 第 1/5 页
CC
3,111 行
lex->GetToken(tk); if(!rTempArgList(args)) return false; if(lex->GetToken(tk) != '>') return false; } if (args == 0) // template < > declaration kind = tdk_specialization; else // template < ... > declaration kind = tdk_decl; return true;}/* temp.arg.list : empty | temp.arg.declaration (',' temp.arg.declaration)**/bool Parser::rTempArgList(Ptree*& args){ Token tk; Ptree* a; if(lex->LookAhead(0) == '>'){ args = 0; return true; } if(!rTempArgDeclaration(a)) return false; args = PtreeUtil::List(a); while(lex->LookAhead(0) == ','){ lex->GetToken(tk); args = PtreeUtil::Snoc(args, new Leaf(tk)); if(!rTempArgDeclaration(a)) return false; args = PtreeUtil::Snoc(args, a); } return true;}/* temp.arg.declaration : CLASS Identifier {'=' type.name} | type.specifier arg.declarator {'=' additive.expr} | template.decl2 CLASS Identifier {'=' type.name}*/bool Parser::rTempArgDeclaration(Ptree*& decl){ Token tk1, tk2; int t0 = lex->LookAhead(0); if(t0 == CLASS && lex->LookAhead(1) == Identifier){ lex->GetToken(tk1); lex->GetToken(tk2); Ptree* name = new Leaf(tk2); decl = PtreeUtil::List(new Leaf(tk1), name); if(lex->LookAhead(0) == '='){ Ptree* default_type; lex->GetToken(tk1); if(!rTypeName(default_type)) return false; decl = PtreeUtil::Nconc(decl, PtreeUtil::List(new Leaf(tk1), default_type)); } } else if (t0 == TEMPLATE) { TemplateDeclKind kind; if(!rTemplateDecl2(decl, kind)) return false; if (lex->GetToken(tk1) != CLASS || lex->GetToken(tk2) != Identifier) return false; Ptree* cspec = new PtreeClassSpec(new LeafReserved(tk1), PtreeUtil::Cons(new Leaf(tk2),0), 0); decl = PtreeUtil::Snoc(decl, cspec); if(lex->LookAhead(0) == '='){ Ptree* default_type; lex->GetToken(tk1); if(!rTypeName(default_type)) return false; decl = PtreeUtil::Nconc(decl, PtreeUtil::List(new Leaf(tk1), default_type)); } } else{ Ptree *type_name, *arg; Encoding type_encode, name_encode; if(!rTypeSpecifier(type_name, true, type_encode)) return false; if(!rDeclarator(arg, kArgDeclarator, false, type_encode, name_encode, true)) return false; decl = PtreeUtil::List(type_name, arg); if(lex->LookAhead(0) == '='){ Ptree* exp; lex->GetToken(tk1); if(!rAdditiveExpr(exp)) return false; decl = PtreeUtil::Nconc(decl, PtreeUtil::List(new Leaf(tk1), exp)); } } return true;}/* extern.template.decl : EXTERN TEMPLATE declaration*/bool Parser::rExternTemplateDecl(Ptree*& decl){ Token tk1, tk2; Ptree* body; if(lex->GetToken(tk1) != EXTERN) return false; if(lex->GetToken(tk2) != TEMPLATE) return false; if(!rDeclaration(body)) return false; decl = new PtreeExternTemplate(new Leaf(tk1), PtreeUtil::List(new Leaf(tk2), body)); return true;}/* declaration : integral.declaration | const.declaration | other.declaration decl.head : {member.spec} {storage.spec} {member.spec} {cv.qualify} integral.declaration : integral.decl.head declarators (';' | function.body) | integral.decl.head ';' | integral.decl.head ':' expression ';' integral.decl.head : decl.head integral.type.or.class.spec {cv.qualify} other.declaration : decl.head name {cv.qualify} declarators (';' | function.body) | decl.head name constructor.decl (';' | function.body) | FRIEND name ';' const.declaration : cv.qualify {'*'} Identifier '=' expression {',' declarators} ';' Note: if you modify this function, look at declaration.statement, too. Note: this regards a statement like "T (a);" as a constructor declaration. See isConstructorDecl().*/bool Parser::rDeclaration(Ptree*& statement){ Ptree *mem_s, *storage_s, *cv_q, *integral, *head; Encoding type_encode; if(!optMemberSpec(mem_s) || !optStorageSpec(storage_s)) return false; if(mem_s == 0) head = 0; else head = mem_s; // mem_s is a list. if(storage_s != 0) head = PtreeUtil::Snoc(head, storage_s); if(mem_s == 0) if(optMemberSpec(mem_s)) head = PtreeUtil::Nconc(head, mem_s); else return false; if(!optCvQualify(cv_q) || !optIntegralTypeOrClassSpec(integral, type_encode)) return false; if(integral != 0) return rIntegralDeclaration(statement, type_encode, head, integral, cv_q); else{ type_encode.Clear(); int t = lex->LookAhead(0); if(cv_q != 0 && ((t == Identifier && lex->LookAhead(1) == '=') || t == '*')) return rConstDeclaration(statement, type_encode, head, cv_q); else return rOtherDeclaration(statement, type_encode, mem_s, cv_q, head); }}/* single declaration, for use in a condition (controlling expression of switch/while/if) */bool Parser::rSimpleDeclaration(Ptree*& statement){ Ptree *cv_q, *integral; Encoding type_encode, name_encode; /* no member specification permitted here, and no storage specifier: type-specifier ::= simple-type-specifier class-specifier enum-specifier elaborated-type-specifier cv-qualifier */ if(!optCvQualify(cv_q) || !optIntegralTypeOrClassSpec(integral, type_encode)) return false; if (integral == 0 && !rName(integral, type_encode)) return false; if (cv_q != 0 && integral != 0) integral = PtreeUtil::Snoc(cv_q, integral); else if (cv_q != 0 && integral == 0) integral = cv_q, cv_q = 0; /* no type-specifier so far -> can't be a declaration */ if (integral == 0) return false; Ptree* d; if(!rDeclarator(d, kDeclarator, false, type_encode, name_encode, true, true)) return false; if (lex->LookAhead(0) != '=') return false; Token eqs; lex->GetToken(eqs); /*int t =*/ lex->LookAhead(0); Ptree* e; if(!rExpression(e)) return false; PtreeUtil::Nconc(d, PtreeUtil::List(new Leaf(eqs), e)); statement = new PtreeDeclaration(0, PtreeUtil::List(integral, PtreeUtil::List(d))); return true;}bool Parser::rIntegralDeclaration(Ptree*& statement, Encoding& type_encode, Ptree* head, Ptree* integral, Ptree* cv_q){ Token tk; Ptree *cv_q2, *decl; if(!optCvQualify(cv_q2)) return false; if(cv_q != 0) if(cv_q2 == 0) integral = PtreeUtil::Snoc(cv_q, integral); else integral = PtreeUtil::Nconc(cv_q, PtreeUtil::Cons(integral, cv_q2)); else if(cv_q2 != 0) integral = PtreeUtil::Cons(integral, cv_q2); type_encode.CvQualify(cv_q, cv_q2); switch(lex->LookAhead(0)){ case ';' : lex->GetToken(tk); statement = new PtreeDeclaration(head, PtreeUtil::List(integral, new Leaf(tk))); return true; case ':' : // bit field lex->GetToken(tk); if(!rExpression(decl)) return false; decl = PtreeUtil::List(PtreeUtil::List(new Leaf(tk), decl)); if(lex->GetToken(tk) != ';') return false; statement = new PtreeDeclaration(head, PtreeUtil::List(integral, decl, new Leaf(tk))); return true; default : if(!rDeclarators(decl, type_encode, true)) return false; if(lex->LookAhead(0) == ';'){ lex->GetToken(tk); statement = new PtreeDeclaration(head, PtreeUtil::List(integral, decl, new Leaf(tk))); return true; } else{ Ptree* body; if(!rFunctionBody(body)) return false; if(PtreeUtil::Length(decl) != 1) return false; statement = new PtreeDeclaration(head, PtreeUtil::List(integral, decl->Car(), body)); return true; } }}bool Parser::rConstDeclaration(Ptree*& statement, Encoding&, Ptree* head, Ptree* cv_q){ Ptree* decl; Token tk; Encoding type_encode; type_encode.SimpleConst(); if(!rDeclarators(decl, type_encode, false)) return false; if(lex->LookAhead(0) != ';') return false; lex->GetToken(tk); statement = new PtreeDeclaration(head, PtreeUtil::List(cv_q, decl, new Leaf(tk))); return true;}bool Parser::rOtherDeclaration(Ptree*& statement, Encoding& type_encode, Ptree* mem_s, Ptree* cv_q, Ptree* head){ Ptree *type_name, *decl, *cv_q2; Token tk; if(!rName(type_name, type_encode)) return false; if(cv_q == 0 && isConstructorDecl()){ Encoding ftype_encode; if(!rConstructorDecl(decl, ftype_encode)) return false; decl = PtreeUtil::List( new PtreeDeclarator( type_name, decl, ftype_encode.Get(), type_encode.Get(), type_name)); type_name = 0; } else if(mem_s != 0 && lex->LookAhead(0) == ';'){ // FRIEND name ';' if(PtreeUtil::Length(mem_s) == 1 && mem_s->Car()->What() == FRIEND){ lex->GetToken(tk); statement = new PtreeDeclaration(head, PtreeUtil::List(type_name, new Leaf(tk))); return true; } else return false; } else{ if(!optCvQualify(cv_q2)) return false; if(cv_q != 0) if(cv_q2 == 0) type_name = PtreeUtil::Snoc(cv_q, type_name); else type_name = PtreeUtil::Nconc(cv_q, PtreeUtil::Cons(type_name, cv_q2)); else if(cv_q2 != 0) type_name = PtreeUtil::Cons(type_name, cv_q2); type_encode.CvQualify(cv_q, cv_q2); if(!rDeclarators(decl, type_encode, false)) return false; } if(lex->LookAhead(0) == ';'){ lex->GetToken(tk); statement = new PtreeDeclaration(head, PtreeUtil::List(type_name, decl, new Leaf(tk))); } else{ Ptree* body; if(!rFunctionBody(body)) return false; if(PtreeUtil::Length(decl) != 1) return false; statement = new PtreeDeclaration(head, PtreeUtil::List(type_name, decl->Car(), body)); } return true;}/* This returns true for an declaration like: T (a); even if a is not a type name. This is a bug according to the ANSI specification, but I believe none says "T (a);" for a variable declaration.*/bool Parser::isConstructorDecl(){ if(lex->LookAhead(0) != '(') return false; else{ int t = lex->LookAhead(1); if(t == '*' || t == '&' || t == '(') return false; // declarator else if(t == CONST || t == VOLATILE) return true; // constructor or declarator else if(isPtrToMember(1)) return false; // declarator (::*) else return true; // maybe constructor }}/* ptr.to.member : {'::'} (identifier {'<' any* '>'} '::')+ '*'*/bool Parser::isPtrToMember(int i){ int t0 = lex->LookAhead(i++); if(t0 == Scope) t0 = lex->LookAhead(i++); while(t0 == Identifier){ int t = lex->LookAhead(i++); if(t == '<'){ int n = 1; while(n > 0){ int u = lex->LookAhead(i++); if(u == '<') ++n; else if(u == '>') --n; else if(u == '('){ int m = 1; while(m > 0){ int v = lex->LookAhead(i++); if(v == '(') ++m; else if(v == ')') --m; else if(v == '\0' || v == ';' || v == '}') return false; } } else if(u == '\0' || u == ';' || u == '}') return false; } t = lex->LookAhead(i++); } if(t != Scope) return false; t0 = lex->LookAhead(i++); if(t0 == '*') return true; } return false;}/* member.spec : (FRIEND | INLINE | VIRTUAL | userdef.keyword)+*/bool Parser::optMemberSpec(Ptree*& p){ Token tk; Ptree* lf; int t = lex->LookAhead(0); p = 0; while(t == FRIEND || t == INLINE || t == VIRTUAL || t == UserKeyword5){ if(t == UserKeyword5){ if(!rUserdefKeyword(lf)) return false; } else{ lex->GetToken(tk); if(t == INLINE) lf = new LeafINLINE(tk); else if(t == VIRTUAL) lf = new LeafVIRTUAL(tk); else lf = new LeafFRIEND(tk); } p = PtreeUtil::Snoc(p, lf); t = lex->LookAhead(0); } return true;}/* storage.spec : STATIC | EXTERN | AUTO | REGISTER | MUTABLE*/bool Parser::optStorageSpec(Ptree*& p){ int t = lex->LookAhead(0); if(t == STATIC || t == EXTERN || t == AUTO || t == REGISTER || t == MUTABLE){ Token tk; lex->GetToken(tk); switch(t){ case STATIC : p = new LeafSTATIC(tk); break; case EXTERN : p = new LeafEXTERN(tk); break; case AUTO : p = new LeafAUTO(tk); break; case REGISTER : p = new LeafREGISTER(tk); break; case MUTABLE : p = new LeafMUTABLE(tk); break; default : errorLog_.Report(MopMsg(Msg::Fatal, "optStorageSpec()", "fatal")); break; } } else p = 0; // no storage specifier return true;}/* cv.qualify : (CONST | VOLATILE)+*/bool Parser::optCvQualify(Ptree*& cv){ Ptree* p = 0; for(;;){ int t = lex->LookAhead(0); if(t == CONST || t == VOLATILE){ Token tk; lex->GetToken(tk); switch(t){ case CONST : p = PtreeUtil::Snoc(p, new LeafCONST(tk)); break; case VOLATILE : p = PtreeUtil::Snoc(p, new LeafVOLATILE(tk)); break; default : errorLog_.Report(MopMsg(Msg::Fatal, "optCvQualify()", "fatal")); break; } } else break; } cv = p; return true;}/* !!! added WCHAR integral.type.or.class.spec : (CHAR | WCHAR | INT | SHORT | LONG | SIGNED | UNSIGNED | FLOAT | DOUBLE | VOID | BOOLEAN)+ | class.spec | enum.spec Note: if editing this, see also isTypeSpecifier().*/bool Parser::optIntegralTypeOrClassSpec(Ptree*& p, Encoding& encode){ bool is_integral; int t; char type = ' ', flag = ' '; is_integral = false; p = 0; for(;;){ t = lex->LookAhead(0); if(t == CHAR || t == INT || t == SHORT || t == LONG || t == SIGNED || t == WCHAR // !!! || t == UNSIGNED || t == FLOAT || t == DOUBLE || t == VOID || t == BOOLEAN
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?