From: <bl...@us...> - 2003-08-02 18:33:56
|
Update of /cvsroot/cpptool/rfta/src/pyrfta/test/rfta In directory sc8-pr-cvs1:/tmp/cvs-serv28200/src/pyrfta/test/rfta Modified Files: parser.py parsertest.py Log Message: * added massive amount of grammar for declaration, declarators, class & exception * added ProxyParser to allow forward declaration of parser (allow recursion) * namespace parsing is now failing (infinite recursion). => need to add a debug facility to the parser. Index: parser.py =================================================================== RCS file: /cvsroot/cpptool/rfta/src/pyrfta/test/rfta/parser.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** parser.py 1 Aug 2003 18:53:44 -0000 1.4 --- parser.py 2 Aug 2003 18:33:53 -0000 1.5 *************** *** 341,346 **** to set the name of the node returned by parser. """ ! def __init__( self ): self.action_on_match = None # not use, use a decoarator parser instead (ActionParser) def parse( self, scanner ): --- 341,353 ---- to set the name of the node returned by parser. """ ! def __init__( self, name = None ): self.action_on_match = None # not use, use a decoarator parser instead (ActionParser) + self.name = name + + def setName( self, name ): + self.name = name + + def getName( self, name ): + return self.name def parse( self, scanner ): *************** *** 356,360 **** The method matched() & notMatched() should be called to created the Match object. """ ! pass def matched( self, scanner, result_value ): --- 363,367 ---- The method matched() & notMatched() should be called to created the Match object. """ ! raise "Parser.parse() should have been implemented by the derived Parser" def matched( self, scanner, result_value ): *************** *** 545,549 **** return 'repeat(%d,%s)' % (self.min_count,str(self.parser)) ! class AnyUntil(Parser): def __init__( self, until_parser ): Parser.__init__( self ) --- 552,556 ---- return 'repeat(%d,%s)' % (self.min_count,str(self.parser)) ! class AnyUntilParser(Parser): def __init__( self, until_parser ): Parser.__init__( self ) *************** *** 591,594 **** --- 598,612 ---- return '0' % str(self.type) + class ProxyParser(Parser): + def __init__( self ): + Parser.__init__( self ) + self.parser = None + + def parse( self, scanner ): + return self.parser.parse( scanner ) + + def setParser( self, parser ): + self.parser = parser + class InlineChildAction(Action): def __init__( self, node_index ): *************** *** 662,665 **** --- 680,686 ---- return RemoveSymbolAction() + def terminal_p( token_type ): + return TerminalParser( token_type ) + end_p = TerminalParser( END_STREAM ) *************** *** 687,691 **** def anyuntil_p( parser ): """ Matchs any tokens until parser returns a match.""" ! return AnyUntil( make_p( parser ) ) id_p = TerminalParser( IDENTIFIER ) --- 708,715 ---- def anyuntil_p( parser ): """ Matchs any tokens until parser returns a match.""" ! return AnyUntilParser( make_p( parser ) ) ! ! def proxy_p(): ! return ProxyParser() id_p = TerminalParser( IDENTIFIER ) *************** *** 774,775 **** --- 798,1065 ---- | class_decl_p + # ############################## A.5: Expressions ############################ + # A.5, C++PL3 p.798-802 + constant_expression_p = terminal_p(INTEGER) | terminal_p(CHAR) # dummy + + # dummy + assignment_expression_p = constant_expression_p + + ##assignment_expression_p = proxy_p() + ## + ##assignment_expression_p.setParser( conditional_expression_p \ + ## | ( logical_or_expression_p >> assignement_operator_p >> assignment_expression_p ) \ + ## | throw_expression_p ) + + # dummy + expression_list_p = constant_expression_p + + # ############################## A.6: Statements ############################ + + #dummy + compound_statement_p = symbol_p('{') >> '}' + + # ############################## A.7.1: Declarators ############################ + # A.7.1, C++PL3 p.807-808 + + class_key_p = proxy_p() + class_specifier_p = proxy_p() + ctor_initializer_p = proxy_p() + declarator_p = proxy_p() + decl_specifier_p = proxy_p() # forward declaration for recursion + exception_specification_p = proxy_p() + function_try_block_p = proxy_p() + ptr_operator_p = proxy_p() + abstract_declarator_p = proxy_p() + direct_abstract_declarator_p = proxy_p() + parameter_declaration_clause_p = proxy_p() + initializer_clause_p = proxy_p() + type_specifier_p = proxy_p() + + cv_qualifier_p = symbol_p('const') | 'volatile' + cv_qualifier_seq_p = repeat_p( 1, cv_qualifier_p ) + + decl_specifier_seq_p = repeat_p( 1, decl_specifier_p ) + + function_body_p = compound_statement_p + + function_definition_start_p = maybe_p(decl_specifier_seq_p) >> declarator_p + function_definition_p = function_definition_start_p \ + >> ( (maybe_p(ctor_initializer_p) >> function_body_p) \ + | function_try_block_p ) + + + direct_abstract_declarator_p.setParser( (maybe_p( direct_abstract_declarator_p ) >> '(' >> parameter_declaration_clause_p >> ')' \ + >> maybe_p( cv_qualifier_seq_p ) >> maybe_p( exception_specification_p ) ) \ + | (maybe_p( direct_abstract_declarator_p ) >> '[' >> constant_expression_p >> ']') \ + | (symbol_p('(') >> direct_abstract_declarator_p >> ')') ) + + abstract_declarator_p.setParser( (ptr_operator_p >> maybe_p( abstract_declarator_p )) \ + | direct_abstract_declarator_p ) + + opt_parameter_decl_assign_p = maybe_p( symbol_p('=') >> assignment_expression_p ) + + parameter_declaration_p = (decl_specifier_seq_p >> declarator_p >> opt_parameter_decl_assign_p ) \ + | (decl_specifier_seq_p >> abstract_declarator_p >> opt_parameter_decl_assign_p ) + + parameter_declaration_clause_p.setParser( symbol_p('...') \ + | (maybe_p( list_p( parameter_declaration_p, ',' ) ) \ + >> maybe_p( symbol_p(',') >> symbol_p('...') ) ) ) + + # Notes: drastically simplified. Is it correct ? + declarator_id = nested_id_p + + ptr_operator_p.setParser( (symbol_p('*') >> maybe_p( cv_qualifier_seq_p )) \ + | symbol_p('&') \ + | (nested_id_p >> '*' >> maybe_p( cv_qualifier_seq_p ) ) ) + + direct_declarator_p = proxy_p() + direct_declarator_p.setParser( declarator_id \ + | (direct_declarator_p >> '(' >> parameter_declaration_clause_p >>')' \ + >> maybe_p( cv_qualifier_seq_p ) >> maybe_p( exception_specification_p ) ) \ + | (direct_declarator_p >> '[' >> maybe_p(constant_expression_p) >> ']') \ + | ( symbol_p('(') >> declarator_p >> ')') ) + + declarator_p.setParser( direct_declarator_p \ + | (ptr_operator_p >> declarator_p) ) + + initializer_list_p = list_p( initializer_clause_p, ',' ) + + initializer_clause_p.setParser( assignment_expression_p \ + | (symbol_p('{') >> initializer_list_p >> maybe_p( ',' ) >> '}') \ + | (symbol_p('{') >> '}') ) + + initializer_p = initializer_clause_p \ + | (symbol_p('(') >> expression_list_p >> ')') + + init_declarator_p = declarator_p >> maybe_p( initializer_p ) + + init_declarator_list_p = list_p( init_declarator_p, ',' ) + + type_specifier_seq_p = repeat_p( 1, type_specifier_p ) + + # ############################## A.7: Declaration ############################ + declaration_p = proxy_p() # forward declaration for recursion + + declaration_seq_p = repeat_p( 1, declaration_p ) + + # A.7, C++PL3 p.805-806 + # => parse namespace declaration and namespace alias declaration + # Notes: OK. No parsing issue + namespace_body_p = maybe_p( declaration_seq_p )['namespace_body'] + qualified_namespace_specifier_p = nested_id_p + named_namespace_definition_p = symbol_p('namespace') >> id_p >> '{' >> namespace_body_p >> '}' + unnamed_namespace_definition_p = (symbol_p('namespace') >> '{' >> namespace_body_p >> '}') + namespace_alias_definition_p = (symbol_p('namespace') >> id_p >> '=' \ + >> qualified_namespace_specifier_p >> eos_p)['namespace_alias_def'][remove_symbol_a()] + namespace_definition_p = ( named_namespace_definition_p['named_namespace_def'] \ + | unnamed_namespace_definition_p['unnamed_namespace_def'] )[remove_symbol_a()] + + # A.7, C++PL3 p.806 + # => parse using declaration and directive + # Notes: OK. No parsing issue + using_declaration_p = ( ( (symbol_p('using') >> 'typename' >> nested_id_p)['using_typename_decl'] \ + | (symbol_p('using') >> nested_id_p)['using_decl'] ) \ + >> eos_p ) + + using_directive_p = symbol_p('using') >> 'namespace' >> nested_id_p >> eos_p + + # A.7, C++PL3 p.806 + # => parse asm definition + asm_keyword_p = symbol_p('asm') \ + | '__asm' # Microsoft Visual C++ + + asm_definition_p = asm_keyword_p >> '(' >> terminal_p(STRING) >> ')' >> eos_p + + # A.7, C++PL3 p.806 + # => parse extern specifiction + linkage_specification_begin_p = symbol_p('extern') >> terminal_p(STRING) + linkage_specification_p = (linkage_specification_begin_p >> '{' >> maybe_p(declaration_seq_p) >> '}') \ + | (linkage_specification_begin_p >> declaration_p) + + # A.7, C++PL3 p.804-806 + # => parse simple declaration + # Notes: parsing issue in: + # -simple_type_specifier_p + # -enumerator_definition_p (for constant expression that contains template with multiple parameters) + + enumerator_p = id_p + + enumerator_definition_p = enumerator_p \ + | enumerator_p >> '=' >> constant_expression_p + + enum_specifier_p = symbol_p('enum') >> maybe_p(id_p) >> '{' >> maybe_p(list_p(enumerator_definition_p, ',')) >> '}' + + elaborated_type_specifier_p = class_key_p >> nested_id_p \ + | (symbol_p('enum') >> nested_id_p) \ + | (symbol_p('typename') >> nested_id_p) \ + | (symbol_p('typename') >> nested_id_p >> 'template' >> id_p ) # need to check that one. Is it really a nest_id_p + + # Notes: following case not handled: + # - opt(::) opt(nested-name-specifier) type-name + # - opt(::) opt(nested-name-specifier) opt(tempalte) template-id + simple_type_specifier_p = symbol_p('char') | 'wchar_t' | 'bool' | 'short' | 'int' | 'long' \ + | 'signed' | 'unsigned' | 'float' | 'double' | 'void' + + storage_class_specifier_p = symbol_p('auto') | 'register' | 'static' | 'extern' | 'mutable' + function_specifier_p = symbol_p('inline') | 'virtual' | 'explicit' + type_specifier_p.setParser( simple_type_specifier_p + | class_specifier_p + | enum_specifier_p + | elaborated_type_specifier_p + | cv_qualifier_p ) + + decl_specifier_p.setParser( storage_class_specifier_p \ + | type_specifier_p \ + | function_specifier_p \ + | 'friend' \ + | 'typedef' ) + + simple_declaration_p = repeat_p( 0, decl_specifier_p ) >> maybe_p( init_declarator_list_p ) >> eos_p + + # A.7, C++PL3 p.804 + block_declaration_p = asm_definition_p \ + | namespace_alias_definition_p \ + | using_declaration_p \ + | using_directive_p \ + | simple_declaration_p + + declaration_p.setParser( block_declaration_p \ + | linkage_specification_p \ + | namespace_definition_p ) + # | function_definition_p \ + # | template_declaration_p \ + # | explicit_instantiation_p \ + # | explicit_specialization_p \ + + + # ############################## A.8: Classes ############################ + # A.8, C++PL3 p.808-809 + + class_name_p = id_p + + constant_initializer_p = symbol_p('=') >> constant_expression_p + + pure_specifier_p = symbol_p('=') >> ZeroParser() + + member_declarator_p = (declarator_p >> maybe_p(pure_specifier_p)) \ + | (declarator_p >> maybe_p(constant_initializer_p)) \ + | (maybe_p(id_p) >> ':' >> constant_expression_p) + + member_declarator_list_p = list_p( member_declarator_p, ',' ) + + #Notes: not included: + #- opt(::) nested-name-specifier opt(template) unqualified-id + member_declaration_p = (maybe_p( decl_specifier_seq_p ) >> maybe_p( member_declarator_list_p ) >> eos_p) \ + | (function_definition_p >> maybe_p( eos_p )) \ + | using_declaration_p + # | template_declaration_p + + access_specifier_p = symbol_p("public") | "protected" | "private" + + member_specification_p = proxy_p() + member_specification_p.setParser( repeat_p( 0, + (access_specifier_p >> ':') \ + | member_declaration_p ) ) + + class_key_p.setParser( symbol_p('class') | 'struct' | 'union' ) + + base_specifier_p = maybe_p('virtual') >> maybe_p( access_specifier_p ) \ + >> maybe_p('virtual') >> nested_id_p # not template support in class_name for now + + base_clause_p = symbol_p(':') >> list_p( base_specifier_p, ',' ) + + class_head_name_p = nested_id_p >> maybe_p( symbol_p('template') >> id_p ) + + class_head_p = class_key_p >> maybe_p( class_head_name_p ) >> maybe_p( base_clause_p ) + + class_specifier_p.setParser( class_head_p >> '{' >> maybe_p( member_specification_p ) >> '}' ) + + # ############### A.8.2: Classes, Specials Member Functions ################## + # A.8.2, C++PL3 p.810 + + mem_initializer_id = nested_id_p + + mem_initializer_p = mem_initializer_id >> '(' >> maybe_p( expression_list_p ) >> ')' + + ctor_initializer_p.setParser( symbol_p( ':' ) >> list_p( mem_initializer_p, ',' ) ) + + + + # ############################## A.10: Exceptions ############################ + # A.10, C++PL3 p.812 + + throw_expression_p = symbol_p('throw') >> maybe_p( assignment_expression_p ) + + exception_declaration_p = (type_specifier_seq_p >> maybe_p( declarator_p | abstract_declarator_p )) \ + | '...' + + handler_p = symbol_p('catch') >> '(' >> exception_declaration_p >> ')' >> compound_statement_p + + handler_seq_p = repeat_p( 1, handler_p ) + + type_id_list_p = list_p( nested_id_p, ',' ) + exception_specification_p.setParser( symbol_p( 'throw' ) >> '(' >> maybe_p( type_id_list_p ) >> ')' ) + + try_block_p = symbol_p('try') >> compound_statement_p >> handler_seq_p + + function_try_block_p.setParser( symbol_p('try') >> maybe_p(ctor_initializer_p) >> function_body_p >> handler_seq_p ) Index: parsertest.py =================================================================== RCS file: /cvsroot/cpptool/rfta/src/pyrfta/test/rfta/parsertest.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** parsertest.py 1 Aug 2003 08:25:05 -0000 1.3 --- parsertest.py 2 Aug 2003 18:33:53 -0000 1.4 *************** *** 130,133 **** --- 130,146 ---- self.checkParser( "class MyClass : public MyParent, MyParent2 { };", parser.class_decl_p ) + proxy_test_p = parser.proxy_p() + proxy_test_p.setParser( parser.id_p ) + self.checkParser( "otot", proxy_test_p ) + + ## self.checkParser( "namespace { } ", parser.namespace_definition_p ) + ## self.checkParser( "namespace MyWork { } ", parser.namespace_definition_p ) + self.checkParser( "namespace fs = boost::filesystem;", parser.namespace_alias_definition_p ) + self.checkParser( "using typename boost::filesystem::path;", parser.using_declaration_p ) + self.checkParser( "using boost::filesystem::path;", parser.using_declaration_p ) + self.checkParser( "using namespace boost::filesystem;", parser.using_directive_p ) + # self.checkParser( 'extern "C" { }', parser.declaration_p ) + + def checkParser( self, text, tested_parser ): tokens = self.scanner.tokenize( text ) |