translation_unit ::= => { global tableOfMacros; } #ignore(preprocessing) #continue [declaration_seq(this.translation_unit, this.translation_unit)]? #empty; //------------------------- // Preprocessing directives //------------------------- preprocessing ::= [ ' ' | '\t' | '\r' | '\n' | "//" #continue ->"\n" | "/*" #continue -> "*/" | '#' #ignore(preprocessor_blanks) #continue #readIdentifier:sDirective preprocessor_directive | #readIdentifier:sMacro #check(findElement(sMacro, tableOfMacros)) macro_expansion(sMacro) ]*; preprocessor_blanks ::= [' ' | '\t' | '\r' | "//" [~"\n"]* | "/*" -> "*/"]*; preprocessor_directive<"if"> ::= #continue => local bResult; preprocessor_expression(bResult); [ #check(bResult) | preprocessor_ignore_group(true); ]; preprocessor_directive<"ifdef"> ::= #continue #readIdentifier:sIdentifier [ #check(findElement(sIdentifier, this.preprocessor.defines)) | preprocessor_ignore_group(true) ]; preprocessor_directive<"ifndef"> ::= #continue #readIdentifier:sIdentifier [ #check(!findElement(sIdentifier, this.preprocessor.defines)) | preprocessor_ignore_group(true) ]; preprocessor_directive<"elif"> ::= preprocessor_ignore_group(false); preprocessor_directive<"else"> ::= preprocessor_ignore_group(false); preprocessor_directive<"endif"> ::= preprocessor_ignore_group(false); preprocessor_ignore_group(bValidate : value) ::= => local sDirective; #continue ->['#' #readIdentifier:{"if, "ifdef", "ifndef", "elif", "else, "endif"}] [ #check(startString(sDirective, "if")) preprocessor_ignore_group(false) | #check(sIdentifier == "else") [ #check(bValidate) | preprocessor_ignore_group(false) ] | #check(sIdentifier == "elif") [ #check(bValidate) => local bResult; preprocessor_expression(bResult); [ #check(bResult) | preprocessor_ignore_group(false) ] | preprocessor_ignore_group(false) ] | #check(sIdentifier == "endif") ]; preprocessor_expression(bResult : node) ::= => local pExpr; constant_expression("preprocessor", pExpr, bResult); preprocessing_file ::= [group]?; group ::= [group_part]+; group_part ::= [pp_tokens]? new_line | if_section | control_line; if_section ::= if_group [elif_group]* [else_group]? endif_line; if_group ::= [ #readIdentifier:"if" #continue constant_expression | #readIdentifier:"ifdef" #continue identifier | #readIdentifier:"ifndef" #continue identifier ] new_line [group]?; elif_group ::= '#' #readIdentifier:"elif" #continue constant_expression new_line [group]?; else_group ::= '#' #readIdentifier:"else" #continue new_line [group]?; endif_line ::= '#' #readIdentifier:"endif" #continue new_line; control_line ::= '#' [ #readIdentifier:"include" pp_tokens new_line | #readIdentifier:"define" identifier replacement_list new_line | #readIdentifier:"define" identifier lparen [identifier_list]? ')' replacement_list new_line | #readIdentifier:"undef" identifier new_line | #readIdentifier:"line" pp_tokens new_line | #readIdentifier:"error" [pp_tokens]? new_line | #readIdentifier:"pragma" [pp_tokens]? new_line | new_line ]; lparen : #!ignore ::= '('; //the left-parenthesis character without preceding white-space replacement_list ::= [pp_tokens]?; pp_tokens ::= [preprocessing_token]+; // the new-line character, ignoring all comments up to the end of the line new_line : #!ignore ::= [['\t' | ' ']* "/*" [~"*/" #continue ~'\n']*]* ['\t' | ' ']* ["//" ->'\n' | ['\r']? '\n']; //------------------------- // Lexical conventions //------------------------- hex_quad ::= [hexadecimal_digit]4; universal_character_name ::= "\\u" hex_quad | "\\U" hex_quad hex_quad; preprocessing_token ::= header_name | identifier | pp_number | character_literal | string_literal | preprocessing_op_or_punc | ~['\t' | ' ' | '\r' | '\n']; // each non-white-space character that cannot be one of the above token ::= identifier | keyword | literal | operator | punctuator; header_name ::= '<' h_char_sequence '>' | '\"' q_char_sequence '\"'; h_char_sequence ::= [h_char]+; h_char ::= ~['\r' | '\n' | '>']; // any member of the source character set except new-line and '>' q_char_sequence ::= [q_char]+; q_char ::= ~['\r' | '\n' | '\"']; // any member of the source character set except new-line and '"' pp_number ::= => local iDigits = 0; [digit => increment(iDigits);]* ['.']? [digit => increment(iDigits);] #check($iDigits > 0$) [['e' |'E'] ['+' | '-']? digit_sequence]?; identifier ::= nondigit [nondigit | digit]*; nondigit ::= '_' | 'a'..'z' | 'A'..'Z'; // one of universal_character_name digit ::= '0'..'9'; preprocessing_op_or_punc ::= '{' | '}' | '[' | ']' | '#' | "##" | '(' | ')' | "<:" | ":>" | "<%" | "%>" | "%:" | "%:%:" | ';' | ':' | "..." | #readIdentifier:{"new", "delete"} | '?' | "::" | '.' | ".*" | '+' | '-' | '*' | '/' | '%' | '^' | '&' | '|' | '~' | '!' | '=' | '<' | '>' | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=" | "<<" | ">>" | ">>=" | "<<=" | "==" | "!=" | "<=" | ">=" | "&&" | "||" | "++" | "--" | ',' | "->*" | "->" | #readIdentifier:{"and", "and_eq", "bitand", "bitor", "compl", "not", "not_eq", "or", "or_eq"} | #readIdentifier:{"xor", "xor_eq"}; //------------------------- // Literals //------------------------- literal(source : value, expr : node, bResult : node) ::= integer_literal(source, expr, bResult) | character_literal(source, expr, bResult) | floating_literal(source, expr, bResult) | string_literal(source, expr, bResult) | boolean_literal(source, expr, bResult); integer_literal(source : value, expr : node, bResult : node) ::= #!ignore [ decimal_literal(source, expr, bResult) | hexadecimal_literal(source, expr, bResult) | octal_literal(source, expr, bResult) ] [integer_suffix(expr)]?; decimal_literal(source : value, expr : node, bResult : node) ::= nonzero_digit:iDigit [digit]*:iNumber => set bResult = iDigit + iNumber; => insert expr.operator = "integer decimal"; => insert expr.value = bResult; ; octal_literal(source : value, expr : node, bResult : node) ::= '0' [octal_digit]*:bResult => insert expr.operator = "integer octal"; => insert expr.value = "0" + bResult; => if source == "preprocessor" set bResult = octalToDecimal(bResult); ; hexadecimal_literal(source : value, expr : node, bResult : node) ::= ["0x" | "0x"] #continue [hexadecimal_digit]+:bResult => insert expr.operator = "integer hexa"; => insert expr.value = "0x" + bResult; => if source == "preprocessor" set bResult = hexaToDecimal(bResult); ; nonzero_digit ::= '1'..'9'; octal_digit ::= '0'..'7'; hexadecimal_digit ::= '0'..'9' | 'a'..'f' | 'A'..'F'; integer_suffix(expr : node) ::= unsigned_suffix(expr) [long_suffix(expr)]? | long_suffix(expr) [unsigned_suffix(expr)]?; unsigned_suffix(expr : node) ::= ['u' | 'U'] => { insert expr.unsigned = true; } ; long_suffix(expr : node) ::= ['l' | 'L'] => { insert expr.long = true; } ; character_literal(source : value, expr : node, bResult : node) ::= => local bWide; ['L' => set bWide = true;]? '\'' #!ignore #continue => insert expr.operator = "character"; c_char_sequence:expr.value => if source == "preprocessor" set bResult = "'" + expr.value + "'"; => if bWide insert expr.wide = true; '\''; c_char_sequence ::= [c_char]+; c_char ::= ~['\'' | '\\' | '\r' | '\n'] | escape_sequence | universal_character_name; escape_sequence ::= simple_escape_sequence | octal_escape_sequence | hexadecimal_escape_sequence; simple_escape_sequence ::= "\\'" | "\\\"" | "\\?" | "\\a" | "\\b" | "\\f" | "\\n" | "\\r" | "\\t" | "\\v"; octal_escape_sequence ::= '\\' [octal_digit]1..3; hexadecimal_escape_sequence ::= "\\x" [hexadecimal_digit]+; floating_literal(source : value, expr : node, bResult : node) ::= fractional_constant(source, expr, bResult) [exponent_part(source, expr, bResult)]? [floating_suffix(source, expr, bResult)]?; fractional_constant(source : value, expr : node, bResult : node) ::= #!ignore => local iDigits = 0; [digit => increment(iDigits);]*:sLeft ['.' [digit => increment(iDigits);]* ]?:sRight #check($iDigits > 0$) => if source == "preprocessor" set bResult = sLeft + sRight; => insert expr.operator = "floating-point"; => insert expr.fractional_constant = sLeft + sRight; ; exponent_part(source : value, expr : node, bResult : node) ::= ['e' | 'E'] #continue #!ignore [sign:expr.exponent]? digit_sequence:sExponent => insert expr.exponent += sExponent; => if source == "preprocessor" set bResult += "E" + expr.exponent; ; sign ::= '+' | '-'; digit_sequence ::= [digit]+; floating_suffix(source : value, expr : node, bResult : node) ::= [ ['f' | 'F'] => insert expr.suffix = "F"; | ['l' | 'L'] => insert expr.suffix = "L"; ] => if source == "preprocessor" set bResult += expr.suffix; ; string_literal(source : value, expr : node, bResult : node) ::= => local bWide; ['L' => set bWide = true;]? '\"' #continue #!ignore => insert expr.operator = "string"; [s_char_sequence:expr.value]? '\"' => if source == "preprocessor" set bResult = "\"" + expr.value + "\""; => if bWide insert expr.wide = true; ; s_char_sequence ::= [s_char]+; s_char ::= ~['\'' | '\\' | '\r' | '\n'] | escape_sequence | universal_character_name; boolean_literal(source : value, expr : node, bResult : node) ::= #readIdentifier:{"false", "true"}:expr.value => if source == "preprocessor" set bResult = expr.value; => insert expr.operator = "boolean"; ; //------------------------- // Expressions //------------------------- primary_expression(source : value, scope : node, expr : node, bResult : node) ::= literal(source, expr, bResult) | #readIdentifier:"this" => insert expr.operator = "this"; | '(' expression(source, scope, expr, bResult) ')' | id_expression(source, scope, expr, bResult); id_expression ::= unqualified_id | qualified_id; unqualified_id ::= identifier | operator_function_id | conversion_function_id | '~' class_name | template_id; qualified_id ::= ["::"]? nested_name_specifier [template]? unqualified_id | "::" [identifier | operator_function_id | template_id]; nested_name_specifier ::= class_or_namespace_name "::" [ #readIdentifier:"template" nested_name_specifier | [nested_name_specifier]? ]; class_or_namespace_name(scope : node, expr : node) ::= class_name(scope, expr) | namespace_name(scope, expr); postfix_expression(source : value, scope : node, scope : node, expr : node, bResult : node) ::= [ primary_expression(source, scope, expr, bResult) | simple_type_specifier '(' [expression_list]? ')' | #readIdentifier:"typename" ["::"]? nested_name_specifier identifier '(' [expression_list]? ')' | #readIdentifier:"typename" ["::"]? nested_name_specifier [#readIdentifier:"template"]? template_id '(' [expression_list]? ')' | #readIdentifier:{"dynamic_cast", "static_cast", "reinterpret_cast", "const_cast"} '<' type_id '>' '(' expression ')' | #readIdentifier:"typeid" '(' [expression | type_id] ')' ] [ '[' expression ']' | '(' [expression_list]? ')' | ['.' | "->"] [#readIdentifier:"template"]? ["::"]? id_expression | ['.' | "->"] pseudo_destructor_name | "++" | "--" ]*; expression_list(source : value, scope : node, scope : node, expr : node, bResult : node) ::= assignment_expression(source, scope, expr, bResult) [',' #continue assignment_expression(source, scope, expr, bResult)]*; pseudo_destructor_name ::= ["::"]? [nested_name_specifier]? [type_name "::"]? '~' type_name | ["::"]? nested_name_specifier #readIdentifier:"template" template_id "::" '~' type_name; unary_expression(source : value, scope : node, expr : node, bResult : node) ::= ["++" | "--" | unary_operator]:sOperator => local pExpr; cast_expression(source, scope, pExpr, bResult) => insert expr.operator = "unary" + sOperator; => setall expr.expression = pExpr; | #readIdentifier:"sizeof" => insert expr.operator = "sizeof"; [ unary_expression(source, scope, expr.expression, bResult) | '(' type_id(scope, expr.type) ')' ] | new_expression(scope, expr) | delete_expression(scope, expr) | postfix_expression(source, scope, expr, bResult); unary_operator ::= '*' | '&' | '+' | '-' | '!' | '~'; new_expression(scope : node, expr : node) ::= ["::"]? #readIdentifier:"new" #continue => insert expr.operator = "new"; [new_placement(scope, expr)]? [ '(' #continue type_id(scope, expr.type) ')' | [new_type_id(scope, expr.type)]? ] [new_initializer(scope, expr)]?; new_placement(scope : node, expr : node) ::= '(' #continue => pushItem expr.placements; => local bResult; assignment_expression("", scope, expr.placements#back, bResult) [ ',' #continue => pushItem expr.placements; assignment_expression("", scope, expr.placements#back, bResult) ]* ')'; new_type_id(scope : node, expr : node) ::= type_specifier_seq(scope, expr) [new_declarator(scope, expr)]?; new_declarator(scope : node, expr : node) ::= ptr_operator(scope, expr) [new_declarator(scope, expr)]? | direct_new_declarator(scope, expr); direct_new_declarator(scope : node, expr : node) ::= '[' #continue => pushItem expr.dimensions; => local bResult; assignment_expression("", scope, expr.dimensions#back, bResult) ']' [ '[' #continue => pushItem expr.dimensions; constant_expression("", scope, expr.dimensions#back, bResult) ']' ]*; new_initializer(scope : node, expr : node) ::= '(' #continue [ => local pExpr; => local bResult; assignment_expression("", scope, pExpr, bResult) => pushItem expr.initializers; => setall expr.initializers#back = pExpr; [ ',' #continue => pushItem expr.initializers; assignment_expression("", scope, expr.initializers#back, bResult) ]* ]? ')'; delete_expression(scope : node, expr : node) ::= ["::"]? #readIdentifier:"delete" #continue => insert expr.operator = "delete"; ['[' #continue ']' => insert expr.array = true;]? => local bResult; cast_expression("", scope, expr.expression, bResult); cast_expression(source : value, scope : node, expr : node, bResult : node) ::= unary_expression(source, scope, expr, bResult) | '(' type_id(scope, pExpr) ')' #continue => insert expr.operator = "cast"; => setall expr.type = pExpr; cast_expression(source, scope, expr.expression, bResult); pm_expression(source : value, scope : node, expr : node, bResult : node) ::= cast_expression(source, scope, expr, bResult) [ [".*" | "->*"]:sOperator #continue => slideNodeContent(expr, left); cast_expression(source, scope, expr.right, bResult) => insert expr.operator = sOperator; ]*; multiplicative_expression(source : value, scope : node, expr : node, bResult : node) ::= pm_expression(source, scope, expr, bResult) [ ['*' | '/' | '%']:sOperator #continue => slideNodeContent(expr, left); pm_expression(source, scope, expr.right, bResult) => insert expr.operator = sOperator; ]*; additive_expression(source : value, scope : node, expr : node, bResult : node) ::= multiplicative_expression(source, scope, expr, bResult) [ ["+" | "-"]:sOperator #continue => slideNodeContent(expr, left); multiplicative_expression(source, scope, expr.right, bResult) => insert expr.operator = sOperator; ]*; shift_expression(source : value, scope : node, expr : node, bResult : node) ::= additive_expression(source, scope, expr, bResult) [ ["<<" | ">>"]:sOperator #continue => slideNodeContent(expr, left); additive_expression(source, scope, expr.right, bResult) => insert expr.operator = sOperator; ]*; relational_expression(source : value, scope : node, expr : node, bResult : node) ::= shift_expression(source, scope, expr, bResult) [ ['<' | '>' | "<=" | ">="]:sOperator #continue => slideNodeContent(expr, left); shift_expression(source, scope, expr.right, bResult) => insert expr.operator = sOperator; ]*; equality_expression(source : value, scope : node, expr : node, bResult : node) ::= relational_expression(source, scope, expr, bResult) [ ["==" | "!="]:sOperator #continue => slideNodeContent(expr, left); relational_expression(source, scope, expr.right, bResult) => insert expr.operator = sOperator; ]*; and_expression(source : value, scope : node, expr : node, bResult : node) ::= equality_expression(source, scope, expr, bResult) [ "&" #continue => slideNodeContent(expr, left); equality_expression(source, scope, expr.right, bResult) => insert expr.operator = "&"; ]*; exclusive_or_expression(source : value, scope : node, expr : node, bResult : node) ::= and_expression(source, scope, expr, bResult) [ "^" #continue => slideNodeContent(expr, left); and_expression(source, scope, expr.right, bResult) => insert expr.operator = "^"; ]*; inclusive_or_expression(source : value, scope : node, expr : node, bResult : node) ::= exclusive_or_expression(source, scope, expr, bResult) [ "|" #continue => slideNodeContent(expr, left); exclusive_or_expression(source, scope, expr.right, bResult) => insert expr.operator = "|"; ]*; logical_and_expression(source : value, scope : node, expr : node, bResult : node) ::= inclusive_or_expression(source, scope, expr, bResult) [ "&&" #continue => slideNodeContent(expr, left); inclusive_or_expression(source, scope, expr.right, bResult) => insert expr.operator = "&&"; ]*; logical_or_expression(source : value, scope : node, expr : node, bResult : node) ::= logical_and_expression(source, scope, expr, bResult) [ "||" #continue => slideNodeContent(expr, left); logical_and_expression(source, scope, expr.right, bResult) => insert expr.operator = "||"; ]*; conditional_expression(source : value, scope : node, expr : node, bResult : node) ::= logical_or_expression(source, scope, expr, bResult) [ '?' #continue => slideNodeContent(expr, condition); => insert expr.operator = "?"; expression(source, scope, expr.left, bResult) ':' assignment_expression(source, scope, expr.right, bResult) ]?; assignment_expression(source : value, scope : node, expr : node, bResult : node) ::= logical_or_expression(source, scope, expr, bResult) [ assignment_operator:sOperator #continue => slideNodeContent(expr, left); assignment_expression(source, scope, expr.right, bResult) => insert expr.operator = sOperator; ]? | throw_expression(scope, expr); assignment_operator ::= ">=" | "*=" | "/=" | "%=" | "+=" | "-=" | ">>=" | "<<=" | "&=" | "^=" | "|="; expression(source : value, scope : node, expr : node, bResult : node) ::= assignment_expression(source, scope, expr, bResult) [ ',' #continue => slideNodeContent(expr, left); assignment_expression(source, scope, expr.right, bResult) => insert expr.operator = ","; ]*; constant_expression(source : value, scope : node, expr : node, bResult : node) ::= conditional_expression(source, scope, expr, bResult); //------------------------- // Statements //------------------------- statement(scope : node, stmt : node) ::= labeled_statement(scope, stmt) | compound_statement(scope, stmt) | selection_statement(scope, stmt) | iteration_statement(scope, stmt) | jump_statement(scope, stmt) | declaration_statement(scope, stmt) | try_block(scope, stmt) | expression_statement(scope, stmt); labeled_statement(scope : node, stmt : node) ::= identifier:sIdentifier ':' #continue => insert stmt.type = "label"; => insert stmt.label = sIdentifier; statement(scope, stmt.statement) | #readIdentifier:"case" #continue => local bResult; constant_expression(scope, stmt.expression, bResult) => insert stmt.type = "case"; ':' statement(scope, stmt.statement) | #readIdentifier:"default" #continue ':' => insert stmt.type = "default"; statement(scope, stmt.statement); expression_statement(scope : node, stmt : node) ::= [ => local bResult; expression(scope, stmt.expression, bResult) => insert stmt.type = "expression"; ]? ';'; compound_statement(scope : node, stmt : node) ::= '{' #continue [ statement_seq(scope, stmt) => insert stmt.type = "compound"; ]? '}'; statement_seq(scope : node, stmt : node) ::= [ => pushItem stmt.statements; statement(scope, stmt.statements#back) ]+ => removeLastElement(stmt.statements); | => removeVariable(stmt.statements); #check(false); selection_statement(scope : node, stmt : node) ::= #readIdentifier:"if" #continue '(' condition(scope, stmt.condition) ')' statement(scope, stmt.then) [ #readIdentifier:"else" #continue statement(scope, stmt.else) ]? => insert stmt.type = "if"; | #readIdentifier:"switch" #continue '(' condition(scope, stmt.condition) ')' statement(scope, stmt.switch) => insert stmt.type = "switch"; ; condition(scope : node, stmt : node) ::= => local pExpr; => local bResult; expression("", scope, pExpr, bResult) => setall stmt = pExpr; | type_specifier_seq declarator '=' assignment_expression; iteration_statement(scope : node, stmt : node) ::= #readIdentifier:"while" #continue '(' condition(scope, stmt.condition) ')' statement(scope, stmt.while) => insert stmt.type = "while"; | #readIdentifier:"do" #continue statement(scope, stmt.do) #readIdentifier:"while" '(' => local bResult; expression("", scope, stmt.condition, bResult) ')' ';' => insert stmt.type = "do"; | #readIdentifier:"for" #continue '(' for_init_statement(scope, stmt.init) [ => local pStmt; condition(scope, pStmt) => setall stmt.condition = pStmt; ]? ';' [ => local pExpr; => local bResult; expression("", scope, pExpr, bResult) => setall stmt.iteration = pExpr; ]? ')' statement(scope, stmt.for) => insert stmt.type = "for"; ; for_init_statement(scope : node, stmt : node) ::= expression_statement(scope, stmt) | simple_declaration; jump_statement(scope : node, stmt : node) ::= #readIdentifier:{"break", "continue"}:stmt.type #continue ';' | #readIdentifier:"return":stmt.type #continue [ => local pExpr; => local bResult; expression("", scope, pExpr, bResult) => setall stmt.return = pExpr; ]? ';' | #readIdentifier:"goto":stmt.type #continue identifier:stmt.goto ';'; declaration_statement(scope : node, stmt : node) ::= block_declaration(scope, stmt); //------------------------- // Declarations //------------------------- declaration_seq(scope : node, stmt : node) ::= [ pushItem stmt.declarations; declaration(scope, stmt.declarations#back) | removeLastElement(stmt.declarations); ]+ => insert stmt.type = "declaration_seq"; | removeVariable(stmt.declarations); declaration(scope : node, stmt : node) ::= block_declaration(scope, stmt) | function_definition(scope, stmt) | template_declaration(scope, stmt) | explicit_instantiation(scope, stmt) | explicit_specialization(scope, stmt) | linkage_specification(scope, stmt) | namespace_definition(scope, stmt); block_declaration(scope : node, stmt : node) ::= simple_declaration(scope, stmt) | asm_definition(scope, stmt) | namespace_alias_definition(scope, stmt) | using_declaration(scope, stmt) | using_directive(scope, stmt); simple_declaration(scope : node, stmt : node) ::= [decl_specifier_seq(scope, stmt)]? [init_declarator_list(scope, stmt)]? ';'; decl_specifier(scope : node, stmt : node) ::= storage_class_specifier(scope, stmt) | type_specifier(scope, stmt) | function_specifier(scope, stmt) | #readIdentifier:"friend" => insert stmt.type = "friend"; decl_specifier_seq(scope, stmt.specifier) | #readIdentifier:"typedef" => insert stmt.type = "typedef"; decl_specifier_seq(scope, stmt.specifier); decl_specifier_seq(scope : node, stmt : node) ::= [ => pushItem stmt.specifiers; decl_specifier(scope, stmt.specifiers) ]+ => removeLastElement(stmt.specifiers) | => removeVariable(stmt.specifiers); ; storage_class_specifier ::= #readIdentifier:{"auto", "register", "static", "extern", "mutable"}; function_specifier ::= #readIdentifier:{"inline", "virtual", "explicit"}; typedef_name ::= identifier; type_specifier ::= simple_type_specifier | class_specifier | enum_specifier | elaborated_type_specifier | cv_qualifier; simple_type_specifier ::= ["::"]? [nested_name_specifier]? type_name | ["::"]? nested_name_specifier #readIdentifier:"template" template_id | #readIdentifier:{"char", "wchar_t", "bool", "short", "int", "long", "signed", "unsigned", "float", "double", "void"}; type_name ::= class_name | enum_name | typedef_name; elaborated_type_specifier ::= class_key ["::"]? [nested_name_specifier]? identifier | #readIdentifier:"enum" ["::"]? [nested_name_specifier]? identifier | #readIdentifier:"typename" ["::"]? nested_name_specifier identifier [[#readIdentifier:"template"]? template_id]?; enum_name ::= identifier; enum_specifier ::= #readIdentifier:"enum" [identifier]? '{' [enumerator_list]? '}'; enumerator_list ::= enumerator_definition [',' enumerator_definition]*; enumerator_definition ::= enumerator ['=' constant_expression]?; enumerator ::= identifier; namespace_name ::= original_namespace_name | namespace_alias; original_namespace_name ::= identifier; namespace_definition ::= named_namespace_definition | unnamed_namespace_definition; named_namespace_definition ::= original_namespace_definition | extension_namespace_definition; original_namespace_definition ::= #readIdentifier:"namespace" identifier '{' namespace_body '}'; extension_namespace_definition ::= #readIdentifier:"namespace" original_namespace_name '{' namespace_body '}'; unnamed_namespace_definition ::= #readIdentifier:"namespace" '{' namespace_body '}'; namespace_body ::= [declaration_seq]?; namespace_alias ::= identifier; namespace_alias_definition ::= #readIdentifier:"namespace" identifier '=' qualified_namespace_specifier ';'; qualified_namespace_specifier ::= ["::"]? [nested_name_specifier]? namespace_name; using_declaration ::= #readIdentifier:"using" [#readIdentifier:"typename"]? ["::"]? nested_name_specifier unqualified_id ';' | #readIdentifier:"using" "::" unqualified_id ';'; using_directive ::= #readIdentifier:"using" #readIdentifier:"namespace" ["::"]? [nested_name_specifier]? namespace_name ';'; asm_definition(scope : node, stmt : node) ::= #readIdentifier:"asm" #continue => insert stmt.type = "asm"; '(' string_literal:stmt.asm ')' ';'; linkage_specification(scope : node, stmt : node) ::= #readIdentifier:"extern" #continue => insert stmt.type = "extern"; string_literal:stmt.extern [ '{' [declaration_seq(scope, stmt)]? '}' | declaration(scope, stmt.declarations[0]) ]; //------------------------- // Declarators //------------------------- init_declarator_list ::= init_declarator [',' init_declarator]*; init_declarator ::= declarator [initializer]?; declarator ::= direct_declarator | ptr_operator declarator; direct_declarator ::= [declarator_id | '(' declarator ')'] [ '(' parameter_declaration_clause ')' [cv_qualifier_seq]? [exception_specification]? | '[' [constant_expression]? ']' ] ; ptr_operator ::= '*' [cv_qualifier_seq]? | '&' | ["::"]? nested_name_specifier '*' [cv_qualifier_seq]?; cv_qualifier_seq ::= cv_qualifier [cv_qualifier_seq]?; cv_qualifier ::= #readIdentifier:{"const", "volatile"}; declarator_id ::= ["::"]? id_expression | ["::"]? [nested_name_specifier]? type_name; type_id ::= type_specifier_seq [abstract_declarator]?; type_specifier_seq ::= [type_specifier]+; abstract_declarator ::= ptr_operator [abstract_declarator]? | direct_abstract_declarator; direct_abstract_declarator ::= [direct_abstract_declarator]? '(' parameter_declaration_clause ')' [cv_qualifier_seq]? [exception_specification]? | [direct_abstract_declarator]? '[' [constant_expression]? ']' | '(' abstract_declarator ')'; parameter_declaration_clause ::= parameter_declaration_list [',' "..."] | ["..."]?; parameter_declaration_list ::= parameter_declaration [',' parameter_declaration]?; parameter_declaration ::= decl_specifier_seq [declarator | [abstract_declarator]?] ['=' assignment_expression]?; function_definition ::= [decl_specifier_seq]? declarator [ctor_initializer]? function_body | [decl_specifier_seq]? declarator function_try_block; function_body ::= compound_statement; initializer ::= '=' initializer_clause | '(' expression_list ')'; initializer_clause ::= assignment_expression | '{' [initializer_list [',']?]? '}'; initializer_list ::= initializer_clause [',' initializer_clause]?; //------------------------- // Classes //------------------------- class_name(scope : node, expr : node) ::= template_id(scope, expr) | identifier:sIdentifier #check(existClass(scope, sIdentifier)) => insert expr.type = "class"; => insert expr.class = sIdentifier; ; class_specifier ::= class_head '{' #continue [member_specification]? '}'; class_head ::= class_key [identifier]? [base_clause]? | class_key nested_name_specifier identifier [base_clause]? | class_key [nested_name_specifier]? template_id [base_clause]?; class_key ::= #readIdentifier:{"class", "struct", "union"}; member_specification ::= member_declaration [member_specification] | access_specifier ':' [member_specification]?; member_declaration ::= [decl_specifier_seq]? [member_declarator_list]? ';' | function_definition [';']? | ["::"]? nested_name_specifier [#readIdentifier:"template"]? unqualified_id ';' | using_declaration | template_declaration; member_declarator_list ::= member_declarator [',' member_declarator]*; member_declarator ::= declarator [pure_specifier | constant_initializer]? | [identifier]? ':' constant_expression; pure_specifier ::= '=' '0'; constant_initializer ::= '=' constant_expression; //------------------------- // Derived classes //------------------------- base_clause ::= ':' base_specifier_list; base_specifier_list ::= base_specifier [',' base_specifier]*; base_specifier ::= ["::"]? [nested_name_specifier]? class_name | #readIdentifier:"virtual" [access_specifier]? ["::"]? [nested_name_specifier]? class_name | access_specifier [#readIdentifier:"virtual"]? ["::"]? [nested_name_specifier]? class_name; access_specifier ::= #readIdentifier:{"private", "protected", "public"}; //------------------------- // Special member //------------------------- // functions: // ---------- conversion_function_id ::= #readIdentifier:"operator" conversion_type_id; conversion_type_id ::= type_specifier_seq [conversion_declarator]?; conversion_declarator ::= ptr_operator [conversion_declarator]?; ctor_initializer ::= ':' mem_initializer_list; mem_initializer_list ::= mem_initializer [',' mem_initializer]*; mem_initializer ::= mem_initializer_id '(' [expression_list]? ')'; mem_initializer_id ::= ["::"]? [nested_name_specifier]? class_name | identifier; //------------------------- // Overloading //------------------------- operator_function_id ::= #readIdentifier:"operator" operator; operator ::= #readIdentifier:{"new", "delete"} ['[' ']']? | #readChar:{"+", "-", "*", "/", "%", "^", "&", "|", "~", "!", "=", "<", ">"} | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=" | "&&" | ">>" | ">>=" | "<<" | "<<=" | "==" | "!=" | "<=" | ">=" | "&&" | "||" | "++" | "--" | "->*" | "->" | ',' | '[' ']' | '(' ')'; //------------------------- // Templates //------------------------- template_declaration ::= [#readIdentifier:"export"]? #readIdentifier:"template" '<' #continue template_parameter_list '>' declaration; template_parameter_list ::= template_parameter [',' template_parameter]*; template_parameter ::= type_parameter | parameter_declaration; type_parameter ::= #readIdentifier:"class" [identifier]? ['=' type_id]? | #readIdentifier:"typename" [identifier]? ['=' type_id]? | #readIdentifier:"template" '<' template_parameter_list '>' #readIdentifier:"class" [identifier]? ['=' id_expression]?; template_id(scope : node, expr : node) ::= template_name(scope, expr) '<' #continue [template_argument_list]? '>'; template_name(scope : node, expr : node) ::= identifier:sIdentifier #check(existTemplate(scope, sIdentifier)) ; template_argument_list ::= template_argument [',' template_argument]*; template_argument ::= assignment_expression | type_id | id_expression; explicit_instantiation ::= #readIdentifier:"template" declaration; explicit_specialization ::= #readIdentifier:"template" '<' '>' declaration; //------------------------- // Exception handling //------------------------- try_block ::= #readIdentifier:"try" compound_statement [handler]+; function_try_block ::= #readIdentifier:"try" [ctor_initializer]? function_body; handler ::= #readIdentifier:"catch" #continue '(' exception_declaration ')' compound_statement; exception_declaration ::= type_specifier_seq [declarator | abstract_declarator]? | "..."; throw_expression(scope : node, expr : node) ::= #readIdentifier:"throw" => local pExpr; => local bResult; [ assignment_expression("", scope, pExpr, bResult) => setall expr.expression = pExpr; ]? => insert expr.operator = "throw"; ; exception_specification ::= #readIdentifier:"throw" #continue '(' [type_id_list]? ')'; type_id_list ::= type_id [',' type_id]*;