|
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 )
|