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 + -
显示快捷键?