diff options
author | Adrian Thurston <thurston@complang.org> | 2015-01-23 17:01:07 -0500 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2015-01-23 17:01:07 -0500 |
commit | 72a8d8a9dd19453db5764a8c11e8f5e1c5a4f351 (patch) | |
tree | 45f1f8142fdfe36ef19013f2d0a6d8227717545d /test/lookup1.lm | |
parent | 92da67efa0e2d0f6c7858bd35d4e1bbad61d1e3b (diff) | |
download | colm-72a8d8a9dd19453db5764a8c11e8f5e1c5a4f351.tar.gz |
revert "moved away the larger grammars for known langs"
This reverts commit 04a32202c1aae4a1c69539ce7dd21dff3a93c7fb.
Diffstat (limited to 'test/lookup1.lm')
-rw-r--r-- | test/lookup1.lm | 2594 |
1 files changed, 2594 insertions, 0 deletions
diff --git a/test/lookup1.lm b/test/lookup1.lm new file mode 100644 index 00000000..38902582 --- /dev/null +++ b/test/lookup1.lm @@ -0,0 +1,2594 @@ + +context lookup + struct list_lang_object_el + Obj: lang_object + list_el el + end + + alias list_lang_object + list<list_lang_object_el> + + alias list_declaration_data + list<declaration_data> + + alias list_declarator_data + list<declarator_data> + + struct list_int_el + Int: int + list_el el + end + + alias list_int + list<list_int_el> + + struct map_list_lang_object_el + List: list_lang_object + map_el<str> el + end + + alias map_list_lang_object + map<str map_list_lang_object_el> + + # + # Data types for global data. + # + + # Language objects. + struct lang_object + typeId: int + name: str + + # If the object is a typedef, this points to the real object. + typedefOf: lang_object + + objectMap: map_list_lang_object + inherited: list_lang_object + lookupParent: lang_object + specializationOf: lang_object + end + + # This structure is used to keep track of information necessary to make a + # declaration. While parsing a declaration it records the declaration's + # attributes. + struct declaration_data + isTypedef: int + isFriend: int + isTemplate: int + + typeObj: lang_object + + list_el el + end + + struct declarator_data + qualObj: lang_object + pdcScope: lang_object + lookupObj: lang_object + + list_el el + end + + # Constants for language object types. + NamespaceType: int + ClassType: int + TemplateClassType: int + EnumType: int + IdType: int + TypedefType: int + TemplateIdType: int + + # + # Global data declarations + # + + # Object stacks. + curNamespace: list_lang_object + declNs: list_lang_object + lookupNs: list_lang_object + qualNs: list_lang_object + templateParamNs: list_lang_object + + # Declaration, declarator data. + declarationData: list_declaration_data + declaratorData: list_declarator_data + + # Template declarations + templDecl: list_int + + # Root namespace object + rootNamespace: lang_object + + # + # Identifier lookup. + # + + # Lookup the token in the members of an object. + lang_object lookupInObject( obj: lang_object name: str ) + { + # LOG print( ' looking in ', obj->name, '\n' ) + + ol: map_list_lang_object_el = obj->objectMap->find( name ) + if ol { + # LOG print( ' * found an object: ', ol.head, '\n' ) + return ol->List->head->Obj + } + + return nil + } + + # Lookup in an object and all the objects beneath it in the inheritance + # tree. + lang_object lookupWithInheritance( obj: lang_object name: str ) + { + found: lang_object = lookupInObject( obj name ) + if found + return found + + localObjInherited: list_lang_object = obj->inherited + II: list_lang_object_el = localObjInherited->head + while II { + inh: lang_object = II->Obj + + # First check if the inherited object is the one we are after. + if inh->name == name && inh->typeId == ClassType { + # LOG print( ' * found a class name\n' ) + return inh + } + + # Otherwise look inside the inherited object. + found = lookupWithInheritance( inh name ) + if found + return found + + II = II->next + } + + return nil + } + + lang_object unqualifiedLookup( name: str ) + { + found: lang_object + + # Start with the objects in the templateParamNs. + localTemplateParamNs: list_lang_object = templateParamNs + TemplParaObjIter: list_lang_object_el = localTemplateParamNs->tail + while ( TemplParaObjIter ) { + found = lookupWithInheritance( TemplParaObjIter->Obj name ) + if found + break + TemplParaObjIter = TemplParaObjIter->prev + } + + if !found { + # Iterator over the objects starting at the head of the lookup stack + # and going up through the lookup parents. + lookupIn: lang_object = lookupNs->tail->Obj + while lookupIn { + found = lookupWithInheritance( lookupIn name ) + if found + break + lookupIn = lookupIn->lookupParent + } + } + + return found + } + + # The C++ scanner. + lex + rl fract_const / digit* '.' digit+ | digit+ '.' / + rl exponent / [eE] [+\-]? digit+ / + rl float_suffix / [flFL] / + + # Single and double literals. + token TK_SingleLit /( 'L'? "'" ( [^'\\\n] | '\\' any )* "'" )/ + token TK_DoubleLit /( 'L'? '"' ( [^"\\\n] | '\\' any )* '"' )/ + + literal `extern `namespace `friend `typedef `auto `register + `static `mutable `inline `virtual `explicit `const + `volatile `restrict `class `struct `union `template + `private `protected `public `using `void `char + `wchar_t `bool `int `float `double `short `long + `signed `unsigned `enum `new `delete `operator + `typename `export `throw `try `catch `sizeof + `dynamic_cast `static_cast `reinterpret_cast `const_cast + `typeid `this `true `false `switch `case `default + `if `else `while `do `for `break `continue + `return `goto + + # Extensions + literal `__typeof `__is_pod `__is_empty + + literal `{ `} `; `, `= `( `) `: `& `* `[ `] `~ `+ `- + `/ `< `> `| `^ `% `! `? `. + + literal `:: `== `!= `&& `|| `*= `/= `%= `+= `-= `&= + `^= `|= `++ `-- `-> `->* `.* `... `<<= `>>= + + # Token translation targets. + def unknown_id [lookup_id] + def class_id [lookup_id] + def namespace_id [lookup_id] + def templ_class_id [lookup_id] + def enum_id [lookup_id] + def typedef_id [lookup_id] + def identifier [lookup_id] + def template_id [lookup_id] + + # Identifiers + token lookup_id + obj: lang_object + qualObj: lang_object + + /( [a-zA-Z_] [a-zA-Z0-9_]* )/ + { + name: str = match_text + found: lang_object = nil + qualObj: lang_object = nil + if qualNs->tail->Obj { + # LOG print( 'qualified lookup of ', name, '\n' ) + + # Transfer the qualification to the token and reset it. + qualObj = qualNs->tail->Obj + qualNs->tail->Obj = nil + + # Lookup using the qualification. + found = lookupWithInheritance( qualObj name ) + } + else { + # No qualification, full search. + # LOG print( 'unqualified lookup of ', name, '\n' ) + found = unqualifiedLookup( name ) + } + + # If no match, return an Unknown ID + id: int = typeid<unknown_id> + if found + id = found->typeId + + LookupId: lookup_id = make_token( typeid<lookup_id> input->pull(match_length) ) + LookupId.obj = found + LookupId.qualObj = qualObj + + input->push( make_tree( id LookupId ) ) + } + + # Floats. + token TK_Float /( fract_const exponent? float_suffix? | + digit+ exponent float_suffix? )/ + + # Integer decimal. Leading part buffered by float. + token TK_IntegerDecimal /( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} )/ + + # Integer octal. Leading part buffered by float. + token TK_IntegerOctal /( '0' [0-9]+ [ulUL]{0,2} )/ + + # Integer hex. Leading 0 buffered by float. + token TK_IntegerHex /( '0x' [0-9a-fA-F]+ [ulUL]{0,2} )/ + + # Preprocessor line. + ignore /'#' [^\n]* '\n'/ + + # Comments and whitespace. + ignore /( '/*' (any | '\n')* :>> '*/' )/ + ignore /( '//' any* :> '\n' )/ + ignore /( any - 33..126 )+/ + end + + # + # Support functions + # + + typeId: int + name: str + + # If the object is a typedef, this points to the real object. + typedefOf: lang_object + + objectMap: map_list_lang_object + inherited: list_lang_object + lookupParent: lang_object + specializationOf: lang_object + + lang_object createLangObject( typeId: int name: str lookupParent: lang_object ) + { + Obj: lang_object = new lang_object + + Obj->typeId = typeId + Obj->name = name + Obj->typedefOf = nil + Obj->objectMap = new map_list_lang_object + Obj->inherited = new list_lang_object + Obj->lookupParent = lookupParent + + return Obj + } + + # Building the language object tree. + int insertObject( definedIn: lang_object name: str obj: lang_object ) + { + ol: map_list_lang_object_el = definedIn->objectMap->find( name ) + if !ol { + # Element not in the map already + ol = new map_list_lang_object_el + ol->key = name + ol->List = new list_lang_object + definedIn->objectMap->insert( ol ) + } + E: list_lang_object_el = new list_lang_object_el + E->Obj = obj + ol->List->push_tail( E ) + } + + lang_object findClass( inObj: lang_object lang_objectname: str ) + { + ol: map_list_lang_object_el = inObj->objectMap->find( name ) + if ol { + ObjIter: list_lang_object_el = ol->List->head + while ( ObjIter ) { + obj: lang_object = ObjIter->Obj + if obj->typeId == ClassType { + return obj + } + ObjIter = ObjIter->next + } + } + return nil + } + + lang_object findTemplateClass( inObj: lang_object name: str ) + { + ol: map_list_lang_object_el = inObj->objectMap->find( name ) + if ol { + ObjIter: list_lang_object_el = ol->List->head + while ( ObjIter ) { + obj: lang_object = ObjIter->Obj + if obj->typeId == TemplateClassType + return obj + ObjIter = ObjIter->next + } + } + return nil + } + + def root_qual_opt + [] + | [`::] + + def nested_name_specifier_opt + [nested_name_specifier_opt qualifying_name `:: designated_qualifying_name `::] + | [nested_name_specifier_opt qualifying_name `::] + | [] + + def nested_name_specifier + [nested_name_specifier designated_qualifying_name `::] + | [nested_name_specifier qualifying_name `::] + | [qualifying_name `::] + + def qualifying_name + [class_name] + { + qualNs->tail->Obj = r1.lookupId.obj + } + + | [namespace_id] + { + match r1 [Id: lookup_id] + qualNs->tail->Obj = Id.obj + } + + | [typedef_id] + { + match r1 [Id: lookup_id] + qualNs->tail->Obj = Id.obj->typedefOf + } + + def designated_qualifying_name + [`template any_id] + { + # FIXME: nulling qualNs is not the right thing to do here. + qualNs->tail->Obj = nil + } + + | [`template any_id + templ_arg_open template_argument_list_opt templ_arg_close] + { + # FIXME: nulling qualNs is not the right thing to do here. + qualNs->tail->Obj = nil + } + + # + # Id Expression + # + + def id_expression + lookupId: lookup_id + + [root_qual_opt nested_name_specifier_opt unknown_id] + { + lhs.lookupId = lookup_id in r3 + } + + | [root_qual_opt nested_name_specifier_opt identifier] + { + lhs.lookupId = lookup_id in r3 + } + + | [root_qual_opt nested_name_specifier_opt operator_function_id] + { + # Normally the token translation transfers the qualification. Since + # the operator_function_id does not end in a lookup we must do it ourselves. + qualObj: lang_object = qualNs->tail->Obj + qualNs->tail->Obj = nil + + lhs.lookupId = construct lookup_id ["x"] + lhs.lookupId.data = '<operator_function_id>' + lhs.lookupId.qualObj = qualObj + } + + | [root_qual_opt nested_name_specifier_opt conversion_function_id] + { + # Normally the token translation transfers the qualification. Since + # the operator_function_id does not } in a lookup we must do it ourselves. + qualObj: lang_object = qualNs->tail->Obj + qualNs->tail->Obj = nil + + # Do we need qual reset here becauase operator_function_id does not do it? + lhs.lookupId = construct lookup_id ["x"] + lhs.lookupId.data = '<conversion_function_id>' + lhs.lookupId.qualObj = qualObj + } + + | [root_qual_opt nested_name_specifier_opt `~ class_name] + { + lhs.lookupId = r4.lookupId + } + + | [root_qual_opt nested_name_specifier_opt template_name] + { + lhs.lookupId = r3.lookupId + } + + def template_name + lookupId: lookup_id + + [template_id templ_arg_open template_argument_list_opt templ_arg_close] + { + lhs.lookupId = lookup_id in r1 + } + + | [template_id] + { + lhs.lookupId = lookup_id in r1 + } + + + # + # Class Names + # + + def class_name + lookupId: lookup_id + + [class_id] + { + lhs.lookupId = lookup_id in r1 + } + + | [templ_class_id] + { + lhs.lookupId = lookup_id in r1 + } + + | [templ_class_id templ_arg_open template_argument_list_opt templ_arg_close] + { + # TODO: Look for a specialization. + lhs.lookupId = lookup_id in r1 + } + + def templ_arg_open + [`<] + { + E: list_lang_object_el = new list_lang_object_el + E->Obj = nil + qualNs->push_tail( E ) + } + + def templ_arg_close + [`>] + { + qualNs->pop_tail() + } + + def declaration + [block_declaration] commit + | [function_definition] commit + | [template_declaration] commit + | [explicit_instantiation] commit + | [explicit_specialization] commit + | [linkage_specification] commit + | [namespace_definition] commit + + # + # Declarations + # + + def block_declaration + [simple_declaration] + | [using_declaration] + | [using_directive] + + def simple_declaration + [declaration_start simple_declaration_forms declaration_end `;] + + # Ordering is important for optimization. The form with the optional + # decl_specifier_sing should go second. + def simple_declaration_forms + [decl_specifier_mult_seq_opt decl_specifier_sing + decl_specifier_mult_seq_opt init_declarator_list_opt] + + | [decl_specifier_mult_seq_opt init_declarator_list_opt] + + def declaration_start + [] + { + # LOG print( 'opening new declaration_data with templDecl: ', templDecl.tail, '\n' ) + DD: declaration_data = new declaration_data + DD->isTypedef = 0 + DD->isFriend = 0 + DD->isTemplate = 0 + declarationData->push_tail( DD ) + + # Transfer the template flag and reset it. + declarationData->tail->isTemplate = templDecl->tail->Int + IntEl: list_int_el = new list_int_el + IntEl->Int = 0 + templDecl->push_tail( IntEl ) + } + + def declaration_end + [] + { + # LOG print( 'closing declaration_data\n' ) + declarationData->pop_tail() + templDecl->pop_tail() + } + + def decl_specifier_sing + [type_specifier_sing] + { + # Store the object type of the declaration (if any) for use + # by typedefs. + declarationData->tail->typeObj = r1.lookupId.obj + } + + def type_specifier_seq + lookupId: lookup_id + + [type_specifier_mult_seq_opt type_specifier_sing type_specifier_mult_seq_opt] + { + lhs.lookupId = r2.lookupId + } + + def type_specifier_sing + lookupId: lookup_id + + [simple_type_specifier] + { + lhs.lookupId = r1.lookupId + } + + | [class_specifier] + { + lhs.lookupId = construct lookup_id ["x"] + lhs.lookupId.data = '<class_specifier>' + } + + | [enum_specifier] + { + lhs.lookupId = construct lookup_id ["x"] + lhs.lookupId.data = '<enum_specifier>' + } + + | [elaborated_type_specifier] + { + lhs.lookupId = construct lookup_id ["x"] + lhs.lookupId.data = '<elaborated_type_specifier>' + } + + # Type specifier sequence without enum specifier or class specifier. + def necs_type_specifier_seq + [type_specifier_mult_seq_opt necs_type_specifier_sing type_specifier_mult_seq_opt] + + # Type specifier singular without enum specifier or class specifier. + def necs_type_specifier_sing + [simple_type_specifier] + | [elaborated_type_specifier] + + def type_specifier_mult_seq_opt + [type_specifier_mult_seq_opt type_specifier_mult] + | [] + + def type_specifier_mult_seq + [type_specifier_mult_seq type_specifier_mult] + | [type_specifier_mult] + + def simple_type_specifier + lookupId: lookup_id + + [simple_type_specifier_name] + { + lhs.lookupId = r1.lookupId + } + + | [simple_type_specifier_kw_seq] + { + lhs.lookupId = construct lookup_id ["x"] + lhs.lookupId.data = '<simple_type_specifier_kw_seq>' + } + + | [`typename root_qual_opt nested_name_specifier type_name] + { + lhs.lookupId = r4.lookupId + } + + | [`typename root_qual_opt nested_name_specifier identifier] + { + lhs.lookupId = lookup_id in r4 + } + + | [`typename root_qual_opt nested_name_specifier unknown_id] + { + lhs.lookupId = lookup_id in r4 + } + + # Extension. + | [`__typeof `( expression `)] + { + lhs.lookupId = construct lookup_id ["x"] + lhs.lookupId.data = '<simple_type_specifier_kw_seq>' + } + + def simple_type_specifier_name + lookupId: lookup_id + + [qual_type_name] + { + lhs.lookupId = r1.lookupId + } + + def simple_type_specifier_kw_seq + [simple_type_specifier_kw_seq simple_type_specifier_kw] + | [simple_type_specifier_kw] + + def simple_type_specifier_kw + [`void] + | [`char] + | [`wchar_t] + | [`bool] + | [`int] + | [`float] + | [`double] + | [`short] + | [`long] + | [`signed] + | [`unsigned] + + def qual_type_name + lookupId: lookup_id + + [root_qual_opt nested_name_specifier_opt type_name] + { + lhs.lookupId = r3.lookupId + } + + def type_name + lookupId: lookup_id + + [class_name] + { + lhs.lookupId = r1.lookupId + } + + | [enum_id] + { + lhs.lookupId = lookup_id in r1 + } + + | [typedef_id] + { + lhs.lookupId = lookup_id in r1 + } + + # NOTE: the typename case is moved to simple type specifier + # to take advantage of its conflict resolution. + def elaborated_type_specifier + [class_key nested_name_specifier_opt class_head_name] + { + Id: lookup_id = lookup_id in r3 + name: str = Id.data + + # Get the ns the class is declared in. + parentObj: lang_object = declNs->tail->Obj + if Id.qualObj + parentObj = Id.qualObj + + # Look for the class in the given scope. + declaredClass: lang_object = findClass( parentObj name ) + if !declaredClass + declaredClass = findTemplateClass( parentObj name ) + + if !declaredClass { + # LOG print( 'creating new class: ', name, '\n' ) + + # Class does not exist in the parent scope, create it. + nsType: int = declaredClassType() + + declaredClass = createLangObject( nsType name lookupNs->tail->Obj ) + + # FIXME: handle friends. Make the class visible only if we are NOT + # in a friend declaration. The new class object is necessary to + # properly process the body of the class. + if declarationData->tail->isFriend == 0 + insertObject( parentObj name declaredClass ) + } + } + + # TODO: Lookup type specialization. + | [class_key nested_name_specifier_opt templ_class_id + templ_arg_open template_argument_list_opt templ_arg_close] + + | [`enum nested_name_specifier_opt enum_head_name] + { + # TODO: should look for existing enums of the same name. + Id: lookup_id = lookup_id in r3 + # LOG print( 'creating enumeration ' Id.data '\n' ) + enum: lang_object = createLangObject( EnumType Id.data lookupNs->tail->Obj ) + insertObject( declNs->tail->Obj Id.data enum ) + } + + def decl_specifier_mult_seq_opt + [decl_specifier_mult_seq_opt decl_specifier_mult] + | [] + + def decl_specifier_mult_seq + [decl_specifier_mult_seq decl_specifier_mult] + | [decl_specifier_mult] + + def decl_specifier_mult + [type_specifier_mult] + | [storage_class_specifier] + | [function_specifier] + + | [`friend] + { + declarationData->tail->isFriend = 1 + } + + | [`typedef] + { + declarationData->tail->isTypedef = 1 + } + + def storage_class_specifier + [`auto] + | [`register] + | [`static] + | [`extern] + | [`mutable] + + def function_specifier + [`inline] + | [`virtual] + | [`explicit] + + def type_specifier_mult + [cv_qualifier] + + def cv_qualifier + [`const] + | [`volatile] + | [`restrict] + + def cv_qualifier_rep + [cv_qualifier_rep cv_qualifier] + | [] + + def namespace_definition + [named_namespace_definition] + | [unnamed_namespace_definition] + + def named_namespace_definition + [original_namespace_definition] + | [extension_namespace_definition] + + # + # Enumerations + # + + def enum_specifier + [`enum nested_name_specifier_opt + enum_head_name `{ enumerator_list_opt `}] + { + # TODO: should look for existing enums of the same name. + Id: lookup_id = lookup_id in r3 + # LOG print( 'creating enumeration ' Id.data '\n' ) + enum: lang_object = createLangObject( EnumType Id.data lookupNs->tail->Obj ) + insertObject( declNs->tail->Obj Id.data enum ) + } + + | [`enum `{ enumerator_list_opt `}] + + def enum_head_name + [class_id] + | [templ_class_id] + | [namespace_id] + | [typedef_id] + | [enum_id] + | [identifier] + | [template_id] + | [unknown_id] + + def enumerator_list_opt + [enumerator_list] + | [enumerator_list `,] + | [] + + def enumerator_list + [enumerator_list `, enumerator_definition] + | [enumerator_definition] + + def enumerator_definition + [enumerator_id] + { + Id: lookup_id = lookup_id in r1 + enumId: lang_object = createLangObject( IdType Id.data lookupNs->tail->Obj ) + insertObject( declNs->tail->Obj Id.data enumId ) + } + + | [enumerator_id `= constant_expression] + { + Id: lookup_id = lookup_id in r1 + enumId: lang_object = createLangObject( IdType Id.data lookupNs->tail->Obj ) + insertObject( declNs->tail->Obj Id.data enumId ) + } + + def enumerator_id + [namespace_id] + | [typedef_id] + | [enum_id] + | [class_id] + | [templ_class_id] + | [template_id] + | [identifier] + | [unknown_id] + + # + # Declarators + # + + def init_declarator_list_opt + [init_declarator_list] + | [] + + def init_declarator_list + [init_declarator_list `, init_declarator] + | [init_declarator] + + def init_declarator + [declarator initializer_opt] + + def initializer_opt + [`= initializer_clause] + | [`( expression `)] + | [] + + def initializer_clause + [assignment_expression] + | [`{ initializer_list `}] + | [`{ initializer_list `, `}] + | [`{ `}] + + def initializer_list + [initializer_list `, initializer_clause] + | [initializer_clause] + + # + # Expressions + # + + def expression + [expression `, assignment_expression] + | [assignment_expression] + + def expression_opt + [expression] + | [] + + def constant_expression + [conditional_expression] + + def constant_expression_opt + [constant_expression] + | [] + + def assignment_expression + [conditional_expression] + | [logical_or_expression assignment_op assignment_expression] + | [throw_expression] + + def assignment_op + [`=] + | [`*=] + | [`/=] + | [`%=] + | [`+=] + | [`-=] + | [`>>=] + | [`<<=] + | [`&=] + | [`^=] + | [`|=] + + def conditional_expression + [logical_or_expression] + | [logical_or_expression `? expression `: assignment_expression] + + def logical_or_expression + [logical_or_expression `|| logical_and_expression] + | [logical_and_expression] + + def logical_and_expression + [logical_and_expression `&& inclusive_or_expression] + | [inclusive_or_expression] + + def inclusive_or_expression + [inclusive_or_expression `| exclusive_or_expression] + | [exclusive_or_expression] + + def exclusive_or_expression + [exclusive_or_expression `^ and_expression] + | [and_expression] + + def and_expression + [and_expression `& equality_expression] + | [equality_expression] + + def equality_expression + [equality_expression `== relational_expression] + | [equality_expression `!= relational_expression] + | [relational_expression] + + def relational_expression + [relational_expression `< shift_expression] + | [relational_expression `> shift_expression] + | [relational_expression lt_eq shift_expression] + | [relational_expression gt_eq shift_expression] + | [shift_expression] + + def shift_expression + [shift_expression shift_left additive_expression] + | [shift_expression shift_right additive_expression] + | [additive_expression] + + def additive_expression + [additive_expression `+ multiplicative_expression] + | [additive_expression `- multiplicative_expression] + | [multiplicative_expression] + + def multiplicative_expression + [multiplicative_expression `* pm_expression] + | [multiplicative_expression `/ pm_expression] + | [multiplicative_expression `% pm_expression] + | [pm_expression] + + def pm_expression + [pm_expression `->* cast_expression] + | [pm_expression `.* cast_expression] + | [cast_expression] + + def cast_expression + [unary_expression] + | [`( type_id `) cast_expression] + + def delete_expression + [root_qual_opt `delete cast_expression] + | [root_qual_opt `delete `[ `] cast_expression] + + def new_initializer_opt + [new_initializer] + | [] + + def new_initializer + [`( expression_opt `)] + + def direct_new_declarator + [`[ expression `]] + | [direct_new_declarator `[ constant_expression `]] + + def new_declarator_opt + [new_declarator] + | [] + + def new_declarator + [direct_new_declarator] + | [ptr_operator_seq direct_new_declarator] + | [ptr_operator_seq] + + def new_type_id + [necs_type_specifier_seq new_declarator_opt] + + def new_placement + [`( expression `)] + + def new_expression + [root_qual_opt `new new_type_id new_initializer_opt] + | [root_qual_opt `new new_placement new_type_id new_initializer_opt] + | [root_qual_opt `new `( type_id `) new_initializer_opt] + | [root_qual_opt `new new_placement `( type_id `) new_initializer_opt] + + def unary_operator + [`*] + | [`&] + | [`+] + | [`-] + | [`!] + | [`~] + + def unary_expression + [postfix_expression] + | [`++ cast_expression] + | [`-- cast_expression] + | [unary_operator cast_expression] + | [`sizeof `( type_id `)] + | [`sizeof unary_expression] + | [new_expression] + | [delete_expression] + + def function_style_type_conv + [simple_type_specifier] + + + def postfix_expression + [primary_expression] + | [postfix_expression `[ expression `]] + | [postfix_expression `( expression_opt `)] + | [function_style_type_conv `( expression_opt `)] + | [member_request_expr dot_arrow id_expression] + | [member_request_expr dot_arrow pseudo_destructor_call] + | [postfix_expression `++] + | [postfix_expression `--] + | [`dynamic_cast templ_arg_open type_id templ_arg_close `( expression `)] + | [`static_cast templ_arg_open type_id templ_arg_close `( expression `)] + | [`reinterpret_cast templ_arg_open type_id templ_arg_close `( expression `)] + | [`const_cast templ_arg_open type_id templ_arg_close `( expression `)] + | [`typeid `( expression `)] + | [`typeid `( type_id `)] + + def pseudo_destructor_call + [root_qual_opt nested_name_specifier_opt `~ pdc_type_name] + + def primary_expression + [expr_lit] + | [`this] + | [`( expression `)] + | [id_expression] + # GNU extensions + | [`( `{ statement_rep `} `)] + | [`__is_pod `( type_id `)] + | [`__is_empty `( type_id `)] + + def expr_lit + [TK_IntegerDecimal] + | [TK_IntegerOctal] + | [TK_IntegerHex] + | [TK_SingleLit] + | [TK_Float] + | [double_lit_list] + | [`true] + | [`false] + + def double_lit_list + [TK_DoubleLit double_lit_list] + | [TK_DoubleLit] + + def member_request_expr + [postfix_expression] + # { + # # FIXME: If no proper type is found, we must fail. + # # LOG print( 'setting member request scope\n' ) + # # qualNs.set( $1->type != 0 ? $1->type->getObject() : 0 ); + # } + + def dot_arrow + [`->] + | [`.] + + def pdc_type_name + [enum_id] + | [typedef_id] + + # + # Statements + # + + def statement_rep + [statement_rep statement] + | [] + + def statement + [declaration_statement] + | [labeled_statement] + | [expression_statement] + | [compound_statement] + | [selection_statement] + | [iteration_statement] + | [jump_statement] + | [try_block] + + def labeled_statement + [label_id `: statement] + | [`case constant_expression `: statement] + | [`default `: statement] + + def label_id + [unknown_id] + | [identifier] + | [class_id] + | [templ_class_id] + | [namespace_id] + | [typedef_id] + | [enum_id] + | [template_id] + + def compound_statement + [`{ compound_begin statement_rep compound_end `}] + + def compound_begin + [] + { + newCompound: lang_object = createLangObject( 0 '<compound_begin>' lookupNs->tail->Obj ) + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = newCompound + lookupNs->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = newCompound + declNs->push_tail( E2 ) + # LOG print( 'opening <compound>\n' ) + } + + def compound_end + [] + { + lookupNs->pop_tail() + declNs->pop_tail() + # LOG print( 'closing <compound>\n' ) + } + + def selection_statement + [`if `( condition `) statement elseif_clauses else_clause] + | [`switch `( condition `) statement] + + def elseif_clauses + [elseif_clauses `else `if `( condition `) statement] + | [] + + def else_clause + [`else statement] + | [] + + def iteration_statement + [`while `( condition `) statement] + | [`do statement `while `( expression `) `;] + | [`for `( for_init_statement condition_opt `; expression_opt `) statement] + + def jump_statement + [`break `;] + | [`continue `;] + | [`return expression_opt `;] + | [`goto any_id `;] + + def any_id + [unknown_id] + | [class_id] + | [namespace_id] + | [templ_class_id] + | [enum_id] + | [typedef_id] + | [identifier] + | [template_id] + + + def for_init_statement + [expression_statement] + | [stmt_block_declaration_forms `;] + + def condition + [expression] + | [type_specifier_seq declarator `= assignment_expression] + + def condition_opt + [condition] + | [] + + def expression_statement + [expression `;] + | [`;] + + def declaration_statement + [stmt_block_declaration] + + def stmt_block_declaration + [declaration_start stmt_block_declaration_forms declaration_end `;] + | [using_declaration] + | [using_directive] + + def stmt_block_declaration_forms + [decl_specifier_mult_seq_opt decl_specifier_sing decl_specifier_mult_seq_opt + init_declarator_list_opt] + | [decl_specifier_mult_seq init_declarator_list_opt] + + # + # Declarators + # + + def declarator + lookupObj: lang_object + + [ptr_operator_seq_opt declarator_id decl_array_or_param_rep declarator_end] + { + lhs.lookupObj = r4.lookupObj + } + + | [ptr_operator_seq_opt `( sub_declarator `) decl_array_or_param_rep declarator_end] + { + lhs.lookupObj = r6.lookupObj + } + + def sub_declarator + [ptr_operator_seq declarator_id decl_array_or_param_rep] + | [ptr_operator_seq `( sub_declarator `) decl_array_or_param_rep] + | [`( sub_declarator `) decl_array_or_param_rep] + | [declarator_id decl_array_or_param_rep] + + def decl_array_or_param_rep + [decl_array_or_param_rep decl_array_or_param] + | [] + + def decl_array_or_param + [`[ constant_expression_opt `]] + | [`( parameter_declaration_clause `) cv_qualifier_rep exception_specification_opt] + + def declarator_id + [declarator_id_forms] + { + name: str = r1.lookupId.data + qualObj: lang_object = r1.lookupId.qualObj + + parentObj: lang_object = declNs->tail->Obj + if qualObj { + parentObj = qualObj + } + + # Decide if we are declaring a constructor/destructor. + isConstructor: bool + if parentObj == r1.lookupId.obj { + isConstructor = true + # LOG print( 'making declarator ' name ' a constructor/destructor\n' ) + } + + if parentObj->specializationOf && + parentObj->specializationOf == r1.lookupId.obj + { + isConstructor = true + # LOG print( 'making declarator ' name ' a constructor/destructor\n' ) + } + + obj: lang_object = nil + if name && !isConstructor && declarationData->tail->isFriend == 0 { + if declarationData->tail->isTypedef { + obj = createLangObject( TypedefType name lookupNs->tail->Obj ) + obj->typedefOf = declarationData->tail->typeObj + insertObject( parentObj name obj ) + + # LOG print( 'making declarator ' name ' a typedef\n' ) + } + else { + if !qualObj { + if declarationData->tail->isTemplate { + # If in a template declaration and the name is not qualified then + # create the template id. + obj = createLangObject( TemplateIdType name lookupNs->tail->Obj ) + #object->objType = declarationData.tail.type + insertObject( declNs->tail->Obj name obj ) + + # LOG print( 'making declarator ' name ' a template id\n' ) + } + else { + obj = createLangObject( IdType name lookupNs->tail->Obj ) + #object->objType = declarationData.tail().type; + insertObject( declNs->tail->Obj name obj ) + + # LOG print( 'making declarator ' name ' an id\n' ) + } + } + } + } + + + DD: declarator_data = new declarator_data + DD->qualObj = qualObj + DD->pdcScope = nil + DD->lookupObj = lookupNs->tail->Obj + + declaratorData->push_tail( DD ) + + # If the declarator is qualified, push the qualification to the lookup + # stack. Also save it in the declarator data so it can be passed to a + # function body if needed. + if qualObj { + E: list_lang_object_el = new list_lang_object_el + E->Obj = qualObj + lookupNs->push_tail( E ) + declaratorData->tail->lookupObj = qualObj + } + + # LOG print( 'reduced declarator_id: ' name '\n' ) + } + + # Undoes the setup done by declarator_id and pdc_start. + def declarator_end + lookupObj: lang_object + + [] + { + # Get the lookupObject from the scope and pass it up. If we are about to + # parse a function body it will be needed. + lhs.lookupObj = declaratorData->tail->lookupObj + + pdcScope: lang_object = declaratorData->tail->pdcScope + qualObj: lang_object = declaratorData->tail->qualObj + + declaratorData->pop_tail() + + if pdcScope { + # LOG print( 'closing <pdc_scope>\n' ) + lookupNs->pop_tail() + declNs->pop_tail() + } + + if qualObj { + # LOG print( 'popping lookupNs\n' ) + lookupNs->pop_tail() + } + } + + def declarator_id_forms + lookupId: lookup_id + + [id_expression] + { + lhs.lookupId = r1.lookupId + } + + | [root_qual_opt nested_name_specifier_opt type_name] + { + lhs.lookupId = r3.lookupId + } + + | [root_qual_opt nested_name_specifier_opt `~ class_id] + { + lhs.lookupId = lookup_id in r4 + } + + | [root_qual_opt nested_name_specifier_opt `~ templ_class_id] + { + lhs.lookupId = lookup_id in r4 + } + | [root_qual_opt nested_name_specifier_opt `~ unknown_id] + { + lhs.lookupId = lookup_id in r4 + } + + def type_id + lookupId: lookup_id + + [type_specifier_seq abstract_declarator_opt] + { + lhs.lookupId = r1.lookupId + } + + def abstract_declarator_opt + [abstract_declarator] + | [] + + def abstract_declarator + [ptr_operator_seq abstract_noid abstract_decl_array_or_param_seq_opt declarator_end] + | [ptr_operator_seq `( sub_abstract_declarator `) + abstract_decl_array_or_param_seq_opt declarator_end] + | [abstract_noid abstract_decl_array_or_param_seq declarator_end] + | [`( sub_abstract_declarator `) abstract_decl_array_or_param_seq_opt declarator_end] + + def sub_abstract_declarator + [ptr_operator_seq abstract_noid abstract_decl_array_or_param_seq_opt] + + | [ptr_operator_seq `( sub_abstract_declarator `) + abstract_decl_array_or_param_seq_opt] + + | [`( sub_abstract_declarator `) abstract_decl_array_or_param_seq_opt] + + def abstract_noid + [] + { + # Make scope for declarator. + DD: declarator_data = new declarator_data + declaratorData->push_tail( DD ) + } + + def abstract_decl_array_or_param_seq_opt + [abstract_decl_array_or_param_seq_opt abstract_decl_array_or_param] + | [] + + def abstract_decl_array_or_param_seq + [abstract_decl_array_or_param_seq abstract_decl_array_or_param] + | [abstract_decl_array_or_param] + + def abstract_decl_array_or_param + [`[ constant_expression_opt `]] + | [`( parameter_declaration_clause `) cv_qualifier_rep + exception_specification_opt] + + def parameter_declaration_clause + [pdc_start parameter_declaration_list] + | [pdc_start parameter_declaration_list `...] + | [pdc_start parameter_declaration_list `, `...] + | [pdc_start `...] + | [pdc_start] + + def pdc_start + [] + { + if !declaratorData->tail->pdcScope { + # We are going to need a scope for the declarator. + pdcScope: lang_object = createLangObject( 0 '<pdc_scope>' lookupNs->tail->Obj ) + + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = pdcScope + lookupNs->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = pdcScope + declNs->push_tail( E2 ) + + declaratorData->tail->pdcScope = pdcScope + declaratorData->tail->lookupObj = pdcScope + # LOG print( 'opening <pdc_scope>\n' ) + } + } + + def parameter_declaration_list + [parameter_declaration_list `, parameter_declaration] + | [parameter_declaration] + + def parameter_declaration + [declaration_start parameter_declaration_forms declaration_end] + + # Ordering the productions such that decl_specifier_sing is tried first is good + # for performance. + def parameter_declaration_forms + [decl_specifier_mult_seq_opt decl_specifier_sing decl_specifier_mult_seq_opt + param_maybe_declarator maybe_parameter_init] + + | [decl_specifier_mult_seq param_maybe_declarator maybe_parameter_init] + + def param_maybe_declarator + [abstract_declarator] + | [declarator] + | [] + + def maybe_parameter_init + [`= constant_expression] + | [] + + def ptr_operator + [`&] + | [root_qual_opt nested_name_specifier_opt `* cv_qualifier_rep] + + def ptr_operator_seq + [ptr_operator_seq ptr_operator] + | [ptr_operator] + + def ptr_operator_seq_opt + [ptr_operator_seq_opt ptr_operator] + | [] + + # + # Functions + # + + def function_definition + [function_def_declaration ctor_initializer_opt function_body function_def_end] + + def function_def_declaration + [declaration_start function_def_declaration_forms declaration_end] + + def function_def_declaration_forms + [decl_specifier_mult_seq_opt decl_specifier_sing + decl_specifier_mult_seq_opt function_def_declarator] + | [decl_specifier_mult_seq function_def_declarator] + | [function_def_declarator] + + def function_def_declarator + [declarator] + { + # The lookupObj from the declarator is the deepest lookup object found + # while parsing the declarator. Make it visible in the function body. + # This could be the args, the qualObj, or the parent to the function. + E: list_lang_object_el = new list_lang_object_el + E->Obj = r1.lookupObj + lookupNs->push_tail( E ) + } + + def function_def_end + [] + { + # Pop the lookup object. + lookupNs->pop_tail() + } + + def function_body + [function_body_begin `{ statement_rep function_body_end `}] + + def function_body_begin + [] + { + newFunctionBody: lang_object = createLangObject( 0 + '<function_body_begin>' lookupNs->tail->Obj ) + + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = newFunctionBody + lookupNs->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = newFunctionBody + declNs->push_tail( E2 ) + + IntEl: list_int_el = new list_int_el + IntEl->Int = 0 + templDecl->push_tail( IntEl ) + # LOG print( 'opening <function_body>\n' ) + } + + def function_body_end + [] + { + # First undoes the function body begin work. Then undoes the setup in + # function_def_declarator. + declNs->pop_tail() + lookupNs->pop_tail() + templDecl->pop_tail() + # LOG print( 'closing <function_body>\n' ) + } + + + + # + # Classs + # + + int declaredClassType() + { + if declarationData->tail->isTemplate { + return TemplateClassType + } else { + return ClassType + } + } + + def class_specifier + [class_head base_clause_opt `{ class_member_rep class_body_end `}] + { + # FIXME: reparse not implemented yet + # FIXME FIXME: reparse is actually implemented now implemented + # # Visit class function bodies, but skip nested classes. + # for CFB: class_function_body in lhs { + # skipping class_specifier + # + # # Reparse the text of the class function body as a function body + # function_body FB = parse function_body[ $CFB ] + # + # # Replace the class function body with the parsed function body. + # CFB = cons class_function_body [FB.tree] + # } + } + + def class_head + [class_key] + { + nsType: int = declaredClassType() + + # LOG print( 'creating new anonymous class\n' ) + newClass: lang_object = createLangObject( nsType + '<anon_class>' lookupNs->tail->Obj ) + + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = newClass + lookupNs->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = newClass + declNs->push_tail( E2 ) + } + + | [class_key nested_name_specifier_opt class_head_name] + { + Id: lookup_id = lookup_id in r3 + name: str = Id.data + + # Get the ns the class is declared in. + parentObj: lang_object = declNs->tail->Obj + if Id.qualObj + parentObj = Id.qualObj + + # Look for the class in the given scope. + declaredClass: lang_object = findClass( parentObj name ) + if !declaredClass + declaredClass = findTemplateClass( parentObj name ) + + if !declaredClass { + # LOG print( 'creating new class: ' name '\n' ) + + # Class does not exist in the parent scope, create it. + nsType: int = declaredClassType() + + declaredClass = createLangObject( nsType name lookupNs->tail->Obj ) + + # FIXME: handle friends. Make the class visible only if we are NOT + # in a friend declaration. The new class object is necessary to + # properly process the body of the class. + if declarationData->tail->isFriend == 0 + insertObject( parentObj name declaredClass ) + } + + # Push the found/new class. + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = declaredClass + lookupNs->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = declaredClass + declNs->push_tail( E2 ) + } + + | [class_key nested_name_specifier_opt templ_class_id + templ_arg_open template_argument_list_opt templ_arg_close] + { + match r3 [Id: lookup_id] + id: str = Id.data + classObj: lang_object = Id.obj + + # TODO: Try to find the specializaition in the template class object. + # TypeList typeList; + # makeTypeList( typeList $6->last ); + + declaredClass: lang_object + #declaredClass = classObj->findSpecExact( typeList ); + if !declaredClass { + # LOG print( 'making new template specialization\n' ) + nsType: int = declaredClassType() + declaredClass = createLangObject( nsType id lookupNs->tail->Obj ) + # LOG print( 'declaredClass: ' declaredClass '\n' ) + declaredClass->specializationOf = classObj + # $$->typeListMapEl = classObj->typeListMap.insert( typeList declaredClass ); + } + + # Push the found/new class. + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = declaredClass + lookupNs->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = declaredClass + declNs->push_tail( E2 ) + } + + def class_body_end + [] + { + # Pop the class ns. + lookupNs->pop_tail() + declNs->pop_tail() + + # LOG print( 'closing off class\n' ) + } + + def class_head_name + [class_id] + | [templ_class_id] + | [namespace_id] + | [typedef_id] + | [enum_id] + | [unknown_id] + | [identifier] + | [template_id] + + def class_key + [`class] + | [`struct] + | [`union] + + def class_member_rep + [class_member_rep class_member] + | [] + + def class_member + [member_declaration] + | [access_specifier `:] + + def member_declaration + [declaration_start member_declaration_forms declaration_end `;] + | [class_function_definition] + | [using_declaration] + | [template_declaration] + + def class_function_definition + [function_def_declaration ctor_initializer_opt class_function_body function_def_end] + + lex + token cfb_open /'{'/ + token cfb_close /'}'/ + token cfb_string / + "'" ( [^'\\\n] | '\\' any )* "'" | + '"' ( [^"\\\n] | '\\' any )* '"'/ + token cfb_comment / + ( '/*' (any | '\n')* :>> '*/' ) | + ( '//' any* :> '\n' )/ + token cfb_data /[^{}'"/]+ | '/'/ + end + + def cfb_item + [cfb_data] + | [cfb_string] + | [cfb_comment] + | [cfb_open cfb_item* cfb_close] + + def cfb_conts + [cfb_item* cfb_close] + + + + def class_function_body + # ['{' cfb_conts] + #| [function_body] + [function_body] + + # Get better performance if the form with decl_specifier_sing comes first. + def member_declaration_forms + [decl_specifier_mult_seq_opt decl_specifier_sing + decl_specifier_mult_seq_opt member_declarator_list_opt] + | [decl_specifier_mult_seq_opt member_declarator_list_opt] + + def member_declarator_list_opt + [member_declarator_list] + | [] + + def member_declarator_list + [member_declarator_list `, member_declarator] + | [member_declarator] + + def member_declarator + [declarator] + | [declarator `= constant_expression] + | [declarator `: constant_expression] + | [`: constant_expression] + + def access_specifier + [`private] + | [`protected] + | [`public] + + def access_specifier_opt + [access_specifier] + | [] + + def using_declaration + [`using id_expression `;] + { + obj: lang_object = r2.lookupId.obj + if obj + insertObject( declNs->tail->Obj obj->name obj ) + } + + | [`using type_id `;] + { + obj: lang_object = r2.lookupId.obj + if obj + insertObject( declNs->tail->Obj obj->name obj ) + } + + def using_directive + [`using `namespace root_qual_opt nested_name_specifier_opt + namespace_id `;] + { + # This uses a simple, incomplete guard against cycles in the graph of + # using namespaces. A more sophisticated and complete guard would look + # for longer cycles as well. Note that even gcc 3.3.5 does not bother. + match r5 [Id: lookup_id] + usingObject: lang_object = Id.obj + inObject: lang_object = declNs->tail->Obj + if usingObject != inObject { + E: list_lang_object_el = new list_lang_object_el + E->Obj = usingObject + inObject->inherited->push_tail( E ) + } + } + + + # + # Derived classes + # + + def base_clause_opt + [base_clause] + | [] + + def base_clause + [`: base_specifier_list] + + def base_specifier_list + [base_specifier_list `, base_specifier] + | [base_specifier] + + int addBaseSpecifier( inObject: lang_object inheritedObject: lang_object ) + { + # Resolve typedefs. + if inheritedObject->typeId == TypedefType + inheritedObject = inheritedObject->typedefOf + + E: list_lang_object_el = new list_lang_object_el + E->Obj = inheritedObject + inObject->inherited->push_tail( E ) + } + + def base_specifier + [root_qual_opt nested_name_specifier_opt type_name] + { + addBaseSpecifier( declNs->tail->Obj r3.lookupId.obj ) + } + + | [`virtual access_specifier_opt root_qual_opt nested_name_specifier_opt type_name] + { + addBaseSpecifier( declNs->tail->Obj r5.lookupId.obj ) + } + + | [access_specifier virtual_opt root_qual_opt nested_name_specifier_opt type_name] + { + addBaseSpecifier( declNs->tail->Obj r5.lookupId.obj ) + } + + def virtual_opt + [`virtual] + | [] + + # + # Special member functions + # + + def conversion_function_id + [`operator conversion_type_id] + + def conversion_type_id + [necs_type_specifier_seq ptr_operator_seq_opt] + + def ctor_initializer_opt + [ctor_initializer] + | [] + + def ctor_initializer + [`: mem_initializer_list] + + def mem_initializer_list + [mem_initializer_list `, mem_initializer] + | [mem_initializer] + + def mem_initializer + [mem_initializer_id `( expression_opt `)] + + def mem_initializer_id + [root_qual_opt nested_name_specifier_opt unknown_id] + | [root_qual_opt nested_name_specifier_opt identifier] + | [root_qual_opt nested_name_specifier_opt type_name] + | [root_qual_opt nested_name_specifier_opt template_name] + + + # + # Overloading + # + def operator_function_id + [`operator operator] + + def operator + [`+] | [`-] | [`*] | [`/] | [`=] | [`<] | [`>] | [`&] | [`|] | + [`^] | [`%] | [`~] | [`!] | [`( `)] | [`[ `]] | [`new] | + [`delete] | [`->] | [`++] | [`--] | [`*=] | [`/=] | [`%=] | + [`+=] | [`-=] | [`>>=] | [`<<=] | [`&=] | [`^=] | [`|=] | [`==] | + [`!=] | [`&&] | [`||] | [lt_eq] | [gt_eq] | [shift_left] | [shift_right] + + def lt_eq + [`< `=] + # try { + # if ( $2->leader != 0 ) { + # #ifdef LOG_REDUCE + # cerr << "rejecting less-than equals-to" << endl; + # #endif + # reject(); + # } + # }; + + def gt_eq + [`> `=] + # try { + # if ( $2->leader != 0 ) { + # #ifdef LOG_REDUCE + # cerr << "rejecting greater-than equals-to" << endl; + # #endif + # reject(); + # } + # }; + + def shift_left + [`< `<] + # try { + # if ( $2->leader != 0 ) { + # #ifdef LOG_REDUCE + # cerr << "rejecting shift left" << endl; + # #endif + # reject(); + # } + # }; + + def shift_right + [`> `>] + # try { + # if ( $2->leader != 0 ) { + # #ifdef LOG_REDUCE + # cerr << "rejecting shift right" << endl; + # #endif + # reject(); + # } + # }; + + # + # Templates + # + + def template_declaration + [template_declaration_params declaration] + { + templDecl->pop_tail() + templateParamNs->pop_tail() + } + + def template_declaration_params + [`template `< tpl_start template_parameter_list `>] + { + IntEl: list_int_el = new list_int_el + IntEl->Int = 1 + templDecl->push_tail( IntEl ) + } + + | [`export `template `< tpl_start template_parameter_list `>] + { + IntEl: list_int_el = new list_int_el + IntEl->Int = 1 + templDecl->push_tail( IntEl ) + } + + def tpl_start + [] + { + # Create a new scope for the template parameters. + newTemplateParamScope: lang_object = + createLangObject( 0 '<tpl_start>' lookupNs->tail->Obj ) + + E: list_lang_object_el = new list_lang_object_el + E->Obj = newTemplateParamScope + templateParamNs->push_tail( E ) + } + + def template_parameter_list + [template_parameter_list `, template_parameter] + | [template_parameter] + + def template_parameter + [type_parameter] + | [template_parameter_declaration] + + def template_parameter_declaration + [declaration_start template_parameter_declaration_forms declaration_end] + + def template_parameter_declaration_forms + [decl_specifier_mult_seq param_maybe_declarator maybe_parameter_init] + + | [temp_param_decl_specifier_sing decl_specifier_mult_seq_opt + param_maybe_declarator maybe_parameter_init] + + | [decl_specifier_mult_seq temp_param_decl_specifier_sing + decl_specifier_mult_seq_opt param_maybe_declarator maybe_parameter_init] + + def temp_param_decl_specifier_sing + [temp_param_type_specifier_sing] + + # Template parameters cannot support elaborated type specifer or class specifier. + def temp_param_type_specifier_sing + [templ_simple_type_specifier] + | [enum_specifier] + + def templ_simple_type_specifier + [simple_type_specifier_name] + | [simple_type_specifier_kw_seq] + + def type_parameter + [`class type_param_id type_param_init_opt] + { + Id: lookup_id = lookup_id in r2 + if Id { + # The lookup ns should be a template param scope. + newClass: lang_object = + createLangObject( ClassType Id.data lookupNs->tail->Obj ) + insertObject( templateParamNs->tail->Obj Id.data newClass ) + } + } + + | [`typename type_param_id type_param_init_opt] + { + Id: lookup_id = lookup_id in r2 + if Id { + # The lookup ns should be a template param scope. + newClass: lang_object = + createLangObject( ClassType Id.data lookupNs->tail->Obj ) + insertObject( templateParamNs->tail->Obj Id.data newClass ) + } + } + + | [`template `< tpl_start template_parameter_list `> + `class type_param_id templ_type_param_init_opt] + { + Id: lookup_id = lookup_id in r7 + if Id { + newClass: lang_object = + createLangObject( TemplateClassType Id.data lookupNs->tail->Obj ) + insertObject( templateParamNs->tail->Obj Id.data newClass ) + } + } + + def templ_type_param_init_opt + [`= id_expression] + | [] + + def type_param_init_opt + [`= type_id] + | [] + + def type_param_id + [namespace_id] + | [typedef_id] + | [enum_id] + | [class_id] + | [templ_class_id] + | [identifier] + | [template_id] + | [unknown_id] + | [] + + def template_argument_list_opt + [template_argument_list] + | [] + + def template_argument_list + [template_argument_list `, template_argument] + | [template_argument] + + def template_argument + [type_id] + | [assignment_expression] + + def explicit_instantiation + [`template declaration] + | [declaration_start decl_specifier_mult_seq `template declaration declaration_end] + + def explicit_specialization + [`template `< `> declaration] + + ## Not sure what this one is about? + #explicit_specialization: + # declaration_start decl_specifier_mult_seq KW_Template '<' '>' + # declaration declaration_end; + + + # + # Original namespace definition + # + + def original_namespace_definition + [orig_namespace_def_name `{ declaration* namespace_end `}] + + def orig_namespace_def_name [`namespace unknown_id] + { + match r2 [Id: lookup_id] + nspace: lang_object = createLangObject( + NamespaceType Id.data lookupNs->tail->Obj ) + + # Insert the new object into the dictionary of the parent. + insertObject( curNamespace->tail->Obj Id.data nspace ) + + # Push the namespace + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = nspace + curNamespace->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = nspace + declNs->push_tail( E2 ) + + E3: list_lang_object_el = new list_lang_object_el + E3->Obj = nspace + lookupNs->push_tail( E3 ) + + # LOG print( 'created original namespace: ' Id.data '\n' ) + } + + def namespace_end [] + { + # Pop the namespace. + curNamespace->pop_tail() + declNs->pop_tail() + lookupNs->pop_tail() + + # LOG print( 'closed namespace\n' ) + } + + # + # Extension namespace definition + # + + def extension_namespace_definition + [ext_namespace_def_name `{ declaration* namespace_end `}] + + def ext_namespace_def_name [`namespace namespace_id] + { + match r2 [Id: lookup_id] + nspace: lang_object = Id.obj + + # Push the namespace + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = nspace + curNamespace->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = nspace + declNs->push_tail( E2 ) + + E3: list_lang_object_el = new list_lang_object_el + E3->Obj = nspace + lookupNs->push_tail( E3 ) + + # LOG print( 'found extended namespace: ' Id.data '\n' ) + } + + # + # Unnamed namespace definition + # + def unnamed_namespace_definition + [unnamed_namespace_def_name `{ declaration* namespace_end `}] + + def unnamed_namespace_def_name [`namespace] + { + nspace: lang_object = createLangObject( + NamespaceType '<unnamed_namespace>' + lookupNs->tail->Obj ) + + # Push the namespace + E1: list_lang_object_el = new list_lang_object_el + E1->Obj = nspace + curNamespace->push_tail( E1 ) + + E2: list_lang_object_el = new list_lang_object_el + E2->Obj = nspace + declNs->push_tail( E2 ) + + E3: list_lang_object_el = new list_lang_object_el + E3->Obj = nspace + lookupNs->push_tail( E3 ) + + # LOG print( 'parsed unnamed namespace\n' ) + } + + # + # linkage_specification + # + def linkage_specification + [`extern TK_DoubleLit `{ declaration* `}] + | [`extern TK_DoubleLit declaration] + + # + # Exception Handling. + # + + def try_block + [`try compound_statement handler_seq] + + def handler_seq + [handler_seq handler] + | [handler] + + def handler + [`catch `( exception_declaration `) compound_statement] + + def exception_declaration + [type_specifier_seq declarator] + | [type_specifier_seq abstract_declarator] + | [type_specifier_seq] + | [`...] + + def throw_expression + [`throw assignment_expression] + | [`throw] + + def exception_specification_opt + [exception_specification] + | [] + + def exception_specification + [`throw `( type_id_list_opt `)] + + def type_id_list_opt + [type_id_list] + | [] + + def type_id_list + [type_id_list `, type_id] + | [type_id] + + def start + [declaration*] + + # + # Grammar done. + # + + int printObject( indent: str obj: lang_object ) + { + print( indent obj->name ) + + if obj->objectMap->length > 0 + print( ' {\n' ) + + ChildNames: map_list_lang_object = obj->objectMap + MapEl: map_list_lang_object_el = ChildNames->head + while ( MapEl ) { + El: list_lang_object_el = MapEl->List->head + while ( El ) { + printObject( indent + ' ' El->Obj ) + El = El->next + } + MapEl = MapEl->next + } + + if obj->objectMap->length > 0 + print( indent '}' ) + + print( '\n' ) + } + +end # lookup + +# +# Global data declarations +# + +Lookup: lookup = new lookup + +# Constants for language object types. +Lookup->NamespaceType = typeid<lookup::namespace_id> +Lookup->ClassType = typeid<lookup::class_id> +Lookup->TemplateClassType = typeid<lookup::templ_class_id> +Lookup->EnumType = typeid<lookup::enum_id> +Lookup->IdType = typeid<lookup::identifier> +Lookup->TypedefType = typeid<lookup::typedef_id> +Lookup->TemplateIdType = typeid<lookup::template_id> + + +# Object stacks. +Lookup->curNamespace = new lookup::list_lang_object +Lookup->declNs = new lookup::list_lang_object +Lookup->lookupNs = new lookup::list_lang_object +Lookup->qualNs = new lookup::list_lang_object +Lookup->templateParamNs = new lookup::list_lang_object + +# Declaration, declarator data. +Lookup->declarationData = new lookup::list_declaration_data +Lookup->declaratorData = new lookup::list_declarator_data + +# Template declarations +Lookup->templDecl = new lookup::list_int + +# Root namespace object +Lookup->rootNamespace = createLangObject( Lookup->NamespaceType '<root_namespace>' nil ) + +# Initialize the namespace and declaration stacks with the root namespace +E1: lookup::list_lang_object_el = new lookup::list_lang_object_el +E1->Obj = Lookup->rootNamespace +Lookup->curNamespace->push_tail( E1 ) + +E2: lookup::list_lang_object_el = new lookup::list_lang_object_el +E2->Obj = Lookup->rootNamespace +Lookup->declNs->push_tail( E2 ) + +E3: lookup::list_lang_object_el = new lookup::list_lang_object_el +E3->Obj = Lookup->rootNamespace +Lookup->lookupNs->push_tail( E3 ) + +# Start with no qualification (note variables are initialized to zero) +E4: lookup::list_lang_object_el = new lookup::list_lang_object_el +E4->Obj = nil +Lookup->qualNs->push_tail( E4 ) + +IntEl: lookup::list_int_el = new lookup::list_int_el +IntEl->Int = 0 +Lookup->templDecl->push_tail( IntEl ) + +DD: lookup::declaration_data = new lookup::declaration_data +DD->isTypedef = 0 +DD->isFriend = 0 +DD->isTemplate = 0 +Lookup->declarationData->push_tail( DD ) + +parse S: lookup::start( Lookup )[ stdin ] +if ! S { + print( error ) + exit( 1 ) +} + +print( '***** NAMSPACES *****\n' ) +printObject( '' Lookup->rootNamespace ) +print( '***** UNKNOWN DECLARATORS *****\n' ) +for DI: lookup::declarator_id in S { + if match DI + [lookup::root_qual_opt lookup::nested_name_specifier_opt lookup::`~ UID: lookup::unknown_id] + { + print( UID '\n' ) + } +} +##### IN ##### +namespace ns1 +{ + namespace sub1 { class A {}; } + namespace sub2 { class B {}; } +} + +namespace ns2 +{ + int i = b; + class C + { + }; + + using namespace ns1; +} + +ns2::sub1::A a; + +struct A +{ + struct B {}; +}; + +struct C +{ + struct D : virtual public A {}; +}; + +C::D::A d; + +C c; + +struct C +{ + +}; + +enum E +{ + C, + b +}; + +E e; + +enum E +{ + C, + b +}; + + +int i; +class C +{ + int j; +}; + +class D +{ + int ~D(); +}; + +int C::k; +int C::~C; + +typedef int Int; + +class C {}; +void ~C( ); +void C::operator +( int i ); + +int i; + +//void operator C( void k ); + +class C +{ + +}; + +int C::f( int i, int j( void v ) ); +class C +{ + class D {}; + + typedef C I; + + I::D i; +}; + +C c; + +void function( int i, int j ) +{ + function(); +} + + + +class B { class Find {}; }; + +typedef B T; + +class C : public T +{ + Find find; +}; + + +template <class X> struct Y +{ + X t; + void f(); +}; + +template <class X> void Y<X>::f(); +template <class X> struct Y +{ + class Z {}; +}; + +class Y<int> +{ + int i; +}; + +//void f( class C<int> i, int j ); + +int f( int (*) [](), void ); +void f(); +class C +{ + class D {}; + void g(); +}; + +//typename C c; + +class C +{ + class D {}; + int f(); +}; + +int f() +{ +} + +int C::f() +{ + D d; +} +##### EXP ##### +***** NAMSPACES ***** +<root_namespace> { + A { + B + } + B { + Find + } + C { + D + } + C + C + C + C { + j + } + C + C + C + C { + D + I + i + } + C { + find + } + C { + D + g + } + C { + D + f + } + D + E + E + T + Y { + Z + f + t + } + a + b + b + c + c + d + e + f + f + f + i + i + Int + ns1 { + sub1 { + A + } + sub2 { + B + } + } + ns2 { + C + i + } + function +} +***** UNKNOWN DECLARATORS ***** +C |