forked from phoedos/pmd
0f9a4a97c0
Fixes #431 Note: the tokens separate by such continuation characters are not merged and appear as two separate tokens, which could lead to false negatives in duplication detection. ContinuationReader is deleted, since skipping characters in the stream makes it difficult to provide accurate line numbers/positions.
1576 lines
28 KiB
Plaintext
1576 lines
28 KiB
Plaintext
/**
|
|
*
|
|
* Copyright (C) 1996, 1997 Sun Microsystems Inc.
|
|
*
|
|
* Use of this file and the system it is part of is constrained by the
|
|
* file COPYRIGHT in the root directory of this system. You may, however,
|
|
* make any modifications you wish to this file.
|
|
*
|
|
* Author: Sreenivasa Viswanadha
|
|
* Date: 3/20/97
|
|
*
|
|
* This file contains a Java grammar and actions that implement a front-end.
|
|
*
|
|
*
|
|
* Derived in part from the following work:
|
|
*
|
|
* PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g)
|
|
*
|
|
* Authors: Sumana Srinivasan, NeXT Inc.; sumana_srinivasan@next.com
|
|
* Terence Parr, Parr Research Corporation; parrt@parr-research.com
|
|
* Russell Quong, Purdue University; quong@ecn.purdue.edu
|
|
*
|
|
* VERSION 1.1
|
|
*
|
|
*/
|
|
options {
|
|
BUILD_PARSER=false;
|
|
CACHE_TOKENS=true;
|
|
UNICODE_INPUT=true;
|
|
}
|
|
|
|
PARSER_BEGIN(CppParser)
|
|
package net.sourceforge.pmd.lang.cpp.ast;
|
|
|
|
import net.sourceforge.pmd.lang.ast.CharStream;
|
|
import net.sourceforge.pmd.lang.ast.TokenMgrError;
|
|
|
|
public final class CppParser {
|
|
|
|
private static String vers = "0.1";
|
|
private static String id = "C++ Parser";
|
|
|
|
private static void msg(String s) {
|
|
System.out.println(id + " Version " + vers +": " + s);
|
|
}
|
|
|
|
public static void main(String args[]) {
|
|
CppParser parser;
|
|
java.io.InputStream input;
|
|
|
|
int ai = 0;
|
|
|
|
if (ai == (args.length-1)) {
|
|
msg("Reading from file " + args[ai] + " . . .");
|
|
try {
|
|
input = new java.io.FileInputStream(args[ai]);
|
|
} catch (java.io.FileNotFoundException e) {
|
|
msg("File " + args[0] + " not found.");
|
|
return;
|
|
}
|
|
} else if (ai >= args.length) {
|
|
msg("Reading from standard input . . .");
|
|
input = System.in;
|
|
} else {
|
|
msg("Usage: java " + id + " [-d] [inputfile]");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
parser = new CppParser(input);
|
|
parser.translation_unit();
|
|
msg("Program parsed successfully.");
|
|
} catch (ParseException e) {
|
|
msg("Encountered errors during parse.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A symbol table manager object. Currently only types are recorded for
|
|
* doing semantic predicates for parsing.
|
|
*/
|
|
static SymtabManager sym;
|
|
|
|
/*
|
|
* Methods used in semantics predicates.
|
|
*/
|
|
|
|
/**
|
|
* Reads a fully qualified name (since it is used during lookahead, we
|
|
* cannot use token. We have to explicitly use getToken).
|
|
*/
|
|
static String GetFullyScopedName() throws ParseException
|
|
{
|
|
Token t = getToken(1);
|
|
|
|
if (t.kind != ID && t.kind != SCOPE)
|
|
return null;
|
|
|
|
StringBuffer s = new StringBuffer();
|
|
|
|
int i;
|
|
if (t.kind != SCOPE)
|
|
{
|
|
s.append(t.image);
|
|
t = getToken(2);
|
|
i = 3;
|
|
}
|
|
else
|
|
i = 2;
|
|
|
|
while (t.kind == SCOPE)
|
|
{
|
|
s.append(t.image);
|
|
s.append((t = getToken(i++)).image);
|
|
t = getToken(i++);
|
|
}
|
|
|
|
return s.toString();
|
|
}
|
|
|
|
/**
|
|
* This method first tries to read a sequence of tokens of the form
|
|
* ("::")? <ID> ("::" <ID>)*
|
|
* and if it succeeds then asks the symbol table manager if this is
|
|
* the name of a constructor.
|
|
*/
|
|
static boolean IsCtor() throws ParseException
|
|
{
|
|
return sym.IsCtor(GetFullyScopedName());
|
|
}
|
|
}
|
|
|
|
PARSER_END(CppParser)
|
|
|
|
SKIP :
|
|
{
|
|
" "
|
|
|
|
|
"\f"
|
|
|
|
|
"\t"
|
|
|
|
|
"\r\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"//" : IN_LINE_COMMENT
|
|
|
|
|
"/*" : IN_COMMENT
|
|
|
|
|
"#" : PREPROCESSOR_OUTPUT
|
|
|
|
|
"\\\r\n"
|
|
|
|
|
"\\\n"
|
|
}
|
|
|
|
<IN_LINE_COMMENT> SKIP:
|
|
{
|
|
"\n" : DEFAULT
|
|
}
|
|
|
|
<IN_LINE_COMMENT> MORE:
|
|
{
|
|
< ~[] >
|
|
}
|
|
|
|
<IN_COMMENT> SKIP:
|
|
{ "*/" : DEFAULT }
|
|
|
|
<IN_COMMENT,IN_PREPROCESSOR_OUTPUT_COMMENT> MORE:
|
|
{ < ~[] > }
|
|
|
|
<IN_PREPROCESSOR_OUTPUT_COMMENT> SKIP:
|
|
{ "*/" : PREPROCESSOR_OUTPUT }
|
|
|
|
<PREPROCESSOR_OUTPUT> SKIP:
|
|
{
|
|
"\n" : DEFAULT
|
|
| "/*" : IN_PREPROCESSOR_OUTPUT_COMMENT
|
|
| "//" : IN_LINE_COMMENT
|
|
}
|
|
|
|
<PREPROCESSOR_OUTPUT> MORE:
|
|
{
|
|
"\\\n"
|
|
|
|
|
"\\\r\n"
|
|
|
|
|
< ~[] >
|
|
}
|
|
|
|
TOKEN :
|
|
{
|
|
< LCURLYBRACE: "{" >
|
|
| < RCURLYBRACE: "}" >
|
|
| < LSQUAREBRACKET: "[" >
|
|
| < RSQUAREBRACKET: "]" >
|
|
| < LPARENTHESIS: "(" >
|
|
| < RPARENTHESIS: ")" >
|
|
| < SCOPE: "::" >
|
|
| < COLON: ":" >
|
|
| < SEMICOLON: ";" >
|
|
| < COMMA: "," >
|
|
| < QUESTIONMARK: "?" >
|
|
| < ELLIPSIS: "..." >
|
|
| < ASSIGNEQUAL: "=" >
|
|
| < TIMESEQUAL: "*=" >
|
|
| < DIVIDEEQUAL: "/=" >
|
|
| < MODEQUAL: "%=" >
|
|
| < PLUSEQUAL: "+=" >
|
|
| < MINUSEQUAL: "-=" >
|
|
| < SHIFTLEFTEQUAL: "<<=" >
|
|
| < SHIFTRIGHTEQUAL: ">>=" >
|
|
| < BITWISEANDEQUAL: "&=" >
|
|
| < BITWISEXOREQUAL: "^=" >
|
|
| < BITWISEOREQUAL: "|=" >
|
|
| < OR: "||" >
|
|
| < AND: "&&" >
|
|
| < BITWISEOR: "|" >
|
|
| < BITWISEXOR: "^" >
|
|
| < AMPERSAND: "&" >
|
|
| < EQUAL: "==" >
|
|
| < NOTEQUAL: "!=" >
|
|
| < LESSTHAN: "<" >
|
|
| < GREATERTHAN: ">" >
|
|
| < LESSTHANOREQUALTO: "<=" >
|
|
| < GREATERTHANOREQUALTO: ">=" >
|
|
| < SHIFTLEFT: "<<" >
|
|
| < SHIFTRIGHT: ">>" >
|
|
| < PLUS: "+" >
|
|
| < MINUS: "-" >
|
|
| < STAR: "*" >
|
|
| < DIVIDE: "/" >
|
|
| < MOD: "%" >
|
|
| < PLUSPLUS: "++" >
|
|
| < MINUSMINUS: "--" >
|
|
| < TILDE: "~" >
|
|
| < NOT: "!" >
|
|
| < DOT: "." >
|
|
| < POINTERTO: "->" >
|
|
| < DOTSTAR: ".*" >
|
|
| < ARROWSTAR: "->*" >
|
|
| < AUTO: "auto" >
|
|
| < BREAK: "break" >
|
|
| < CASE: "case" >
|
|
| < CATCH: "catch" >
|
|
| < CHAR: "char" >
|
|
| < CONST: "const" >
|
|
| < CONTINUE: "continue" >
|
|
| < _DEFAULT: "default" >
|
|
| < DELETE: "delete" >
|
|
| < DO: "do" >
|
|
| < DOUBLE: "double" >
|
|
| < ELSE: "else" >
|
|
| < ENUM: "enum" >
|
|
| < EXTERN: "extern" >
|
|
| < FLOAT: "float" >
|
|
| < FOR: "for" >
|
|
| < FRIEND: "friend" >
|
|
| < GOTO: "goto" >
|
|
| < IF: "if" >
|
|
| < INLINE: "inline" >
|
|
| < INT: "int" >
|
|
| < LONG: "long" >
|
|
| < NEW: "new" >
|
|
| < PRIVATE: "private" >
|
|
| < PROTECTED: "protected" >
|
|
| < PUBLIC: "public" >
|
|
| < REDECLARED: "redeclared" >
|
|
| < REGISTER: "register" >
|
|
| < RETURN: "return" >
|
|
| < SHORT: "short" >
|
|
| < SIGNED: "signed" >
|
|
| < SIZEOF: "sizeof" >
|
|
| < STATIC: "static" >
|
|
| < STRUCT: "struct" >
|
|
| < CLASS : "class" >
|
|
| < SWITCH: "switch" >
|
|
| < TEMPLATE: "template" >
|
|
| < THIS: "this" >
|
|
| < TRY: "try" >
|
|
| < TYPEDEF: "typedef" >
|
|
| < UNION: "union" >
|
|
| < UNSIGNED: "unsigned" >
|
|
| < VIRTUAL: "virtual" >
|
|
| < VOID: "void" >
|
|
| < VOLATILE: "volatile" >
|
|
| < WHILE: "while" >
|
|
| < OPERATOR: "operator" >
|
|
| < TRUETOK: "true" >
|
|
| < FALSETOK: "false" >
|
|
| < THROW: "throw" >
|
|
| < AT: "@" >
|
|
| < FINALLY: "finally" >
|
|
}
|
|
|
|
TOKEN [IGNORE_CASE] :
|
|
{
|
|
< OCTALINT : "0" (["0"-"7"])* >
|
|
| < OCTALLONG : <OCTALINT> "l" >
|
|
| < UNSIGNED_OCTALINT : <OCTALINT> "u" >
|
|
| < UNSIGNED_OCTALLONG : <OCTALINT> ("ul" | "lu") >
|
|
|
|
| < DECIMALINT : ["1"-"9"] (["0"-"9"])* >
|
|
| < DECIMALLONG : <DECIMALINT> ["u","l"] >
|
|
| < UNSIGNED_DECIMALINT : <DECIMALINT> "u" >
|
|
| < UNSIGNED_DECIMALLONG : <DECIMALINT> ("ul" | "lu") >
|
|
|
|
|
|
| < HEXADECIMALINT : "0x" (["0"-"9","a"-"f"])+ >
|
|
| < HEXADECIMALLONG : <HEXADECIMALINT> (["u","l"])? >
|
|
| < UNSIGNED_HEXADECIMALINT : <HEXADECIMALINT> "u" >
|
|
| < UNSIGNED_HEXADECIMALLONG : <HEXADECIMALINT> ("ul" | "lu") >
|
|
|
|
|
|
| < FLOATONE : ((["0"-"9"])+ "." (["0"-"9"])* | (["0"-"9"])* "." (["0"-"9"])+)
|
|
("e" (["-","+"])? (["0"-"9"])+)? (["f","l"])? >
|
|
|
|
| < FLOATTWO : (["0"-"9"])+ "e" (["-","+"])? (["0"-"9"])+ (["f","l"])? >
|
|
}
|
|
|
|
TOKEN :
|
|
{
|
|
|
|
< CHARACTER : ("L")? "'" ( ( ~["'","\\","\r","\n"] ) | ( "\\" ( ~["\n","\r"] ) ) )* "'" >
|
|
|
|
| < STRING : ("L")? "\"" ( ( ~["\"","\\","\r","\n"] ) | ( ("\\")+ ( ~["\n","\r"] | "\n" | "\r\n" ) ) )* "\"" >
|
|
|
|
| < RSTRING : "R\"(" ( ~[")"] | ( ")" ~["\""] ) )* ")\"" >
|
|
}
|
|
|
|
TOKEN :
|
|
{
|
|
< ID : ["$", "a"-"z","A"-"Z", "_"] (["a"-"z","A"-"Z","0"-"9","_","$"])* >
|
|
}
|
|
|
|
|
|
void translation_unit() :
|
|
{}
|
|
{
|
|
{ sym.OpenScope(null, false); }
|
|
( LOOKAHEAD(2) external_declaration() )* <EOF>
|
|
{ sym.CloseScope(); }
|
|
}
|
|
|
|
void external_declaration() :
|
|
{ boolean isTypedef = false; }
|
|
{
|
|
LOOKAHEAD(("typedef" | template_head())? class_head() "{")
|
|
( template_head() )? declaration()
|
|
|
|
|
LOOKAHEAD("enum" (<ID>)? "{")
|
|
enum_specifier() (init_declarator_list(false))? ";"
|
|
|
|
|
LOOKAHEAD ((template_head())? dtor_ctor_decl_spec()
|
|
dtor_declarator() "{")
|
|
dtor_definition()
|
|
|
|
|
LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead())
|
|
ctor_definition()
|
|
|
|
|
|
|
LOOKAHEAD((declaration_specifiers())? function_declarator_lookahead())
|
|
function_definition()
|
|
|
|
|
|
|
LOOKAHEAD((scope_override())? "operator")
|
|
conversion_function_decl_or_def()
|
|
|
|
|
template_head()
|
|
(
|
|
LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead())
|
|
ctor_definition()
|
|
|
|
|
LOOKAHEAD((declaration_specifiers())? function_declarator_lookahead())
|
|
function_definition()
|
|
|
|
|
isTypedef = declaration_specifiers()
|
|
(init_declarator_list(isTypedef))? ";"
|
|
)
|
|
|
|
|
declaration()
|
|
|
|
|
";"
|
|
}
|
|
|
|
void function_definition() :
|
|
{
|
|
Scope sc = null;
|
|
boolean isTypedef;
|
|
}
|
|
{
|
|
|
|
LOOKAHEAD(3) isTypedef = declaration_specifiers()
|
|
sc = function_declarator(isTypedef) func_decl_def(sc)
|
|
|
|
|
sc = function_declarator(false) func_decl_def(sc)
|
|
}
|
|
|
|
void func_decl_def(Scope sc) :
|
|
{
|
|
boolean closeReqd = false;
|
|
}
|
|
{
|
|
{
|
|
if (closeReqd = (sc != null && sc != sym.GetCurScope()))
|
|
sym.OpenScope(sc);
|
|
}
|
|
|
|
(
|
|
";"
|
|
|
|
|
compound_statement()
|
|
)
|
|
|
|
{ if (closeReqd) sym.CloseScope(); }
|
|
}
|
|
|
|
void linkage_specification() :
|
|
{}
|
|
{
|
|
"extern" <STRING>
|
|
(
|
|
"{" ( external_declaration() )* "}"
|
|
( LOOKAHEAD(";") ";")?
|
|
|
|
|
declaration()
|
|
)
|
|
}
|
|
|
|
void declaration() :
|
|
{ boolean isTypedef = false; }
|
|
{
|
|
LOOKAHEAD(2)
|
|
isTypedef = declaration_specifiers()
|
|
(init_declarator_list(isTypedef))? ";"
|
|
|
|
|
linkage_specification()
|
|
}
|
|
|
|
/**
|
|
* Very temporary. Just returns true if it sees a typedef. Finally, we will
|
|
* need a structure that stores all the attributes.
|
|
*/
|
|
boolean type_modifiers() :
|
|
{ boolean isTypedef = false; }
|
|
{
|
|
(
|
|
isTypedef = storage_class_specifier()
|
|
|
|
|
type_qualifier()
|
|
|
|
|
"inline"
|
|
|
|
|
"virtual"
|
|
|
|
|
"friend"
|
|
)
|
|
|
|
{ return isTypedef; }
|
|
}
|
|
|
|
/**
|
|
* Very temporary. Just returns true if it sees a typedef. Finally, we will
|
|
* need a structure that stores all the attributes.
|
|
*/
|
|
boolean declaration_specifiers() :
|
|
{
|
|
Token t;
|
|
boolean isTypedef = false, tmp;
|
|
}
|
|
{
|
|
(
|
|
(
|
|
LOOKAHEAD(type_modifiers()) tmp = type_modifiers() { isTypedef |= tmp; }
|
|
)+
|
|
|
|
[ LOOKAHEAD(2) (
|
|
LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
|
|
( LOOKAHEAD(2) (
|
|
LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
|
|
|
|
|
LOOKAHEAD(type_modifiers()) tmp = type_modifiers() )
|
|
{ isTypedef |= tmp; }
|
|
)*
|
|
|
|
|
(
|
|
class_specifier()
|
|
|
|
|
enum_specifier()
|
|
|
|
|
qualified_type()
|
|
)
|
|
(LOOKAHEAD(2) tmp = type_modifiers() { isTypedef |= tmp;} )*
|
|
) ]
|
|
|
|
|
LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
|
|
( LOOKAHEAD(2) (
|
|
LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
|
|
|
|
|
tmp = type_modifiers() { isTypedef |= tmp; } )
|
|
)*
|
|
|
|
|
|
|
(
|
|
class_specifier()
|
|
|
|
|
enum_specifier()
|
|
|
|
|
qualified_type()
|
|
)
|
|
(LOOKAHEAD(2) tmp = type_modifiers() { isTypedef |= tmp; } )*
|
|
)
|
|
|
|
{ return isTypedef; }
|
|
}
|
|
|
|
/*
|
|
void type_specifier() :
|
|
{}
|
|
{
|
|
simple_type_specifier()
|
|
|
|
|
class_specifier()
|
|
|
|
|
enum_specifier()
|
|
}
|
|
*/
|
|
|
|
void simple_type_specifier() :
|
|
{}
|
|
{
|
|
(
|
|
builtin_type_specifier()
|
|
|
|
|
qualified_type()
|
|
)
|
|
}
|
|
|
|
void scope_override_lookahead() :
|
|
{}
|
|
{
|
|
"::"
|
|
|
|
|
<ID> ("<" template_argument_list() ">")? "::"
|
|
}
|
|
|
|
String scope_override() :
|
|
{
|
|
String name = "";
|
|
Token t;
|
|
}
|
|
{
|
|
(
|
|
("::") { name += "::"; }
|
|
(
|
|
LOOKAHEAD(2) t = <ID> ("<" template_argument_list() ">")? "::"
|
|
{ name += t.image + "::"; }
|
|
)*
|
|
|
|
|
(
|
|
LOOKAHEAD(2) t = <ID> ("<" template_argument_list() ">")? "::"
|
|
{ name += t.image + "::"; }
|
|
)+
|
|
)
|
|
{ return name; }
|
|
}
|
|
|
|
|
|
String qualified_id() :
|
|
{
|
|
String name = "";
|
|
Token t;
|
|
}
|
|
{
|
|
[ LOOKAHEAD(scope_override_lookahead()) name = scope_override() ]
|
|
(
|
|
t = <ID> [ "<" template_argument_list() ">" ]
|
|
{ return name + t.image; }
|
|
|
|
|
"operator" optor() { return "operator"; }
|
|
)
|
|
}
|
|
|
|
void ptr_to_member() :
|
|
{}
|
|
{
|
|
scope_override() "*"
|
|
}
|
|
|
|
void qualified_type() :
|
|
{}
|
|
{
|
|
LOOKAHEAD({ sym.IsFullyScopedTypeName(GetFullyScopedName()) } )
|
|
qualified_id()
|
|
}
|
|
|
|
void type_qualifier() :
|
|
{}
|
|
{
|
|
"const" | "volatile"
|
|
}
|
|
|
|
/**
|
|
* Very temporary. Just returns true if it sees a typedef. Finally, we will
|
|
* need a structure that stores all the attributes.
|
|
*/
|
|
boolean storage_class_specifier() :
|
|
{}
|
|
{
|
|
( "auto" | "register" | "static" | "extern" ) { return false; }
|
|
| "typedef" { return true; }
|
|
}
|
|
|
|
void builtin_type_specifier() :
|
|
{}
|
|
{
|
|
"void" | "char" | "short" | "int" | "long" | "float" |
|
|
"double" | "signed" | "unsigned"
|
|
}
|
|
|
|
void init_declarator_list(boolean isTypedef) :
|
|
{}
|
|
{
|
|
init_declarator(isTypedef) ("," init_declarator(isTypedef))*
|
|
}
|
|
|
|
void init_declarator(boolean isTypedef) :
|
|
{ String name; }
|
|
{
|
|
name = declarator()
|
|
{
|
|
if (isTypedef)
|
|
sym.PutTypeName(name);
|
|
}
|
|
(
|
|
"=" initializer()
|
|
|
|
|
"(" expression_list() ")"
|
|
)?
|
|
}
|
|
|
|
void class_head() :
|
|
{}
|
|
{
|
|
("struct" | "union" | "class")
|
|
(<ID> (base_clause(null))?)?
|
|
}
|
|
|
|
void class_specifier() :
|
|
{
|
|
ClassScope sc = null;
|
|
Token t;
|
|
}
|
|
{
|
|
("struct" | "union" | "class" )
|
|
(
|
|
"{"
|
|
{
|
|
sym.OpenScope(null, false);
|
|
}
|
|
(member_declaration())*
|
|
"}"
|
|
{
|
|
sym.CloseScope();
|
|
}
|
|
|
|
|
LOOKAHEAD(2) t = <ID>
|
|
{
|
|
sc = (ClassScope)sym.OpenScope(t.image, true);
|
|
}
|
|
(base_clause(sc))?
|
|
"{"
|
|
(member_declaration())*
|
|
"}"
|
|
{
|
|
sym.CloseScope();
|
|
}
|
|
|
|
|
t=<ID> (LOOKAHEAD(2) "<" template_argument_list() ">")?
|
|
{ sym.PutTypeName(t.image); }
|
|
)
|
|
}
|
|
|
|
void base_clause(ClassScope scope) :
|
|
{}
|
|
{
|
|
":" base_specifier(scope) ( "," base_specifier(scope) )*
|
|
}
|
|
|
|
void base_specifier(ClassScope scope) :
|
|
{ Token t; }
|
|
{
|
|
("virtual" (access_specifier())? | access_specifier() ("virtual")?)?
|
|
(LOOKAHEAD(scope_override_lookahead()) scope_override())?
|
|
t = <ID> ("<" template_argument_list() ">")?
|
|
{ scope.AddSuper(sym.GetScope(t.image));
|
|
}
|
|
}
|
|
|
|
void access_specifier() :
|
|
{}
|
|
{
|
|
"public" | "protected" | "private"
|
|
}
|
|
|
|
void member_declaration() :
|
|
{ boolean isTypedef = false; }
|
|
{
|
|
LOOKAHEAD(("typedef")? class_head() "{") declaration()
|
|
|
|
|
|
|
LOOKAHEAD("enum" (<ID>)? "{") enum_specifier()
|
|
( member_declarator_list(false) )? ";"
|
|
|
|
|
LOOKAHEAD( "operator" )
|
|
conversion_function_decl_or_def()
|
|
|
|
|
LOOKAHEAD(dtor_ctor_decl_spec() dtor_declarator() "{")
|
|
dtor_definition()
|
|
|
|
|
LOOKAHEAD(("inline"| "virtual")* "~")
|
|
dtor_ctor_decl_spec() simple_dtor_declarator() ";"
|
|
|
|
|
LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead())
|
|
ctor_definition()
|
|
|
|
|
LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead() ";")
|
|
(dtor_ctor_decl_spec() ctor_declarator() ";")
|
|
|
|
|
LOOKAHEAD((declaration_specifiers())? function_declarator_lookahead())
|
|
function_definition()
|
|
|
|
|
LOOKAHEAD(declaration_specifiers())
|
|
isTypedef = declaration_specifiers()
|
|
(member_declarator_list(isTypedef))? ";"
|
|
|
|
|
LOOKAHEAD(<ID>) function_declarator(false) ";"
|
|
|
|
|
LOOKAHEAD(3)
|
|
qualified_id() ";"
|
|
|
|
|
access_specifier() ":"
|
|
|
|
|
";"
|
|
}
|
|
|
|
void member_declarator_list(boolean isTypedef) :
|
|
{}
|
|
{
|
|
member_declarator(isTypedef) ("=" <OCTALINT>)?
|
|
("," member_declarator(isTypedef) ("=" <OCTALINT>)?)*
|
|
}
|
|
|
|
void member_declarator(boolean isTypedef) :
|
|
{ String name; }
|
|
{
|
|
name = declarator()
|
|
{
|
|
if (isTypedef)
|
|
sym.PutTypeName(name);
|
|
}
|
|
}
|
|
|
|
void conversion_function_decl_or_def() :
|
|
{
|
|
Scope sc = null;
|
|
String name = null;
|
|
}
|
|
{
|
|
[ LOOKAHEAD(scope_override_lookahead()) name = scope_override() ]
|
|
|
|
"operator" declaration_specifiers() ("*" | "&")?
|
|
|
|
"(" (parameter_list())? ")"
|
|
(LOOKAHEAD(2) type_qualifier())?
|
|
(exception_spec())?
|
|
func_decl_def(null) // Temporary (fix the null)
|
|
}
|
|
|
|
void enum_specifier() :
|
|
{ Token t; }
|
|
{
|
|
"enum"
|
|
(
|
|
"{" enumerator_list() "}"
|
|
|
|
|
t=<ID> (LOOKAHEAD(2) "{" enumerator_list() "}")?
|
|
{ sym.PutTypeName(t.image); }
|
|
)
|
|
}
|
|
|
|
void enumerator_list() :
|
|
{}
|
|
{
|
|
enumerator() ("," enumerator())*
|
|
}
|
|
|
|
void enumerator() :
|
|
{}
|
|
{
|
|
<ID> ("=" constant_expression())?
|
|
}
|
|
|
|
void ptr_operator() :
|
|
{}
|
|
{
|
|
"&" cv_qualifier_seq()
|
|
|
|
|
"*" cv_qualifier_seq()
|
|
|
|
|
ptr_to_member() cv_qualifier_seq()
|
|
}
|
|
|
|
void cv_qualifier_seq() :
|
|
{}
|
|
{
|
|
[ LOOKAHEAD(2) (
|
|
"const" [ LOOKAHEAD(2) "volatile" ]
|
|
|
|
|
"volatile" [ LOOKAHEAD(2) "const" ] )
|
|
]
|
|
}
|
|
|
|
String declarator() :
|
|
{ String name; }
|
|
{
|
|
(
|
|
LOOKAHEAD(ptr_operator())
|
|
ptr_operator() name = declarator()
|
|
|
|
|
name = direct_declarator()
|
|
)
|
|
|
|
{ return name; }
|
|
}
|
|
|
|
String direct_declarator() :
|
|
{
|
|
String name;
|
|
Token t;
|
|
}
|
|
{
|
|
LOOKAHEAD(2)
|
|
"~" t = <ID> (LOOKAHEAD(2) declarator_suffixes())?
|
|
{ return "~" + t.image; }
|
|
|
|
|
"(" name = declarator() ")" (LOOKAHEAD(2) declarator_suffixes())?
|
|
{ return name; }
|
|
|
|
|
name = qualified_id() (LOOKAHEAD(2) declarator_suffixes())?
|
|
{ return name; }
|
|
}
|
|
|
|
void declarator_suffixes() :
|
|
{}
|
|
{
|
|
("[" (constant_expression())? "]" )+
|
|
|
|
|
"(" (parameter_list())? ")"
|
|
(LOOKAHEAD(2) type_qualifier())?
|
|
(exception_spec())?
|
|
}
|
|
|
|
/**
|
|
* Used only for lookahead.
|
|
*/
|
|
void function_declarator_lookahead() :
|
|
{}
|
|
{
|
|
(LOOKAHEAD(2) ptr_operator() )* qualified_id() "("
|
|
}
|
|
|
|
Scope function_declarator(boolean isTypedef) :
|
|
{ Scope sc = null; }
|
|
{
|
|
(
|
|
LOOKAHEAD(ptr_operator())
|
|
ptr_operator() sc = function_declarator(isTypedef)
|
|
|
|
|
sc = function_direct_declarator(isTypedef)
|
|
)
|
|
|
|
{ return sc; }
|
|
}
|
|
|
|
Scope function_direct_declarator(boolean isTypedef) :
|
|
{
|
|
String name;
|
|
Scope sc = null;
|
|
boolean closeReqd = false;
|
|
}
|
|
{
|
|
name = qualified_id()
|
|
|
|
{
|
|
sc = sym.GetScopeOfFullyScopedName(name);
|
|
|
|
if (closeReqd = (sc != null && sc != sym.GetCurScope()))
|
|
sym.OpenScope(sc);
|
|
}
|
|
|
|
"(" (parameter_list())? ")"
|
|
(LOOKAHEAD(2) type_qualifier())?
|
|
(exception_spec())?
|
|
(LOOKAHEAD("=") "=" <OCTALINT>)?
|
|
|
|
{
|
|
if (closeReqd)
|
|
sym.CloseScope();
|
|
|
|
if (isTypedef)
|
|
sym.PutTypeName(name);
|
|
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
void dtor_ctor_decl_spec() :
|
|
{}
|
|
{
|
|
[
|
|
"virtual" [ "inline"]
|
|
|
|
|
"inline" [ "virtual"]
|
|
]
|
|
}
|
|
|
|
void dtor_definition() :
|
|
{}
|
|
{
|
|
(template_head())?
|
|
dtor_ctor_decl_spec()
|
|
dtor_declarator()
|
|
compound_statement()
|
|
}
|
|
|
|
void ctor_definition() :
|
|
{
|
|
Scope sc = null;
|
|
boolean closeReqd = false;
|
|
}
|
|
{
|
|
dtor_ctor_decl_spec() sc = ctor_declarator()
|
|
|
|
{
|
|
if (closeReqd = (sc != null && sc != sym.GetCurScope()))
|
|
sym.OpenScope(sc);
|
|
}
|
|
|
|
(exception_spec())?
|
|
|
|
(
|
|
";"
|
|
|
|
|
[ ctor_initializer() ] compound_statement()
|
|
)
|
|
|
|
{ if (closeReqd) sym.CloseScope(); }
|
|
}
|
|
|
|
void ctor_declarator_lookahead() :
|
|
{}
|
|
{
|
|
LOOKAHEAD( { IsCtor() } ) qualified_id() "("
|
|
}
|
|
|
|
Scope ctor_declarator() :
|
|
{
|
|
String name;
|
|
Scope sc = null;
|
|
boolean closeReqd = false;
|
|
}
|
|
{
|
|
LOOKAHEAD( { IsCtor() } )
|
|
name = qualified_id()
|
|
|
|
{
|
|
sc = sym.GetScopeOfFullyScopedName(name);
|
|
|
|
if (closeReqd = (sc != null && sc != sym.GetCurScope()))
|
|
sym.OpenScope(sc);
|
|
}
|
|
|
|
"(" [ LOOKAHEAD(2) parameter_list() ] ")"
|
|
|
|
[ LOOKAHEAD(2) exception_spec() ]
|
|
|
|
{
|
|
if (closeReqd)
|
|
sym.CloseScope();
|
|
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
void ctor_initializer() :
|
|
{}
|
|
{
|
|
":" superclass_init() ("," superclass_init())*
|
|
}
|
|
|
|
void superclass_init() :
|
|
{}
|
|
{
|
|
qualified_id() "(" (expression_list())? ")"
|
|
}
|
|
|
|
void dtor_declarator() :
|
|
{}
|
|
{
|
|
(LOOKAHEAD(scope_override_lookahead()) scope_override())?
|
|
simple_dtor_declarator()
|
|
}
|
|
|
|
void simple_dtor_declarator() :
|
|
{}
|
|
{
|
|
"~"
|
|
LOOKAHEAD( { IsCtor() } ) <ID> "(" (parameter_list())? ")"
|
|
}
|
|
|
|
void parameter_list() :
|
|
{}
|
|
{
|
|
parameter_declaration_list() [ LOOKAHEAD(2) [ "," ] "..." ]
|
|
|
|
|
"..."
|
|
}
|
|
|
|
void parameter_declaration_list() :
|
|
{}
|
|
{
|
|
parameter_declaration() (LOOKAHEAD(2) "," parameter_declaration())*
|
|
}
|
|
|
|
void parameter_declaration() :
|
|
{}
|
|
{
|
|
declaration_specifiers()
|
|
(
|
|
LOOKAHEAD(declarator()) declarator()
|
|
|
|
|
abstract_declarator()
|
|
)
|
|
("=" assignment_expression())?
|
|
}
|
|
|
|
void initializer() :
|
|
{}
|
|
{
|
|
LOOKAHEAD(3)
|
|
"{" initializer() ("," initializer())* "}"
|
|
|
|
|
assignment_expression()
|
|
}
|
|
|
|
void type_name() :
|
|
{}
|
|
{
|
|
declaration_specifiers() abstract_declarator()
|
|
}
|
|
|
|
void abstract_declarator() :
|
|
{}
|
|
{
|
|
[ LOOKAHEAD(2) (
|
|
"(" abstract_declarator() ")"
|
|
(abstract_declarator_suffix())+
|
|
|
|
|
("[" (constant_expression())? "]")+
|
|
|
|
|
ptr_operator() abstract_declarator() )
|
|
]
|
|
}
|
|
|
|
void abstract_declarator_suffix() :
|
|
{}
|
|
{
|
|
"[" ( constant_expression() )? "]"
|
|
|
|
|
"(" (parameter_list())? ")"
|
|
}
|
|
|
|
void template_head() :
|
|
{}
|
|
{
|
|
"template" "<" template_parameter_list() ">"
|
|
}
|
|
|
|
void template_parameter_list() :
|
|
{}
|
|
{
|
|
template_parameter() ("," template_parameter())*
|
|
}
|
|
|
|
void template_parameter() :
|
|
{ Token t; }
|
|
{
|
|
LOOKAHEAD(3)
|
|
"class" t=<ID> { sym.PutTypeName(t.image); }
|
|
|
|
|
parameter_declaration()
|
|
}
|
|
|
|
void template_id() :
|
|
{}
|
|
{
|
|
<ID> "<" template_argument_list() ">"
|
|
}
|
|
|
|
void template_argument_list() :
|
|
{}
|
|
{
|
|
template_argument() ("," template_argument())*
|
|
}
|
|
|
|
void template_argument() :
|
|
{}
|
|
{
|
|
LOOKAHEAD(3)
|
|
type_name()
|
|
|
|
|
shift_expression()
|
|
}
|
|
|
|
void statement_list() :
|
|
{}
|
|
{
|
|
(LOOKAHEAD(statement()) statement())+
|
|
}
|
|
|
|
void statement() :
|
|
{}
|
|
{
|
|
LOOKAHEAD( declaration() )
|
|
declaration()
|
|
|
|
|
LOOKAHEAD( expression() ";" )
|
|
expression() ";"
|
|
|
|
|
compound_statement()
|
|
|
|
|
selection_statement()
|
|
|
|
|
jump_statement()
|
|
|
|
|
";"
|
|
|
|
|
try_block()
|
|
|
|
|
throw_statement()
|
|
|
|
|
LOOKAHEAD(2)
|
|
labeled_statement()
|
|
|
|
|
iteration_statement()
|
|
}
|
|
|
|
void labeled_statement() :
|
|
{}
|
|
{
|
|
<ID> ":" statement()
|
|
|
|
|
"case" constant_expression() ":" statement()
|
|
|
|
|
"default" ":" statement()
|
|
}
|
|
|
|
void compound_statement() :
|
|
{}
|
|
{
|
|
"{"
|
|
|
|
{ sym.OpenScope(null, false); }
|
|
|
|
(statement_list())?
|
|
|
|
{ sym.CloseScope(); }
|
|
|
|
"}"
|
|
}
|
|
|
|
void selection_statement() :
|
|
{}
|
|
{
|
|
"if" "(" expression() ")" statement()
|
|
(LOOKAHEAD(2) "else" statement())?
|
|
|
|
|
"switch" "(" expression() ")" statement()
|
|
}
|
|
|
|
void iteration_statement() :
|
|
{}
|
|
{
|
|
"while" "(" expression() ")" statement()
|
|
|
|
|
"do" statement() "while" "(" expression() ")" ";"
|
|
|
|
|
"for" "(" (LOOKAHEAD(3) declaration() | expression() ";" | ";")
|
|
(expression())? ";" (expression())? ")" statement()
|
|
}
|
|
|
|
void jump_statement() :
|
|
{}
|
|
{
|
|
"goto" <ID> ";"
|
|
|
|
|
"continue" ";"
|
|
|
|
|
"break" ";"
|
|
|
|
|
"return" (expression())? ";"
|
|
}
|
|
|
|
void try_block() :
|
|
{}
|
|
{
|
|
"try" compound_statement() (handler())*
|
|
}
|
|
|
|
void handler() :
|
|
{}
|
|
{
|
|
"catch" "(" exception_declaration() ")"
|
|
compound_statement()
|
|
|
|
|
"finally" compound_statement()
|
|
}
|
|
|
|
void exception_declaration() :
|
|
{}
|
|
{ parameter_declaration_list()
|
|
|
|
|
"..."
|
|
}
|
|
|
|
void throw_statement() :
|
|
{}
|
|
{ "throw" (assignment_expression())? ";"
|
|
}
|
|
|
|
void expression() :
|
|
{}
|
|
{
|
|
assignment_expression() ( LOOKAHEAD(2) "," assignment_expression())*
|
|
}
|
|
|
|
void assignment_expression() :
|
|
{}
|
|
{
|
|
conditional_expression()
|
|
(("="
|
|
| "*="
|
|
| "/="
|
|
| "%="
|
|
| "+="
|
|
| "-="
|
|
| "<<="
|
|
| ">>="
|
|
| "&="
|
|
| "^="
|
|
| "|="
|
|
)
|
|
assignment_expression()
|
|
)?
|
|
}
|
|
|
|
void conditional_expression() :
|
|
{}
|
|
{ logical_or_expression()
|
|
("?" conditional_expression() ":" conditional_expression())?
|
|
}
|
|
|
|
void constant_expression() :
|
|
{}
|
|
{ conditional_expression()
|
|
}
|
|
|
|
void logical_or_expression() :
|
|
{}
|
|
{ logical_and_expression() ( "||" logical_and_expression())*
|
|
}
|
|
|
|
void logical_and_expression() :
|
|
{}
|
|
{ inclusive_or_expression() ( "&&" inclusive_or_expression())*
|
|
}
|
|
|
|
void inclusive_or_expression() :
|
|
{}
|
|
{ exclusive_or_expression()( "|" exclusive_or_expression())*
|
|
}
|
|
|
|
void exclusive_or_expression() :
|
|
{}
|
|
{ and_expression()( "^" and_expression())*
|
|
}
|
|
|
|
void and_expression() :
|
|
{}
|
|
{ equality_expression()( LOOKAHEAD(2) "&" equality_expression())*
|
|
}
|
|
|
|
void equality_expression() :
|
|
{}
|
|
{ relational_expression()(( "!=" | "==") relational_expression())*
|
|
}
|
|
|
|
void relational_expression() :
|
|
{}
|
|
{ shift_expression()
|
|
(
|
|
LOOKAHEAD(2)
|
|
(
|
|
"<"
|
|
| ">"
|
|
| "<="
|
|
| ">="
|
|
)
|
|
shift_expression()
|
|
)*
|
|
}
|
|
|
|
void shift_expression() :
|
|
{}
|
|
{ additive_expression()(( "<<" | ">>") additive_expression())*
|
|
}
|
|
|
|
void additive_expression() :
|
|
{}
|
|
{ multiplicative_expression()
|
|
(LOOKAHEAD(2) ( "+" | "-") multiplicative_expression())*
|
|
}
|
|
|
|
void multiplicative_expression() :
|
|
{}
|
|
{ pm_expression()
|
|
(LOOKAHEAD(2) ( "*" | "/" | "%") pm_expression())*
|
|
}
|
|
|
|
void pm_expression() :
|
|
{}
|
|
{
|
|
cast_expression() (( ".*" | "->*" ) cast_expression())*
|
|
}
|
|
|
|
void cast_expression() :
|
|
{}
|
|
{
|
|
LOOKAHEAD( "(" type_name() ")" )
|
|
"(" type_name() ")" cast_expression()
|
|
|
|
|
unary_expression()
|
|
}
|
|
|
|
void unary_expression() :
|
|
{}
|
|
{
|
|
"++" unary_expression()
|
|
|
|
|
"--" unary_expression()
|
|
|
|
|
LOOKAHEAD(3)
|
|
unary_operator() cast_expression()
|
|
|
|
|
"sizeof"
|
|
(
|
|
LOOKAHEAD("(")
|
|
"(" type_name() ")"
|
|
|
|
|
unary_expression()
|
|
)
|
|
|
|
|
postfix_expression()
|
|
}
|
|
|
|
void new_expression() :
|
|
{}
|
|
{
|
|
(LOOKAHEAD("::") ("::"))?
|
|
"new"
|
|
(
|
|
LOOKAHEAD("(" type_name() ")" )
|
|
"(" type_name() ")"
|
|
|
|
|
(LOOKAHEAD("(" expression_list() ) "(" expression_list() ")")?
|
|
(
|
|
LOOKAHEAD("(" type_name() ")" )
|
|
"(" type_name() ")"
|
|
|
|
|
LOOKAHEAD(declaration_specifiers())
|
|
new_type_id()
|
|
)
|
|
)
|
|
(LOOKAHEAD(new_initializer()) new_initializer())?
|
|
}
|
|
|
|
void new_type_id() :
|
|
{}
|
|
{
|
|
declaration_specifiers()
|
|
( LOOKAHEAD(new_declarator()) new_declarator() )?
|
|
}
|
|
|
|
void new_declarator() :
|
|
{}
|
|
{
|
|
direct_new_declarator()
|
|
|
|
|
ptr_operator() cv_qualifier_seq() [ LOOKAHEAD(2) new_declarator() ]
|
|
}
|
|
|
|
void direct_new_declarator() :
|
|
{}
|
|
{
|
|
(LOOKAHEAD(2) "[" expression() "]" )+
|
|
}
|
|
|
|
void new_initializer() :
|
|
{}
|
|
{ "(" ( expression_list() )? ")"
|
|
}
|
|
|
|
void delete_expression() :
|
|
{}
|
|
{ ( "::" )? "delete" ( "[" "]" )? cast_expression()
|
|
}
|
|
|
|
void unary_operator() :
|
|
{}
|
|
{ "&"
|
|
| "*"
|
|
| "+"
|
|
| "-"
|
|
| "~"
|
|
| "!"
|
|
}
|
|
|
|
void postfix_expression() :
|
|
{}
|
|
{
|
|
LOOKAHEAD(3)
|
|
primary_expression()
|
|
( LOOKAHEAD(2) (
|
|
"[" expression() "]"
|
|
|
|
|
"(" ( expression_list() )? ")"
|
|
|
|
|
"." id_expression()
|
|
|
|
|
"->" id_expression()
|
|
|
|
|
"++"
|
|
|
|
|
"--" )
|
|
)*
|
|
|
|
|
simple_type_specifier() "(" ( expression_list() )? ")"
|
|
}
|
|
|
|
void id_expression() :
|
|
{}
|
|
{
|
|
(LOOKAHEAD(scope_override_lookahead()) scope_override())?
|
|
( <ID>
|
|
| "operator" optor()
|
|
| "~" <ID>
|
|
)
|
|
}
|
|
|
|
void primary_expression() :
|
|
{}
|
|
{
|
|
"this"
|
|
| ( LOOKAHEAD(2) <STRING> )+
|
|
| "(" expression() ")"
|
|
|
|
|
LOOKAHEAD( ("::")? "new")
|
|
new_expression()
|
|
|
|
|
LOOKAHEAD( ("::")? "delete")
|
|
delete_expression()
|
|
| id_expression()
|
|
| constant()
|
|
}
|
|
|
|
void expression_list() :
|
|
{}
|
|
{ assignment_expression()( "," assignment_expression())*
|
|
}
|
|
|
|
void constant() :
|
|
{}
|
|
{ <OCTALINT>
|
|
| <OCTALLONG>
|
|
| <DECIMALINT>
|
|
| <DECIMALLONG>
|
|
| <HEXADECIMALINT>
|
|
| <HEXADECIMALLONG>
|
|
|
|
| <UNSIGNED_OCTALINT>
|
|
| <UNSIGNED_OCTALLONG>
|
|
| <UNSIGNED_DECIMALINT>
|
|
| <UNSIGNED_DECIMALLONG>
|
|
| <UNSIGNED_HEXADECIMALINT>
|
|
| <UNSIGNED_HEXADECIMALLONG>
|
|
|
|
| <CHARACTER>
|
|
| <FLOATONE>
|
|
| <FLOATTWO>
|
|
| "true"
|
|
| "false"
|
|
}
|
|
|
|
void optor() :
|
|
{}
|
|
{
|
|
"new" [ LOOKAHEAD(2) "[" "]" ]
|
|
| "delete" [ LOOKAHEAD(2) "[" "]" ]
|
|
| "+"
|
|
| "-"
|
|
| "*"
|
|
| "/"
|
|
| "%"
|
|
| "^"
|
|
| "&"
|
|
| "|"
|
|
| "~"
|
|
| "!"
|
|
| "="
|
|
| "<"
|
|
| ">"
|
|
| "+="
|
|
| "-="
|
|
| "*="
|
|
| "/="
|
|
| "%="
|
|
| "^="
|
|
| "&="
|
|
| "|="
|
|
| "<<"
|
|
| ">>"
|
|
| ">>="
|
|
| "<<="
|
|
| "=="
|
|
| "!="
|
|
| "<="
|
|
| ">="
|
|
| "&&"
|
|
| "||"
|
|
| "++"
|
|
| "--"
|
|
| ","
|
|
| "->*"
|
|
| "->"
|
|
| "(" ")"
|
|
| "[" "]"
|
|
| declaration_specifiers() (LOOKAHEAD(2) ("*"|"&"))?
|
|
}
|
|
|
|
void exception_spec() :
|
|
{}
|
|
{
|
|
"throw" "(" exception_list() ")"
|
|
}
|
|
|
|
void exception_list() :
|
|
{}
|
|
{
|
|
type_name() ( "," type_name())*
|
|
}
|
|
|
|
/*end*/
|