Update of /cvsroot/cpptool/rfta/src/pyrfta/test/rfta/parser
In directory sc8-pr-cvs1:/tmp/cvs-serv3499/src/pyrfta/test/rfta/parser
Added Files:
__init__.py alltests.py generateparserdebuginfo.py grammar.py
grammartest.py node.py nodetest.py nodetesthelper.py parser.py
parsertest.py parsertesthelper.py parsingtracker.py
structuredtokenstream.py structuredtokenstreamtest.py token.py
tokenizer.py tokenizertest.py
Log Message:
* added C++ parser in python (without C++ template for the time being), as well as a load of tests.
--- NEW FILE: __init__.py ---
# module
--- NEW FILE: alltests.py ---
#!/usr/bin/env python
#
# Example of assembling all available unit tests into one suite. This usually
# varies greatly from one project to the next, so the code shown below will not
# be incorporated into the 'unittest' module. Instead, modify it for your own
# purposes.
#
# $Id: alltests.py,v 1.1 2003/08/24 21:00:36 blep Exp $
import unittest
import nodetest
import parsertest
import grammartest
import tokenizertest
def suite():
alltests = unittest.TestSuite()
alltests.addTest(unittest.findTestCases(nodetest))
alltests.addTest(unittest.findTestCases(tokenizertest))
alltests.addTest(unittest.findTestCases(parsertest))
alltests.addTest(unittest.findTestCases(grammartest))
# for module in map(__import__, modules_to_test):
# alltests.addTest(unittest.findTestCases(module))
return alltests
if __name__ == '__main__':
unittest.TextTestRunner().run(suite())
--- NEW FILE: generateparserdebuginfo.py ---
# generate parser name for debug
import grammar
import string
for var in dir(grammar):
if var.endswith('_p') or var.endswith('_pi'):
print "%s.setName( '%s' )" % (var,var)
--- NEW FILE: grammar.py ---
# c++ grammar
from parser import *
# IMPORTANT NOTES:
# If a parser rule is stored in a variable and is an Alternative or a Sequence parser, then it must be wrapped
# in a proxy parser, other the parser rule will be extended when used within another rule.
#
# my_p = id_p >> '::' >> id_p # BAD
# my_p = proxy_f( id_p >> '::' >> id_p ) # GOOD
# other_p = my_p >> ',' # in the BAD case, the sequence parser 'my_p' would be extended
# Remarks:
# Because the grammar does use know declared type, it is not possible to distinguish between:
# 1) In the context of an expression:
# function call and object instantiation => node(1) may be either a function call, or a object instantiation,
# or a functional style conversion
# => in this case, the grammar create a 'call_or_conversion_expression'
# 2) In the context of a declaration:
# function declarator and object instantiation => node n(2); may be either a function declaration or an object instantiation.
# => in this case, the grammar create a function_declaration.
id_p = TerminalParser( IDENTIFIER )
eos_p = symbol_f( ';' )
pp_directive_pi = rename_f( 'preprocessor_directive', terminal_f( PP_DIRECTIVE ) )
# ############################## A.4: Program ############################
# A.4, C++PL3 p.798
declaration_seq_pi = proxy_f()
translation_unit_pi = node_f( 'translation_unit', optional_f( declaration_seq_pi ) )
# ############################## A.5: Expressions ############################
# A.5, C++PL3 p.798-802
operator_function_id_pi = proxy_f()
conversion_function_id_pi = proxy_f()
simple_type_specifier_p = proxy_f()
ptr_operator_pi = proxy_f()
type_specifier_seq_pi = proxy_f()
throw_expression_pi = proxy_f()
class_name_pi = proxy_f()
nested_name_specifier_pi = proxy_f()
template_id_pi = proxy_f()
type_id_pi = proxy_f()
expression_pi = proxy_f()
expression_list_pi = proxy_f()
cast_expression_p = proxy_f()
assignment_expression_pi = proxy_f()
unary_expression_p = proxy_f()
constant_expression_pi = proxy_f()
unqualified_id_pi = proxy_f()
new_type_pi = proxy_f() # define in declarators
type_name_pi = proxy_f()
literal_expression_p = proxy_f( ( terminal_f(INTEGER)
| terminal_f(CHAR)
| terminal_f(STRING)
| terminal_f(FLOAT)
| one_of_f( 'true false' ) ) >> rename_last_cmd( 'literal' ) )
namespace_name_pi = proxy_f( id_p )
class_or_namespace_name_p = class_name_pi | namespace_name_pi
template_name_specifier_p = (symbol_f('template') >> nested_name_specifier_pi)
nested_name_specifier_pi.setParser(
repeat_f( 1, class_or_namespace_name_p >> '::' >> optional_f(template_name_specifier_p) ) )
# Notes: qualified_id can not include 'template' => A::template B::zozo is not parsed (IT SHOULD BE)
qualified_id_p = node_f('qualified_id',
( optional_f('::') >> nested_name_specifier_pi >> optional_f('template') >> unqualified_id_pi )
| ( symbol_f('::') >> ( id_p
| operator_function_id_pi
| conversion_function_id_pi ) ) )
# Notes: template id not included
# destructor_ref may be parsed as such while it is not a reference to a destructor (overloaded ~ operator & ())
unqualified_id_pi.setParser( id_p
| operator_function_id_pi
| conversion_function_id_pi \
| node_f('destructor_ref', symbol_f('~') >> id_p >> look_ahead_f( symbol_f('(') >> ')' ) )
) # | template_id_pi
id_expression_pi = longuest_f( qualified_id_p,
node_f( 'unqualified_id', unqualified_id_pi ) )
# C++ Standard p65
primary_expression_p = proxy_f( literal_expression_p
| ( symbol_f('this') >> rename_last_cmd( 'this_ref' ) )
| node_f('braced_expr', symbol_f('(') >> expression_pi >> symbol_f(')') )
| id_expression_pi )
# Notes: missing template in scope case
pseudo_destructor_name_p = node_f( 'pseudo_destructor_name',
optional_f('::') >> optional_f(nested_name_specifier_pi) >> optional_f(type_name_pi >> '::')
>> symbol_f('~') >> id_p )
instance_accessor_p = one_of_f('. ->')
cast_keywords_p = one_of_f('dynamic_cast static_cast reinterpret_cast const_cast')
# Notes: not included in postfix_expression_p:
# typename with template in scope
#
# postfix_expression_p as been modified to avoid the infinite left recursion. This recursion has been
# moved to multiple 'optional' suffixes
#
array_operator_suffix_p = node_f('array_index', symbol_f('[') >> expression_pi >> ']')
call_operator_suffix_p = node_f('call_parameters', symbol_f('(') >> optional_f( expression_list_pi ) >> ')')
accessed_member_p = pseudo_destructor_name_p | (optional_f( 'template' ) >> optional_f( '::' ) >> id_expression_pi)
member_access_suffix_p = node_f('accessed_member', instance_accessor_p >> accessed_member_p )
post_incdec_suffix_p = node_f( 'operator', one_of_f( '++ --' ) )
cppcast_expression_p = node_f('cppcast_expression',
cast_keywords_p >> '<' >> type_id_pi >> '>' >> '(' >> expression_pi >> ')' )
type_id_expression_p = node_f( 'typeid_expression',
symbol_f('typeid') >> '(' >> (type_id_pi | expression_pi) >> ')' )
# Notes: because of the typeless parsing a function call can not be distinguished from a
# functional type conversion. In the case of a function call, the name of the function will be found in the
# type id.
call_or_conversion_expression_p = node_f( 'call_or_conversion_expression',
( (symbol_f('typename') >> optional_f('::') >> nested_name_specifier_pi >> id_p)
| simple_type_specifier_p )
>> '(' >> optional_f( expression_list_pi ) >> ')' )
#Notes: template_id construction is missing
postfix_expression_p = binary_operator_f(
alternative_f( cppcast_expression_p,
type_id_expression_p,
call_or_conversion_expression_p,
primary_expression_p ),
alternative_f( make_right_op_f(array_operator_suffix_p, 'array_access'), # longuest could be removed if instance_accessor stuff are factorized into one rule
make_right_op_f(call_operator_suffix_p, 'call'),
make_right_op_f(member_access_suffix_p, 'member_access'),
make_right_op_f(post_incdec_suffix_p, 'post_incdec') ) )
cast_expression_p = proxy_f()
cast_expression_p.setParser( unary_expression_p
| node_f('cast_expression',
symbol_f('(') >> type_id_pi >> ')' >> node_f('casted_expression',
cast_expression_p ) ) )
delete_expression_p = node_f( 'delete_operator',
optional_f( '::') >> 'delete' >> optional_f(symbol_f('[') >> ']') >> cast_expression_p)
new_initializer_p = node_f('new_initializer', symbol_f('(') >> optional_f( expression_list_pi ) >> ')')
expression_list_pi.setParser( node_f( 'expression_list', list_f( assignment_expression_pi, ',' ) ) )
direct_new_declarator_p = repeat_f( 1, symbol_f('[') >> expression_pi >> ']' ) \
>> optional_f( symbol_f('[') >> constant_expression_pi >> ']' )
new_declarator_p = proxy_f()
new_declarator_p.setParser( (ptr_operator_pi >> optional_f( new_declarator_p ))
| direct_new_declarator_p )
new_type_id_p = node_f('new_type_id', new_type_pi >> optional_f( new_declarator_p ))
new_type_id_alt_p = (symbol_f('(') >> new_type_id_p >> ')') \
| new_type_id_p
new_placement_p = node_f('new_placement', symbol_f( '(' ) >> expression_list_pi >> ')')
new_expression_p = node_f('new_operator',
optional_f( '::' ) >> 'new' >>
optional_alternative_f( new_placement_p,
new_type_id_alt_p >> optional_f(new_initializer_p) ))
# Notes: added '++' & '--'
unary_operator_p = one_of_f( '++ -- * & + - ! ~' )
# Notes: sizeof( expr ) is already handled because unary_expression may be a braced expression.
unary_expression_p.setParser( postfix_expression_p
| node_f('unary_operator', unary_operator_p >> cast_expression_p)
| node_f('sizeof_operator', symbol_f( 'sizeof' ) >> unary_expression_p)
| new_expression_p
| delete_expression_p )
pm_expression_p = binary_operator_f( cast_expression_p,
make_right_op_f( node_f('right_operand',
instance_accessor_p >> '*' >> cast_expression_p ),
'pointer_to_member_operator' ) )
##def binary_expr_p_factory( simple_expr_parser, symbols ):
## return proxy_f( simple_expr_parser >> repeat_f( 0, one_of_f( symbols ) >> simple_expr_parser ) )
def binary_expr_p_factory( simple_expr_parser, symbols ):
return binary_operator_f( simple_expr_parser,
make_right_op_f( node_f('right_operand',
one_of_f( symbols ) >> simple_expr_parser),
'binary_operator' ) )
multiplicative_expression_p = binary_expr_p_factory( pm_expression_p, '* / %' )
additive_expression_p = binary_expr_p_factory( multiplicative_expression_p, '+ -' )
shift_expression_p = binary_expr_p_factory( additive_expression_p, '<< >>' )
relational_expression_p = binary_expr_p_factory( shift_expression_p, '< > <= >=' )
equality_expression_p = binary_expr_p_factory( relational_expression_p, '== !=' )
and_expression_p = binary_expr_p_factory( equality_expression_p, '&' )
exclusive_or_expression_p = binary_expr_p_factory( and_expression_p, '^' )
inclusive_or_expression_p = binary_expr_p_factory( exclusive_or_expression_p, '|' )
logical_and_expression_p = binary_expr_p_factory( inclusive_or_expression_p, '&&' )
logical_or_expression_p = binary_expr_p_factory( logical_and_expression_p, '||' )
##conditional_expression_p = proxy_f( logical_or_expression_p
## >> repeat_f( 0, symbol_f('?') >> expression_pi >> ':' >> assignment_expression_pi ) )
conditional_expression_p = binary_operator_f(
logical_or_expression_p,
make_right_op_f( node_f('right_operand', symbol_f('?') >> expression_pi >> ':' >> assignment_expression_pi ),
'tertiary_operator' ) )
assignment_operator_p = one_of_f( '= *= /= %= += -= >>= <<= &= ^= |=' )
assignment_expression_p = longuest_f(
conditional_expression_p,
(logical_or_expression_p >> assignment_operator_p >> assignment_expression_pi),
throw_expression_pi )
expression_pi.setParser( node_f( 'expression',
node_f( 'assignment_expression_list', list_f( assignment_expression_p, ',', 2 ) )
| assignment_expression_p ) )
assignment_expression_pi.setParser( node_f( 'assignment_expression', assignment_expression_p ) )
constant_expression_pi.setParser( node_f( 'constant_expression', conditional_expression_p ) )
# ############################## A.6: Statements ############################
# A.6, C++PL3 p.802-803
block_declaration_p = proxy_f()
declarator_p = proxy_f()
simple_declaration_p = proxy_f()
statement_p = proxy_f()
try_block_pi = proxy_f()
condition_p = expression_pi \
| ( type_specifier_seq_pi >> declarator_p >> '=' >> assignment_expression_pi )
expression_statement_p = node_f( 'expression_statement', optional_f(expression_pi) >> eos_p )
jump_statement_p = node_f( 'break_statement', symbol_f('break') >> eos_p ) \
| node_f( 'continue_statement', symbol_f('continue') >> eos_p ) \
| node_f( 'return_statement', symbol_f('return') >> optional_f(expression_pi) >> eos_p) \
| node_f( 'goto_statement', symbol_f('goto') >> id_p >> eos_p)
for_init_statement_p = expression_statement_p \
| simple_declaration_p
iteration_statement_p = node_f('while_statement',
symbol_f('while') >> '(' >> condition_p >> ')' >> statement_p) \
| node_f('dowhile_statement',
symbol_f('do') >> statement_p >> 'while' >> '(' >> expression_pi >> ')' >> eos_p) \
| node_f('for_statement',
symbol_f('for') >> '(' >> for_init_statement_p
>> node_f('for_condition', optional_f( condition_p ) )
>> eos_p >> optional_f( expression_pi ) >> ')' >> statement_p )
selection_statement_p = node_f( 'if_statement', symbol_f('if') >> '(' >> condition_p >> ')' >> statement_p \
>> optional_f( symbol_f('else') >> statement_p ) ) \
| node_f( 'switch_statement', symbol_f('switch') >> '(' >> condition_p >> ')' >> statement_p )
error_statement_p = node_f( 'error_statement', block_error_f() )
compound_statement_pi = node_f( 'compound_statement',
symbol_f('{') >> repeat_f( 0,
statement_p | error_statement_p ) >> '}' )
labeled_statement_p = node_f('label_statement', id_p >> ':' >> statement_p) \
| node_f( 'case_statement', symbol_f('case') >> constant_expression_pi >> ':' >> statement_p ) \
| node_f( 'default_statement', symbol_f('default') >> ':' >> statement_p )
declaration_statement_p = node_f( 'declaration_statement', block_declaration_p )
statement_p.setParser( labeled_statement_p
| compound_statement_pi
| selection_statement_p
| iteration_statement_p
| jump_statement_p
| expression_statement_p
| declaration_statement_p
| try_block_pi
| pp_directive_pi )
# ############################## A.7.1: Declarators ############################
# A.7.1, C++PL3 p.807-808
class_key_pi = proxy_f()
class_specifier_pi = proxy_f()
ctor_initializer_p = proxy_f()
exception_specification_pi = proxy_f()
function_try_block_pi = proxy_f()
abstract_declarator_p = proxy_f()
direct_abstract_declarator_p = proxy_f()
parameter_declaration_clause_p = proxy_f()
initializer_clause_p = proxy_f()
workaround_type_specifier_pi = proxy_f()
cv_qualifier_p = one_of_f('const volatile' )
cv_qualifier_seq_p = node_f( 'cv_qualifiers', repeat_f( 1, cv_qualifier_p ) )
# buggy standard C++ rules. Use 'custom type parser instead' => see decl_specifiers_p, parameter_type_p,
# new_type_pi, function_return_type...
# decl_specifier_seq_p = buggy # repeat_f( 1, decl_specifier_p )
# decl_specifier_p = buggy #( storage_class_specifier_p
# | type_specifier_p
# | function_specifier_p
# | rename_f( 'friend_specifier', 'friend' )
# | rename_f( 'typedef_specifier', 'typedef' ) )
# type_specifier_p = buggy #( simple_type_specifier_p
# | enum_specifier_p
# | longuest_f( class_specifier_pi, elaborated_type_specifier_p )
# | cv_qualifier_p)
# removed left recursion
direct_abstract_declarator_fn_suffix_p = proxy_f(
node_f( 'function_parameters', symbol_f('(') >> parameter_declaration_clause_p >> ')' )
>> optional_f( cv_qualifier_seq_p )
>> optional_f( exception_specification_pi ) )
direct_abstract_declarator_array_suffix_p = node_f( 'abstract_array_declarator',
symbol_f('[') >> optional_f( constant_expression_pi ) >> ']' )
direct_abstract_declarator_p.setParser(
optional_f( symbol_f('(') >> abstract_declarator_p >> ')' )
>> repeat_f( 0, direct_abstract_declarator_fn_suffix_p
| direct_abstract_declarator_array_suffix_p ) )
abstract_declarator_p.setParser( (ptr_operator_pi >> optional_f( abstract_declarator_p )) \
| direct_abstract_declarator_p )
opt_parameter_decl_assign_p = optional_f( node_f( 'parameter_default_value',
symbol_f('=') >> assignment_expression_pi ) )
parameter_type_p = proxy_f( optional_f(cv_qualifier_seq_p)
>> workaround_type_specifier_pi
>> optional_f(cv_qualifier_seq_p) )
new_type_pi.setParser( workaround_type_specifier_pi )
parameter_declaration_p = node_f( 'function_parameter',
node_f('parameter_type', parameter_type_p)
>> node_f('parameter_name', declarator_p | abstract_declarator_p)
>> opt_parameter_decl_assign_p )
ellipsis_parameter_declaration = node_f('ellipsis_parameter', '...' )
parameter_declaration_clause_p.setParser( ellipsis_parameter_declaration \
| (optional_f( list_f( parameter_declaration_p, ',' ) ) \
>> optional_f( symbol_f(',') >> ellipsis_parameter_declaration ) ) )
enum_name_p = id_p
typedef_name_p = id_p # p793
type_name_pi.setParser( class_name_pi | enum_name_p | typedef_name_p )
# Notes: simplified, alternatives are redondant in typeless context
declarator_id_p = node_f( 'declarator_id', optional_f( '::' ) >> id_expression_pi )
ptr_operator_pi.setParser( (symbol_f('*') >> optional_f( cv_qualifier_seq_p )) \
| symbol_f('&') \
| node_f('pointer_to_member',
optional_f('::') >> nested_name_specifier_pi >> '*' >> optional_f( cv_qualifier_seq_p ) ) )
# defined in A71, declarators, p807 , after cv_qualifier
type_id_pi.setParser( node_f( 'type_id',
type_specifier_seq_pi >> optional_f( abstract_declarator_p ) ) )
# removed infinite left recursion
direct_declarator_p = proxy_f( ( declarator_id_p
| (symbol_f('(') >> declarator_p >> ')') )
>> repeat_f( 0, direct_abstract_declarator_fn_suffix_p
| direct_abstract_declarator_array_suffix_p ) )
# Notes: inversed order to parse pointer to member correctly.
declarator_p.setParser( (ptr_operator_pi >> declarator_p)
| direct_declarator_p )
initializer_list_p = list_f( initializer_clause_p, ',' )
initializer_clause_p.setParser( assignment_expression_pi \
| (symbol_f('{') >> optional_f( initializer_list_p >> optional_f( ',' ) ) >> '}') )
initializer_p = node_f('assign_initializer', symbol_f('=') >> initializer_clause_p ) \
| (symbol_f('(') >> expression_list_pi >> ')')
init_declarator_p = node_f( 'init_declarator', declarator_p >> optional_f( initializer_p ) )
init_declarator_list_p = node_f( 'init_declarators', list_f( init_declarator_p, ',' ) )
type_specifier_seq_pi.setParser( node_f( 'type_specifier',
optional_f(cv_qualifier_seq_p)
>> workaround_type_specifier_pi
>> optional_f(cv_qualifier_seq_p) ) )
function_body_p = compound_statement_pi
#Note: C++ standard, p140:
# a declarator_p in a function definition shall have the form:
# D1 ( parameter_declaration_clause ) optional_f(cv_qualifier_seq) optional_f(exception_specification)
# function_declarator_p implement this instead of using a standard declarator_p.
function_return_type_p = proxy_f( optional_f(cv_qualifier_seq_p)
>> workaround_type_specifier_pi
>> optional_f(cv_qualifier_seq_p) )
function_declarator_p = declarator_id_p >> direct_abstract_declarator_fn_suffix_p
function_definition_start_p = optional_alternative_f( node_f( 'function_return_type', function_return_type_p ),
function_declarator_p )
function_definition_pi = node_f('function_definition',
function_definition_start_p
>> ( (optional_f(ctor_initializer_p) >> function_body_p)
| function_try_block_pi ) )
# ############################## A.7: Declaration ############################
declaration_pi = proxy_f() # forward declaration for recursion
declaration_error_p = node_f( 'declaration_error', block_error_f() )
declaration_seq_pi.setParser( repeat_f( 1, declaration_pi | declaration_error_p ) )
# A.7, C++PL3 p.805-806
# => parse namespace declaration and namespace alias declaration
# Notes: OK. No parsing issue
namespace_body_p = optional_f( node_f( 'namespace_body', declaration_seq_pi ) )
qualified_namespace_specifier_p = node_f( 'namespace_specifier',
optional_f('::') >> optional_f(nested_name_specifier_pi) >> namespace_name_pi )
named_namespace_definition_p = symbol_f('namespace') >> id_p >> '{' >> namespace_body_p >> '}'
unnamed_namespace_definition_p = (symbol_f('namespace') >> '{' >> namespace_body_p >> '}')
namespace_definition_p = node_f( 'named_namespace_def', named_namespace_definition_p) \
| node_f( 'unnamed_namespace_def', unnamed_namespace_definition_p )
namespace_alias_definition_p = node_f('namespace_alias_def',
symbol_f('namespace') >> id_p >> '='
>> qualified_namespace_specifier_p >> eos_p)
# A.7, C++PL3 p.806
# => parse using declaration and directive
# Notes: OK. No parsing issue
using_id_p = node_f( 'using_id',
(optional_f('typename') >> optional_f('::') >> nested_name_specifier_pi >> unqualified_id_pi)
| ( symbol_f('::') >> unqualified_id_pi ) )
using_declaration_p = node_f('using_declaration',
symbol_f('using') >> using_id_p >> eos_p )
using_directive_p = symbol_f('using') >> 'namespace' >> qualified_namespace_specifier_p >> eos_p
# A.7, C++PL3 p.806
# => parse asm definition
asm_keyword_p = one_of_f('asm __asm') # (__asm) => Microsoft Visual C++
asm_definition_p = asm_keyword_p >> '(' >> terminal_f(STRING) >> ')' >> eos_p
# A.7, C++PL3 p.806
# => parse extern specifiction
linkage_specification_begin_p = symbol_f('extern') >> terminal_f(STRING)
linkage_specification_p = node_f( 'linkage_specification',
linkage_specification_begin_p
>> ( (symbol_f('{') >> optional_f(declaration_seq_pi) >> '}')
| declaration_pi ) )
# 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 = proxy_f( id_p )
enumerator_definition_p = node_f( 'enumerator_definition',
enumerator_p >> optional_f( symbol_f('=') >> constant_expression_pi ) )
enum_specifier_p = node_f( 'enum_specifier',
symbol_f('enum') >> optional_f(id_p) >> '{' >>
optional_f(list_f(enumerator_definition_p, ',') )
>> '}' )
forwarded_type_id_p = node_f( 'forwarded_type_id',
optional_f( '::' ) >> optional_f( nested_name_specifier_pi ) >> id_p )
forward_typename_id_p = node_f( 'forwarded_type_id',
optional_f( '::' ) >> optional_f( nested_name_specifier_pi )
>> ( (symbol_f('template') >> template_id_pi ) | id_p ) )
elaborated_type_specifier_p = proxy_f(
node_f( 'forward_class_specifier', class_key_pi >> forwarded_type_id_p )
| node_f( 'forward_enum_specifier', symbol_f('enum') >> forwarded_type_id_p >> look_ahead_f( not_f( '(' ) ) )
| node_f( 'forward_typename_specifier', symbol_f('typename') >> forward_typename_id_p >> look_ahead_f( not_f( '(' ) ) ) )
fundamental_type = repeat_f( 1,
one_of_f( 'char wchar_t bool short int long signed unsigned float double void' ) )
# Notes: possible optimization issue for type_name => may need longuest_f
user_type_specifier_p = proxy_f(
node_f( 'type_name', optional_f('::') >> nested_name_specifier_pi >> optional_f('template') >> template_id_pi )
| node_f( 'type_name', optional_f('::') >> optional_f(nested_name_specifier_pi) >> type_name_pi ) )
simple_type_specifier_p.setParser(
node_f( 'fundamental_type_specifier', fundamental_type )
| user_type_specifier_p )
storage_class_specifier_p = rename_f('storage_class_specifier',
one_of_f('auto register static extern mutable') )
function_specifier_p = rename_f('function_specifier', one_of_f('inline virtual explicit') )
# Hand made rules concerning the order of decl_specifier
# Those rules allow us to detect that the type specifier of 'MyClass instance' is 'MyClass'
# and not 'MyClass insance'.
# typedef cv_qualifiers type cv_qualifiers
# storage_class_specifier(1) function_specifiers cv_qualifiers type cv_qualifiers
# friend 'storage decl'
# type = repeat(1,base_type) | user_type
##decl_specifiers_p = buggy # node_f( 'decl_specifiers', repeat_f( 1, decl_specifier_p ) )
constructor_type_specifier_pi = optional_f(function_specifier_p)
workaround_type_specifier_pi.setParser(
simple_type_specifier_p
| enum_specifier_p
| longuest_f( class_specifier_pi, elaborated_type_specifier_p ) )
standard_decl_specifier_impl_p = proxy_f(
optional_f( storage_class_specifier_p )
>> optional_f( function_specifier_p )
>> optional_f( cv_qualifier_seq_p )
>> workaround_type_specifier_pi
>> optional_f( cv_qualifier_seq_p ) )
standard_decl_specifiers_p = node_f( 'declaration_specifier', standard_decl_specifier_impl_p )
typedef_decl_specifiers_p = node_f( 'typedef_specifier',
symbol_f('typedef')
>> optional_f(cv_qualifier_seq_p)
>> workaround_type_specifier_pi
>> optional_f(cv_qualifier_seq_p) )
friend_decl_specifiers_p = node_f( 'friend_specifier',
symbol_f('friend') >> standard_decl_specifier_impl_p )
decl_specifiers_p = proxy_f( typedef_decl_specifiers_p
| friend_decl_specifiers_p
| standard_decl_specifiers_p )
simple_declaration_p.setParser( node_f( 'simple_declaration',
optional_f( decl_specifiers_p )
>> optional_f( init_declarator_list_p ) >> eos_p ) )
# A.7, C++PL3 p.804
block_declaration_p.setParser( asm_definition_p
| namespace_alias_definition_p
| using_declaration_p
| using_directive_p
| simple_declaration_p )
declaration_pi.setParser( block_declaration_p
| linkage_specification_p
| namespace_definition_p
| function_definition_pi
| pp_directive_pi )
## | template_declaration_p
## | explicit_instantiation_p
## | explicit_specialization_p )
# ############################## A.8: Classes ############################
# A.8, C++PL3 p.808-809
class_name_pi.setParser( id_p )
constant_initializer_p = symbol_f('=') >> constant_expression_pi
pure_specifier_p = symbol_f('=') >> ZeroParser()
# added, somehow the grammar is not parsing this
constructor_declaration_p = constructor_type_specifier_pi >> function_declarator_p
member_declarator_p = longuest_f( declarator_p >> optional_f(pure_specifier_p),
declarator_p >> optional_f(constant_initializer_p),
optional_f(id_p) >> ':' >> constant_expression_pi )
member_declarator_list_p = list_f( member_declarator_p, ',' )
#Notes: not included:
#- opt(::) nested-name-specifier opt(template) unqualified-id
member_declaration_p = proxy_f(
node_f( 'member_function_definition', (function_definition_pi >> optional_f( eos_p )) )
| node_f('member_declaration', optional_f( decl_specifiers_p ) >> optional_f( member_declarator_list_p ) >> eos_p)
| node_f('typeless_function_declaration', constructor_declaration_p >> eos_p)
| using_declaration_p )
# | template_declaration_p
access_specifier_p = one_of_f( "public protected private" )
access_specification_p = node_f( 'access_specification', access_specifier_p >> ':' )
member_specification_p = node_f('member_specification',
repeat_f( 1, access_specification_p | member_declaration_p ) )
class_key_pi.setParser( one_of_f('class struct union' ) )
base_class_name_p = node_f( 'base_class_name',
optional_f('::') >> optional_f(nested_name_specifier_pi) >> class_name_pi )
base_specifier_p = node_f( 'base_class_access',
optional_f('virtual') >> optional_f( access_specifier_p ) >> optional_f('virtual') ) \
>> base_class_name_p
# Notes: could use a subparser here: match ':' - '{'
base_clause_p = node_f( 'class_bases',
symbol_f(':') >> list_f( node_f( 'base_specifier', base_specifier_p ), ',' ) )
class_head_name_p = node_f( 'class_name',
optional_f( nested_name_specifier_pi ) >> (id_p | template_id_pi) )
class_head_p = proxy_f( class_key_pi >> optional_f( class_head_name_p ) >> optional_f( base_clause_p ) )
class_specifier_pi.setParser( node_f( 'class_specifier',
class_head_p >> '{' >> optional_f( member_specification_p ) >> '}' ) )
# ############### A.8.2: Classes, Specials Member Functions ##################
# A.8.2, C++PL3 p.810
conversion_declarator_p = repeat_f( 1, ptr_operator_pi )
conversion_type_id_p = node_f('conversion_type',
type_specifier_seq_pi >> optional_f( conversion_declarator_p ))
conversion_function_id_pi.setParser( node_f('conversion_function_ref',
symbol_f('operator') >> conversion_type_id_p) )
mem_initializer_id = node_f( 'mem_initializer_id',
(optional_f('::') >> optional_f(nested_name_specifier_pi) >> class_name_pi)
| id_p )
mem_initializer_p = node_f( 'mem_initializer',
mem_initializer_id >> '(' >> optional_f( expression_list_pi ) >> ')' )
ctor_initializer_p.setParser( symbol_f( ':' ) >> list_f( mem_initializer_p, ',' ) )
# ############### A.8.2: Classes, OverLoading ##################
# A.8.3, C++PL3 p.810
operator_p = one_of_f( '+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> () []') \
| ( one_of_f( 'new delete' ) >> optional_f( symbol_f('[') >> ']' ) )
operator_function_id_pi.setParser( node_f('operator_function_ref',
symbol_f('operator') >> operator_p) )
# ############################## A.9: Templates ############################
# A.9, C++PL3 p.811
template_declaration_p = proxy_f()
template_parameter_list_p = proxy_f()
template_name_p = proxy_f( id_p )
template_argument_p = assignment_expression_pi | type_id_pi | template_name_p
template_argument_list_p = list_f( template_argument_p, ',' )
template_id_pi.setParser( template_name_p >> '<' >> optional_f( template_argument_list_p ) >> '>' )
type_parameter_p = proxy_f(
one_of_f('class typename') >> optional_f( id_p ) >> optional_f( symbol_f('=') >> type_id_pi )
| ( symbol_f('template') >> '<' >> template_parameter_list_p >> '>' >> 'class' >> optional_f(id_p)
>> optional_f( symbol_f('=') >> template_name_p ) ) )
template_parameter_p = type_parameter_p | parameter_declaration_p
template_parameter_list_p.setParser( list_f( template_parameter_p, ',' ) )
template_declaration_p.setParser( symbol_f('template') >> '<' >> template_parameter_list_p >> '>' >> declaration_pi )
explicit_instantiation_p = proxy_f( symbol_f('template') >> declaration_pi )
explicit_specialization_p = proxy_f( symbol_f('template') >> '<' >> '>' >> declaration_pi )
# ############################## A.10: Exceptions ############################
# A.10, C++PL3 p.812
throw_expression_pi.setParser( symbol_f('throw') >> optional_f( assignment_expression_pi ) )
exception_declaration_p = (type_specifier_seq_pi >> optional_f( declarator_p | abstract_declarator_p )) \
| '...'
handler_p = node_f('exception_handler',
symbol_f('catch') >> '(' >> exception_declaration_p >> ')' >> compound_statement_pi )
handler_seq_p = repeat_f( 1, handler_p )
type_id_list_p = node_f( 'type_id_list', list_f( type_id_pi, ',' ) )
exception_specification_pi.setParser(
node_f('exception_specification',
symbol_f( 'throw' ) >> '(' >> optional_f( type_id_list_p ) >> ')' ) )
try_block_pi.setParser( node_f( 'try_block', symbol_f('try') >> compound_statement_pi >> handler_seq_p ) )
function_try_block_pi.setParser( symbol_f('try') >> optional_f(ctor_initializer_p) >> function_body_p >> handler_seq_p )
# #################################### Debug information for parser ###################
# generated using generateparserdebuginfo.py (Notes: could this be done dynamically ?)
abstract_declarator_p.setName( 'abstract_declarator_p' )
access_specification_p.setName( 'access_specification_p' )
access_specifier_p.setName( 'access_specifier_p' )
accessed_member_p.setName( 'accessed_member_p' )
additive_expression_p.setName( 'additive_expression_p' )
and_expression_p.setName( 'and_expression_p' )
array_operator_suffix_p.setName( 'array_operator_suffix_p' )
asm_definition_p.setName( 'asm_definition_p' )
asm_keyword_p.setName( 'asm_keyword_p' )
assignment_expression_p.setName( 'assignment_expression_p' )
assignment_expression_pi.setName( 'assignment_expression_pi' )
assignment_operator_p.setName( 'assignment_operator_p' )
base_class_name_p.setName( 'base_class_name_p' )
base_clause_p.setName( 'base_clause_p' )
base_specifier_p.setName( 'base_specifier_p' )
block_declaration_p.setName( 'block_declaration_p' )
call_operator_suffix_p.setName( 'call_operator_suffix_p' )
call_or_conversion_expression_p.setName( 'call_or_conversion_expression_p' )
cast_expression_p.setName( 'cast_expression_p' )
cast_keywords_p.setName( 'cast_keywords_p' )
class_head_name_p.setName( 'class_head_name_p' )
class_head_p.setName( 'class_head_p' )
class_key_pi.setName( 'class_key_pi' )
class_name_pi.setName( 'class_name_pi' )
class_or_namespace_name_p.setName( 'class_or_namespace_name_p' )
class_specifier_pi.setName( 'class_specifier_pi' )
compound_statement_pi.setName( 'compound_statement_pi' )
condition_p.setName( 'condition_p' )
conditional_expression_p.setName( 'conditional_expression_p' )
constant_expression_pi.setName( 'constant_expression_pi' )
constant_initializer_p.setName( 'constant_initializer_p' )
constructor_declaration_p.setName( 'constructor_declaration_p' )
constructor_type_specifier_pi.setName( 'constructor_type_specifier_pi' )
conversion_declarator_p.setName( 'conversion_declarator_p' )
conversion_function_id_pi.setName( 'conversion_function_id_pi' )
conversion_type_id_p.setName( 'conversion_type_id_p' )
cppcast_expression_p.setName( 'cppcast_expression_p' )
ctor_initializer_p.setName( 'ctor_initializer_p' )
cv_qualifier_p.setName( 'cv_qualifier_p' )
cv_qualifier_seq_p.setName( 'cv_qualifier_seq_p' )
decl_specifiers_p.setName( 'decl_specifiers_p' )
declaration_pi.setName( 'declaration_pi' )
declaration_seq_pi.setName( 'declaration_seq_pi' )
declaration_statement_p.setName( 'declaration_statement_p' )
declarator_id_p.setName( 'declarator_id_p' )
declarator_p.setName( 'declarator_p' )
delete_expression_p.setName( 'delete_expression_p' )
direct_abstract_declarator_array_suffix_p.setName( 'direct_abstract_declarator_array_suffix_p' )
direct_abstract_declarator_fn_suffix_p.setName( 'direct_abstract_declarator_fn_suffix_p' )
direct_abstract_declarator_p.setName( 'direct_abstract_declarator_p' )
direct_declarator_p.setName( 'direct_declarator_p' )
direct_new_declarator_p.setName( 'direct_new_declarator_p' )
elaborated_type_specifier_p.setName( 'elaborated_type_specifier_p' )
end_p.setName( 'end_p' )
enum_name_p.setName( 'enum_name_p' )
enum_specifier_p.setName( 'enum_specifier_p' )
enumerator_definition_p.setName( 'enumerator_definition_p' )
enumerator_p.setName( 'enumerator_p' )
eos_p.setName( 'eos_p' )
equality_expression_p.setName( 'equality_expression_p' )
exception_declaration_p.setName( 'exception_declaration_p' )
exception_specification_pi.setName( 'exception_specification_pi' )
exclusive_or_expression_p.setName( 'exclusive_or_expression_p' )
explicit_instantiation_p.setName( 'explicit_instantiation_p' )
explicit_specialization_p.setName( 'explicit_specialization_p' )
expression_list_pi.setName( 'expression_list_pi' )
expression_pi.setName( 'expression_pi' )
expression_statement_p.setName( 'expression_statement_p' )
for_init_statement_p.setName( 'for_init_statement_p' )
forward_typename_id_p.setName( 'forward_typename_id_p' )
forwarded_type_id_p.setName( 'forwarded_type_id_p' )
friend_decl_specifiers_p.setName( 'friend_decl_specifiers_p' )
function_body_p.setName( 'function_body_p' )
function_declarator_p.setName( 'function_declarator_p' )
function_definition_pi.setName( 'function_definition_pi' )
function_definition_start_p.setName( 'function_definition_start_p' )
function_return_type_p.setName( 'function_return_type_p' )
function_specifier_p.setName( 'function_specifier_p' )
function_try_block_pi.setName( 'function_try_block_pi' )
handler_p.setName( 'handler_p' )
handler_seq_p.setName( 'handler_seq_p' )
id_expression_pi.setName( 'id_expression_pi' )
id_p.setName( 'id_p' )
inclusive_or_expression_p.setName( 'inclusive_or_expression_p' )
init_declarator_list_p.setName( 'init_declarator_list_p' )
init_declarator_p.setName( 'init_declarator_p' )
initializer_clause_p.setName( 'initializer_clause_p' )
initializer_list_p.setName( 'initializer_list_p' )
initializer_p.setName( 'initializer_p' )
instance_accessor_p.setName( 'instance_accessor_p' )
iteration_statement_p.setName( 'iteration_statement_p' )
jump_statement_p.setName( 'jump_statement_p' )
labeled_statement_p.setName( 'labeled_statement_p' )
linkage_specification_begin_p.setName( 'linkage_specification_begin_p' )
linkage_specification_p.setName( 'linkage_specification_p' )
literal_expression_p.setName( 'literal_expression_p' )
logical_and_expression_p.setName( 'logical_and_expression_p' )
logical_or_expression_p.setName( 'logical_or_expression_p' )
mem_initializer_p.setName( 'mem_initializer_p' )
member_access_suffix_p.setName( 'member_access_suffix_p' )
member_declaration_p.setName( 'member_declaration_p' )
member_declarator_list_p.setName( 'member_declarator_list_p' )
member_declarator_p.setName( 'member_declarator_p' )
member_specification_p.setName( 'member_specification_p' )
multiplicative_expression_p.setName( 'multiplicative_expression_p' )
named_namespace_definition_p.setName( 'named_namespace_definition_p' )
namespace_alias_definition_p.setName( 'namespace_alias_definition_p' )
namespace_body_p.setName( 'namespace_body_p' )
namespace_definition_p.setName( 'namespace_definition_p' )
namespace_name_pi.setName( 'namespace_name_pi' )
nested_name_specifier_pi.setName( 'nested_name_specifier_pi' )
new_declarator_p.setName( 'new_declarator_p' )
new_expression_p.setName( 'new_expression_p' )
new_initializer_p.setName( 'new_initializer_p' )
new_placement_p.setName( 'new_placement_p' )
new_type_id_alt_p.setName( 'new_type_id_alt_p' )
new_type_id_p.setName( 'new_type_id_p' )
new_type_pi.setName( 'new_type_pi' )
operator_function_id_pi.setName( 'operator_function_id_pi' )
operator_p.setName( 'operator_p' )
opt_parameter_decl_assign_p.setName( 'opt_parameter_decl_assign_p' )
parameter_declaration_clause_p.setName( 'parameter_declaration_clause_p' )
parameter_declaration_p.setName( 'parameter_declaration_p' )
parameter_type_p.setName( 'parameter_type_p' )
pm_expression_p.setName( 'pm_expression_p' )
post_incdec_suffix_p.setName( 'post_incdec_suffix_p' )
postfix_expression_p.setName( 'postfix_expression_p' )
primary_expression_p.setName( 'primary_expression_p' )
pseudo_destructor_name_p.setName( 'pseudo_destructor_name_p' )
ptr_operator_pi.setName( 'ptr_operator_pi' )
pure_specifier_p.setName( 'pure_specifier_p' )
qualified_id_p.setName( 'qualified_id_p' )
qualified_namespace_specifier_p.setName( 'qualified_namespace_specifier_p' )
relational_expression_p.setName( 'relational_expression_p' )
selection_statement_p.setName( 'selection_statement_p' )
shift_expression_p.setName( 'shift_expression_p' )
simple_declaration_p.setName( 'simple_declaration_p' )
simple_type_specifier_p.setName( 'simple_type_specifier_p' )
standard_decl_specifier_impl_p.setName( 'standard_decl_specifier_impl_p' )
standard_decl_specifiers_p.setName( 'standard_decl_specifiers_p' )
statement_p.setName( 'statement_p' )
storage_class_specifier_p.setName( 'storage_class_specifier_p' )
template_argument_list_p.setName( 'template_argument_list_p' )
template_argument_p.setName( 'template_argument_p' )
template_declaration_p.setName( 'template_declaration_p' )
template_id_pi.setName( 'template_id_pi' )
template_name_p.setName( 'template_name_p' )
template_name_specifier_p.setName( 'template_name_specifier_p' )
template_parameter_list_p.setName( 'template_parameter_list_p' )
template_parameter_p.setName( 'template_parameter_p' )
throw_expression_pi.setName( 'throw_expression_pi' )
translation_unit_pi.setName( 'translation_unit_pi' )
try_block_pi.setName( 'try_block_pi' )
type_id_expression_p.setName( 'type_id_expression_p' )
type_id_list_p.setName( 'type_id_list_p' )
type_id_pi.setName( 'type_id_pi' )
type_name_pi.setName( 'type_name_pi' )
type_parameter_p.setName( 'type_parameter_p' )
type_specifier_seq_pi.setName( 'type_specifier_seq_pi' )
typedef_decl_specifiers_p.setName( 'typedef_decl_specifiers_p' )
typedef_name_p.setName( 'typedef_name_p' )
unary_expression_p.setName( 'unary_expression_p' )
unary_operator_p.setName( 'unary_operator_p' )
unnamed_namespace_definition_p.setName( 'unnamed_namespace_definition_p' )
unqualified_id_pi.setName( 'unqualified_id_pi' )
user_type_specifier_p.setName( 'user_type_specifier_p' )
using_declaration_p.setName( 'using_declaration_p' )
using_directive_p.setName( 'using_directive_p' )
using_id_p.setName( 'using_id_p' )
workaround_type_specifier_pi.setName( 'workaround_type_specifier_pi' )
--- NEW FILE: grammartest.py ---
import unittest
import mock
import parser
import grammar
import parsingtracker
import string
import tokenizer
from parsertesthelper import *
# * need to modify binary_operator right node so that the operator is a child of binary_operator node.
# * end_p to terminate translation unit
# * error recovery using subparsing and special 'error' matching rules. Will probably need a special parser to
# skip 'a statement' (skip everything until next semi-colon while balancing braces and curly braces. stop if
# closing a curly-brace (means that the end of the block is found) )
def unqualified_id_n( name ):
return TestNode( 'unqualified_id', id_n(name) )
def fundamental_type_n( types ):
return TestNode( 'fundamental_type_specifier', *types.split() )
def fundamental_type_specifier_n( types ):
return TestNode( 'type_specifier', fundamental_type_n( types ) )
def declarator_id_n( *ids ):
return TestNode( 'declarator_id', TestNode( 'unqualified_id', *ids ) )
class GrammarTest(unittest.TestCase,ParserTestHelperMixIn):
"""GrammarTest tests"""
def setUp( self ):
pass
def tearDown( self ):
pass
# Expression
def testLiteralExpression( self ):
self.checkParser( '1', grammar.literal_expression_p )
self.checkParser( '1.0', grammar.literal_expression_p )
self.checkParser( '"abc"', grammar.literal_expression_p )
self.checkParser( "'a'", grammar.literal_expression_p )
self.checkParser( "true", grammar.literal_expression_p )
self.checkParser( "false", grammar.literal_expression_p )
self.checkProducedTree( 'true', grammar.literal_expression_p, ('literal','true') )
self.checkProducedTree( '123.456', grammar.literal_expression_p, ('literal','123.456') )
def testUnqualifiedId( self ):
self.checkProducedNodes( 'xyz', grammar.unqualified_id_pi, id_n( 'xyz' ) )
self.checkProducedNodes( 'operator =', grammar.unqualified_id_pi,
TestNode( 'operator_function_ref', 'operator', '=' ) )
self.checkProducedNodes( 'operator int', grammar.unqualified_id_pi,
TestNode( 'conversion_function_ref',
'operator',
TestNode( 'conversion_type', fundamental_type_specifier_n('int') ) ) )
self.checkProducedNodes( '~ClassName()', grammar.unqualified_id_pi,
TestNode( 'destructor_ref', '~', id_n('ClassName') ) )
def testQualifiedId( self ):
self.checkProducedNodes( '::NamespaceName::ClassName::xyz', grammar.qualified_id_p,
TestNode( 'qualified_id',
'::', id_n('NamespaceName'), '::', id_n('ClassName'), '::', id_n('xyz') ) )
self.checkProducedNodes( 'Name::template Class::xyz', grammar.qualified_id_p,
TestNode( 'qualified_id',
id_n('Name'), '::', 'template', id_n('Class'), '::', id_n('xyz') ) )
self.checkProducedNodes( '::xyz', grammar.qualified_id_p,
TestNode( 'qualified_id', '::', id_n('xyz') ) )
self.checkProducedNodes( '::operator =', grammar.qualified_id_p,
TestNode( 'qualified_id',
'::',
TestNode( 'operator_function_ref', 'operator', '=' ) ) )
self.checkProducedNodes( '::operator int', grammar.qualified_id_p,
TestNode( 'qualified_id',
'::',
TestNode( 'conversion_function_ref',
'operator',
TestNode( 'conversion_type', fundamental_type_specifier_n('int') ) ) ) )
def testPrimaryExpression( self ):
# require: literal_expression_p, qualified_id_p, unqualified_id_pi, id_expression_pi, operator_function_id_p, conversion_function_id_p
self.checkProducedTree( '1', grammar.primary_expression_p, ('literal','1') )
self.checkProducedTree( 'this', grammar.primary_expression_p, ('this_ref','this') )
self.checkProducedNodes( '(this)', grammar.primary_expression_p,
TestNode( 'braced_expr',
'(',
TestNode( 'expression', ('this_ref','this') ),
')' ) )
self.checkParser( '::my_id', grammar.primary_expression_p )
self.checkParser( 'MyNamespace::my_var', grammar.primary_expression_p )
self.checkParser( '::MyNamespace::MyClass::member_', grammar.primary_expression_p )
self.checkParser( '::operator =', grammar.primary_expression_p )
self.checkParser( 'Base::operator =', grammar.primary_expression_p )
self.checkProducedNodes( 'xyz', grammar.primary_expression_p,
TestNode( 'unqualified_id', id_n( 'xyz' ) ) )
self.checkProducedNodes( 'operator =', grammar.primary_expression_p,
TestNode( 'unqualified_id',
TestNode( 'operator_function_ref', 'operator', '=' ) ) )
self.checkProducedNodes( 'operator int', grammar.primary_expression_p,
TestNode( 'unqualified_id',
TestNode( 'conversion_function_ref',
'operator',
TestNode( 'conversion_type', fundamental_type_specifier_n('int') ) ) ) )
self.checkProducedNodes( '~ClassName()', grammar.primary_expression_p,
TestNode( 'unqualified_id',
TestNode( 'destructor_ref', '~', id_n('ClassName') ) ) )
def testPostFixExpressionSuffix( self ):
self.checkProducedNodes( '[123]', grammar.array_operator_suffix_p,
TestNode('array_index', '[', JokerTestNode( 'expression' ), ']') )
self.checkParser( '()', grammar.call_operator_suffix_p )
self.checkParser( '(123)', grammar.call_operator_suffix_p )
self.checkParser( '(123,456)', grammar.call_operator_suffix_p )
self.checkParser( '.my_member', grammar.member_access_suffix_p )
self.checkParser( '->my_member', grammar.member_access_suffix_p )
self.checkParser( '->template Parent::my_member', grammar.member_access_suffix_p )
self.checkParser( '.~MyClass', grammar.member_access_suffix_p )
self.checkParser( '.::Base::~MyClass', grammar.member_access_suffix_p )
self.checkParser( '.MyParent::~MyClass', grammar.member_access_suffix_p )
self.checkParser( '++', grammar.post_incdec_suffix_p )
self.checkParser( '--', grammar.post_incdec_suffix_p )
def testPostFixExpression( self ):
# require: primary_expression_p
self.checkParser( '(this)', grammar.postfix_expression_p )
self.checkParser( 'my_id', grammar.postfix_expression_p )
self.checkProducedNodes( 'arr[1][2]', grammar.postfix_expression_p,
TestNode( 'array_access',
TestNode( 'array_access',
JokerTestNode( 'unqualified_id' ),
TestNode('array_index', '[', JokerTestNode( 'expression' ), ']') ), #[1]
TestNode('array_index', '[', JokerTestNode( 'expression' ), ']') ) ) #[2]
self.checkProducedTree( 'this', grammar.postfix_expression_p, ('this_ref','this') )
self.checkParser( 'int(1234)', grammar.postfix_expression_p )
self.checkParser( 'MyClass(1234)', grammar.postfix_expression_p )
self.checkParser( 'MyNamespace::MyClass(1234)', grammar.postfix_expression_p )
self.checkParser( 'typeid( 1234.0 )', grammar.postfix_expression_p )
self.checkParser( 'typeid( int )', grammar.postfix_expression_p )
self.checkParser( 'static_cast<int>(1234)', grammar.postfix_expression_p )
self.checkParser( 'dynamic_cast<Derived>(p)', grammar.postfix_expression_p )
self.checkParser( 'my_array[1]', grammar.postfix_expression_p )
self.checkParser( 'my_function(1)', grammar.postfix_expression_p )
self.checkParser( 'my_instance->my_member', grammar.postfix_expression_p )
self.checkParser( 'my_instance.BaseClass::my_member', grammar.postfix_expression_p )
self.checkParser( 'my_instance->~MyClass', grammar.postfix_expression_p )
self.checkParser( 'my_instance.MyClass::~MyClass()', grammar.postfix_expression_p, 0 )
self.checkParser( 'my_variable++', grammar.postfix_expression_p )
self.checkParser( 'my_variable--', grammar.postfix_expression_p )
self.checkParser( 'my_instance->my_member++', grammar.postfix_expression_p )
self.checkParser( '(my_instance->my_member)->my_member++', grammar.postfix_expression_p )
self.checkParser( 'typename ::Base::attribute(1,2)', grammar.postfix_expression_p )
def testDeleteExpressionParser( self ):
self.checkParser( 'delete p', grammar.delete_expression_p )
self.checkParser( '::delete p', grammar.delete_expression_p )
self.checkParser( 'delete ++p', grammar.delete_expression_p )
self.checkProducedNodes( '::delete [] p', grammar.delete_expression_p,
TestNode( 'delete_operator', '::', 'delete', '[', ']', unqualified_id_n('p') ) )
self.checkParser( 'delete x.z', grammar.delete_expression_p )
def testNewTypeIdParser( self ):
self.checkParser( 'int', grammar.new_type_id_alt_p )
self.checkParser( 'int *', grammar.new_type_id_alt_p )
self.checkParser( 'UserType[10][5]', grammar.new_type_id_alt_p )
self.checkParser( '(UserType*[10][5])', grammar.new_type_id_alt_p )
self.checkParserFail( 'const UserType', grammar.new_type_id_alt_p )
def testNewExpressionParser( self ):
self.checkProducedNodes( 'new int', grammar.new_expression_p,
TestNode( 'new_operator', 'new',
TestNode('new_type_id', fundamental_type_n('int') ) ) )
self.checkParser( 'new int(3)', grammar.new_expression_p )
self.checkProducedNodes( '::new (__FILE__,__LINE__) int(3)', grammar.new_expression_p,
TestNode( 'new_operator', '::', 'new',
TestNode( 'new_placement', '(',
TestNode( 'expression_list',
TestNode( 'assignment_expression',
unqualified_id_n('__FILE__') ),
',',
TestNode( 'assignment_expression',
unqualified_id_n('__LINE__') ) ),
')'),
TestNode( 'new_type_id', fundamental_type_n('int') ),
TestNode( 'new_initializer', '(',
TestNode( 'expression_list',
TestNode( 'assignment_expression',
('literal','3') ) ),
')' ) ) )
self.checkParser( 'new (int)(3)', grammar.new_expression_p )
self.checkParser( 'new int[10](7)', grammar.new_expression_p )
self.checkParser( 'new MyType[10](7)', grammar.new_expression_p )
self.checkParser( 'new (UserType)(7)', grammar.new_expression_p )
self.checkParser( 'new (UserType(3))(UserType)(7)', grammar.new_expression_p )
# need more test concerning new_type_id (should be restricted to plain type without cv)
#expression_list structure for new_initializer need to be defined
def testUnaryExpressionParser( self ):
#require postfix_expression_p
self.checkProducedTree( 'this', grammar.unary_expression_p, ('this_ref','this') )
self.checkParser( '(this)', grammar.unary_expression_p )
self.checkProducedNodes( '++my_variable', grammar.unary_expression_p,
TestNode( 'unary_operator',
'++',
unqualified_id_n('my_variable') ) )
self.checkProducedNodes( '!my_variable', grammar.unary_expression_p,
TestNode( 'unary_operator',
'!',
unqualified_id_n('my_variable') ) )
self.checkParser( '--my_variable', grammar.unary_expression_p )
self.checkParser( '-my_variable', grammar.unary_expression_p )
self.checkProducedNodes( 'sizeof !my_variable', grammar.unary_expression_p,
TestNode( 'sizeof_operator',
'sizeof',
TestNode( 'unary_operator', '!',
unqualified_id_n('my_variable') ) ) )
self.checkProducedNodes( 'sizeof(++my_variable)', grammar.unary_expression_p,
TestNode( 'sizeof_operator',
'sizeof',
TestNode( 'braced_expr',
'(',
TestNode( 'expression',
TestNode( 'unary_operator', '++',
unqualified_id_n('my_variable') ) ),
')' ) ) )
self.checkParser( 'new int[10]', grammar.unary_expression_p )
self.checkParser( 'delete p', grammar.unary_expression_p )
self.checkParser( '(my_instance->my_member)->my_member++', grammar.unary_expression_p )
def testPMExpression( self ):
self.checkProducedTree( '1234', grammar.pm_expression_p, ('literal','1234') )
def testLogicalOrExpressionParser( self ):
self.checkProducedTree( '1234', grammar.logical_or_expression_p, ('literal','1234') )
self.checkParser( 'my_instance->*my_member', grammar.logical_or_expression_p )
self.checkParser( 'sizeof ++my_variable', grammar.logical_or_expression_p )
self.checkParser( '34 * 35', grammar.logical_or_expression_p )
self.checkProducedNodes( '34 * 35', grammar.logical_or_expression_p,
TestNode( 'binary_operator',
...
[truncated message content] |