parser.cc

来自「这个程序是关于OpenC++的反射植入机制的编译器」· CC 代码 · 共 3,111 行 · 第 1/5 页

CC
3,111
字号
//@beginlicenses@//@license{chiba_tokyo}{}@//@license{contributors}{}@////  Permission to use, copy, distribute and modify this software and its  //  documentation for any purpose is hereby granted without fee, provided that//  the above copyright notice appears in all copies and that both that copyright//  notice and this permission notice appear in supporting documentation.// //  1997-2001 Shigeru Chiba, Tokyo Institute of Technology. make(s) no representations about the suitability of this//  software for any purpose. It is provided "as is" without express or implied//  warranty.//  //  Copyright (C)  1997-2001 Shigeru Chiba, Tokyo Institute of Technology.////  -----------------------------------------------------------------////  Permission to use, copy, distribute and modify this software and its  //  documentation for any purpose is hereby granted without fee, provided that//  the above copyright notice appears in all copies and that both that copyright//  notice and this permission notice appear in supporting documentation.// //  Other Contributors (see file AUTHORS) make(s) no representations about the suitability of this//  software for any purpose. It is provided "as is" without express or implied//  warranty.//  //  Copyright (C)  Other Contributors (see file AUTHORS)////@endlicenses@/*   C++ Parser   This parser is a LL(k) parser with ad hoc rules such as   backtracking.   r<name>() is the grammer rule for a non-terminal <name>.   opt<name>() is the grammer fule for an optional non-terminal <name>.   is<name>() looks ahead and returns true if the next symbol is <name>.*/#include <iostream>#include <opencxx/parser/Parser.h>#include <opencxx/parser/Token.h>#include <opencxx/parser/Lex.h>#include <opencxx/parser/token-names.h>#include <opencxx/parser/ptreeAll.h>#include <opencxx/parser/Encoding.h>#include <opencxx/parser/PtreeUtil.h>#include <opencxx/parser/MopMsg.h>#include <opencxx/parser/ParseErrorMsg.h>#include <opencxx/parser/ErrorLog.h>#include <opencxx/parser/SourceLocation.h>#include <opencxx/parser/NullMetaclassLoader.h>#if defined(_PARSE_VCC)#define _MSC_VER	1100#endifusing namespace std;namespace Opencxx{unsigned Parser::LineNumber(char* pos, char*& fname, int& fname_len){    unsigned line_number = lex->LineNumber(pos, fname, fname_len);    if(fname_len > 1){	if(fname[0] == '"') {	    ++fname;	    --fname_len;	}	if(fname[fname_len - 1] == '"')	    --fname_len;    }    return line_number;}bool Parser::rProgram(Ptree*& def){    while(lex->LookAhead(0) != '\0')	if(rDefinition(def))	    return true;	else{	    Token tk;	    if(!SyntaxError())		return false;		// too many errors	    SkipTo(';');	    lex->GetToken(tk);	// ignore ';'	}    return false;}/*  definition  : null.declaration  | typedef.stmt  | template.decl  | metaclass.decl  | linkage.spec  | namespace.spec  | namespace.alias  | using.declaration  | extern.template.decl  | declaration*/bool Parser::rDefinition(Ptree*& p){    bool res;    int t = lex->LookAhead(0);    if(t == ';')	res = rNullDeclaration(p);    else if(t == TYPEDEF)	res = rTypedef(p);    else if(t == TEMPLATE)	res = rTemplateDecl(p);    else if(t == METACLASS)	res = rMetaclassDecl(p);    else if(t == EXTERN && lex->LookAhead(1) == StringL)	res = rLinkageSpec(p);    else if(t == EXTERN && lex->LookAhead(1) == TEMPLATE)	res = rExternTemplateDecl(p);    else if(t == NAMESPACE && lex->LookAhead(2) == '=')	res = rNamespaceAlias(p);    else if(t == NAMESPACE)	res = rNamespaceSpec(p);    else if(t == USING)	res = rUsing(p);    else {	Ptree* c = lex->GetComments2();	if (res = rDeclaration(p))	{	    PtreeUtil::SetDeclaratorComments(p, c);	}    }    lex->GetComments();    return res;}bool Parser::rNullDeclaration(Ptree*& decl){    Token tk;    if(lex->GetToken(tk) != ';')	return false;    decl = new PtreeDeclaration(0, PtreeUtil::List(0, new Leaf(tk)));    return true;}/*  typedef.stmt  : TYPEDEF type.specifier declarators ';'*/bool Parser::rTypedef(Ptree*& def){    Token tk;    Ptree *type_name, *decl;    Encoding type_encode;    if(lex->GetToken(tk) != TYPEDEF)	return false;    def = new PtreeTypedef(new LeafReserved(tk));    if(!rTypeSpecifier(type_name, false, type_encode))	return false;    def = PtreeUtil::Snoc(def, type_name);    if(!rDeclarators(decl, type_encode, true))	return false;    if(lex->GetToken(tk) != ';')	return false;    def = PtreeUtil::Nconc(def, PtreeUtil::List(decl, new Leaf(tk)));    return true;}/*  type.specifier  : {cv.qualify} (integral.type.or.class.spec | name) {cv.qualify}*/bool Parser::rTypeSpecifier(Ptree*& tspec, bool check, Encoding& encode){    Ptree *cv_q, *cv_q2;    if(!optCvQualify(cv_q) || !optIntegralTypeOrClassSpec(tspec, encode))	return false;    if(tspec == 0){	if(check){	    Token tk;	    lex->LookAhead(0, tk);	    if(!MaybeTypeNameOrClassTemplate(tk))		return false;	}	if(!rName(tspec, encode))	    return false;    }    if(!optCvQualify(cv_q2))	return false;    if(cv_q != 0){	tspec = PtreeUtil::Snoc(cv_q, tspec);	if(cv_q2 != 0)	    tspec = PtreeUtil::Nconc(tspec, cv_q2);    }    else if(cv_q2 != 0)	tspec = PtreeUtil::Cons(tspec, cv_q2);    encode.CvQualify(cv_q, cv_q2);    return true;}// isTypeSpecifier() returns true if the next is probably a type specifier.bool Parser::isTypeSpecifier(){    int t = lex->LookAhead(0);    if(t == Identifier || t == Scope       ||t == CONST || t == VOLATILE       || t == CHAR || t == INT || t == SHORT || t == LONG       || t == WCHAR // new !!!       || t == SIGNED || t == UNSIGNED || t == FLOAT || t == DOUBLE       || t == VOID || t == BOOLEAN       || t == CLASS || t == STRUCT || t == UNION || t == ENUM#if defined(_MSC_VER)       || t == INT64#endif       )	return true;    else	return false;}/*  metaclass.decl  : METACLASS Identifier {{':'} Identifier {'(' meta.arguments ')'}} ';'  We allow two kinds of syntax:  metaclass <metaclass> <class>(...);  metaclass <metaclass>;  metaclass <class> : <metaclass>(...);		// for backward compatibility*/bool Parser::rMetaclassDecl(Ptree*& decl){    int t;    Token tk1, tk2, tk3, tk4;    Ptree* metaclass_name;    if(lex->GetToken(tk1) != METACLASS)	return false;    if(lex->GetToken(tk2) != Identifier)	return false;    t = lex->GetToken(tk3);    if(t == Identifier){	metaclass_name = new Leaf(tk2);	decl = new PtreeMetaclassDecl(new LeafReserved(tk1),				      PtreeUtil::List(metaclass_name,						  new Leaf(tk3)));    }    else if(t == ':'){	if(lex->GetToken(tk4) != Identifier)	    return false;	metaclass_name = new Leaf(tk4);	decl = new PtreeMetaclassDecl(new LeafReserved(tk1),				      PtreeUtil::List(metaclass_name,						  new Leaf(tk2)));    }    else if(t == ';'){	metaclass_name = new Leaf(tk2);	decl = new PtreeMetaclassDecl(new LeafReserved(tk1),				      PtreeUtil::List(metaclass_name, 0,						  new Leaf(tk3)));	metaclassLoader_->LoadMetaclass(metaclass_name->ToString());	return true;    }    else	return false;    t = lex->GetToken(tk1);    if(t == '('){	Ptree* args;	if(!rMetaArguments(args))	    return false;	if(lex->GetToken(tk2) != ')')	    return false;	decl = PtreeUtil::Nconc(decl, PtreeUtil::List(new Leaf(tk1), args,					      new Leaf(tk2)));	t = lex->GetToken(tk1);    }    if(t == ';'){	decl = PtreeUtil::Snoc(decl, new Leaf(tk1));	metaclassLoader_->LoadMetaclass(metaclass_name->ToString());	return true;    }    else	return false;}/*  meta.arguments : (anything but ')')**/bool Parser::rMetaArguments(Ptree*& args){    int t;    Token tk;    int n = 1;    args = 0;    for(;;){	t = lex->LookAhead(0);	if(t == '\0')	    return false;	else if(t == '(')	    ++n;	else if(t == ')')	    if(--n <= 0)		return true;	lex->GetToken(tk);	args = PtreeUtil::Snoc(args, new Leaf(tk));    }}/*  linkage.spec  : EXTERN StringL definition  |  EXTERN StringL linkage.body*/bool Parser::rLinkageSpec(Ptree*& spec){    Token tk1, tk2;    Ptree* body;    if(lex->GetToken(tk1) != EXTERN)	return false;    if(lex->GetToken(tk2) != StringL)	return false;    spec = new PtreeLinkageSpec(new LeafEXTERN(tk1),				PtreeUtil::List(new Leaf(tk2)));    if(lex->LookAhead(0) == '{'){	if(!rLinkageBody(body))	    return false;    }    else	if(!rDefinition(body))	    return false;    spec = PtreeUtil::Snoc(spec, body);    return true;}/*  namespace.spec  : NAMESPACE Identifier definition  | NAMESPACE { Identifier } linkage.body*/bool Parser::rNamespaceSpec(Ptree*& spec){    Token tk1, tk2;    Ptree* name;    Ptree* body;    if(lex->GetToken(tk1) != NAMESPACE)	return false;    if(lex->LookAhead(0) == '{')	name = 0;    else	if(lex->GetToken(tk2) == Identifier)	    name = new Leaf(tk2);	else	    return false;    if(lex->LookAhead(0) == '{'){	if(!rLinkageBody(body))	    return false;    }    else	if(!rDefinition(body))	    return false;    spec = new PtreeNamespaceSpec(new LeafNAMESPACE(tk1),				  PtreeUtil::List(name, body));    return true;}/*  namespace.alias : NAMESPACE Identifier '=' Identifier ';'*/bool Parser::rNamespaceAlias(Ptree *&exp){  Token tk;  if(lex->GetToken(tk) != NAMESPACE) return false;  Ptree *ns = new LeafNAMESPACE(tk);  if (lex->GetToken(tk) != Identifier) return false;  Ptree *alias = new Leaf(tk);  if (lex->GetToken(tk) != '=') return false;  Ptree *eq = new Leaf(tk);  Ptree *name;  Encoding encode;  int length = 0;  if(lex->LookAhead(0) == Scope)  {    lex->GetToken(tk);    name = PtreeUtil::List(new Leaf(tk));    encode.GlobalScope();    ++length;  }  else name = 0;  while (true)  {    if (lex->GetToken(tk) != Identifier) return false;    Ptree *n = new Leaf(tk);    encode.SimpleName(n);    ++length;        if(lex->LookAhead(0) == Scope)    {      lex->GetToken(tk);      name = PtreeUtil::Nconc(name, PtreeUtil::List(n, new Leaf(tk)));    }    else    {      if(name == 0) name = n;      else name = PtreeUtil::Snoc(name, n);      if(length > 1) encode.Qualified(length);      break;    }  }  if (lex->GetToken(tk) != ';') return false;  exp = new PtreeNamespaceAlias(ns, PtreeUtil::List(alias, eq, name, new Leaf(tk)));  return true;}/*  using.declaration : USING { NAMESPACE } name ';'*/bool Parser::rUsing(Ptree*& decl){    Token tk;    Ptree* name;    Encoding encode;    if(lex->GetToken(tk) != USING)	return false;    Ptree* using0 = new LeafUSING(tk);    Ptree* using1;    if (lex->LookAhead(0) != NAMESPACE)	using1 = 0;    else {	lex->GetToken(tk);	using1 = new LeafNAMESPACE(tk);    }    if (!rName(name, encode))	return false;    if (lex->GetToken(tk) != ';')	return false;    decl = new PtreeUsing(using0, using1, name, encode.Get(), new Leaf(tk));    return true;}/*  linkage.body : '{' (definition)* '}'  Note: this is also used to construct namespace.spec*/bool Parser::rLinkageBody(Ptree*& body){    Token op, cp;    Ptree* def;    if(lex->GetToken(op) != '{')	return false;    body = 0;    while(lex->LookAhead(0) != '}'){	if(!rDefinition(def)){	    if(!SyntaxError())		return false;		// too many errors	    SkipTo('}');	    lex->GetToken(cp);	    body = PtreeUtil::List(new Leaf(op), 0, new Leaf(cp));	    return true;		// error recovery	}	body = PtreeUtil::Snoc(body, def);    }    lex->GetToken(cp);    body = new PtreeBrace(new Leaf(op), body, new Leaf(cp));    return true;}/*  template.decl  : TEMPLATE '<' temp.arg.list '>' declaration  | TEMPLATE declaration  | TEMPLATE '<' '>' declaration  The second case is an explicit template instantiation.  declaration must  be a class declaration.  For example,      template class Foo<int, char>;  explicitly instantiates the template Foo with int and char.  The third case is a specialization of a template function.  declaration  must be a function template.  For example,      template <> int count(String x) { return x.length; }*/bool Parser::rTemplateDecl(Ptree*& decl){    Ptree *body;    TemplateDeclKind kind = tdk_unknown;    if(!rTemplateDecl2(decl, kind))	return false;    if(!rDeclaration(body))	return false;    // Repackage the decl and body depending upon what kind of template    // declaration was observed.    switch (kind) {    case tdk_instantiation:	// Repackage the decl as a PtreeTemplateInstantiation	decl = body;	// assumes that decl has the form: [0 [class ...] ;]	if (PtreeUtil::Length(decl) != 3)	    return false;	if (PtreeUtil::First(decl) != 0)	    return false;	if (PtreeUtil::Second(decl)->What() != ntClassSpec)	    return false;	if (!PtreeUtil::Eq(PtreeUtil::Third(decl), ';'))	    return false;	decl = new PtreeTemplateInstantiation(PtreeUtil::Second(decl));	break;    case tdk_decl:    case tdk_specialization:	decl = PtreeUtil::Snoc(decl, body);	break;    default:        errorLog_.Report(MopMsg(Msg::Fatal, "rTemplateDecl()", "fatal"));	break;    }    return true;}bool Parser::rTemplateDecl2(Ptree*& decl, TemplateDeclKind &kind){    Token tk;    Ptree *args;    if(lex->GetToken(tk) != TEMPLATE)	return false;    if(lex->LookAhead(0) != '<') {	// template instantiation	decl = 0;	kind = tdk_instantiation;	return true;	// ignore TEMPLATE    }    decl = new PtreeTemplateDecl(new LeafReserved(tk));    if(lex->GetToken(tk) != '<')	return false;    decl = PtreeUtil::Snoc(decl, new Leaf(tk));    if(!rTempArgList(args))	return false;    if(lex->GetToken(tk) != '>')	return false;    decl = PtreeUtil::Nconc(decl, PtreeUtil::List(args, new Leaf(tk)));    // ignore nested TEMPLATE    while (lex->LookAhead(0) == TEMPLATE) {	lex->GetToken(tk);	if(lex->LookAhead(0) != '<')	    break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?