Remove old scope/type/value analysis, fix omissions where Declaration.storage_class... master
authorNick Downing <nick@ndcode.org>
Wed, 27 Dec 2023 13:03:21 +0000 (00:03 +1100)
committerNick Downing <nick@ndcode.org>
Wed, 27 Dec 2023 13:36:16 +0000 (00:36 +1100)
ansi_c.l
ansi_c.py
ansi_c.t
ansi_c.y
declarator.py
post_process.py

index e057770..7613b55 100644 (file)
--- a/ansi_c.l
+++ b/ansi_c.l
@@ -114,24 +114,24 @@ __func__                          return y_tab.STRING_LITERAL # revisit
   return y_tab.IDENTIFIER
 }
 
-(?E{y_tab.build, t_def.ExpressionFloatingConstant}{FRACTIONAL_CONSTANT}(?E{t_def.ExponentPart}{EXPONENT_PART}?){FLOATING_SUFFIX}?) |
-(?E{y_tab.build, t_def.ExpressionFloatingConstant}{DIGIT_SEQUENCE}(?E{t_def.Text}"")(?E{t_def.ExponentPart}{EXPONENT_PART}){FLOATING_SUFFIX}?) {
+(?E{t_def.ExpressionFloatingConstant}{FRACTIONAL_CONSTANT}(?E{t_def.ExponentPart}{EXPONENT_PART}?){FLOATING_SUFFIX}?) |
+(?E{t_def.ExpressionFloatingConstant}{DIGIT_SEQUENCE}(?E{t_def.Text}"")(?E{t_def.ExponentPart}{EXPONENT_PART}){FLOATING_SUFFIX}?) {
   return y_tab.FLOATING_CONSTANT
 }
 
-(?E{y_tab.build, t_def.ExpressionIntegerConstant, base = 10}{DECIMAL_CONSTANT}{INTEGER_SUFFIX}?) |
-(?E{y_tab.build, t_def.ExpressionIntegerConstant, base = 8}{OCTAL_CONSTANT}{INTEGER_SUFFIX}?) |
-(?E{y_tab.build, t_def.ExpressionIntegerConstant, base = 16}{HEXADECIMAL_CONSTANT}{INTEGER_SUFFIX}?) {
+(?E{t_def.ExpressionIntegerConstant, base = 10}{DECIMAL_CONSTANT}{INTEGER_SUFFIX}?) |
+(?E{t_def.ExpressionIntegerConstant, base = 8}{OCTAL_CONSTANT}{INTEGER_SUFFIX}?) |
+(?E{t_def.ExpressionIntegerConstant, base = 16}{HEXADECIMAL_CONSTANT}{INTEGER_SUFFIX}?) {
   return y_tab.INTEGER_CONSTANT
 }
 
-(?E{y_tab.build, t_def.ExpressionCharacterConstant, wide = False}'{C_CHAR_SEQUENCE}') |
-(?E{y_tab.build, t_def.ExpressionCharacterConstant, wide = True}L'{C_CHAR_SEQUENCE}') {
+(?E{t_def.ExpressionCharacterConstant, wide = False}'{C_CHAR_SEQUENCE}') |
+(?E{t_def.ExpressionCharacterConstant, wide = True}L'{C_CHAR_SEQUENCE}') {
   return y_tab.CHARACTER_CONSTANT
 }
 
-(?E{y_tab.build, t_def.ExpressionStringLiteral, wide = False}\"{S_CHAR_SEQUENCE}\") |
-(?E{y_tab.build, t_def.ExpressionStringLiteral, wide = True}L\"{S_CHAR_SEQUENCE}\") {
+(?E{t_def.ExpressionStringLiteral, wide = False}\"{S_CHAR_SEQUENCE}\") |
+(?E{t_def.ExpressionStringLiteral, wide = True}L\"{S_CHAR_SEQUENCE}\") {
   return y_tab.STRING_LITERAL
 }
 
index c593a90..a5923a9 100755 (executable)
--- a/ansi_c.py
+++ b/ansi_c.py
@@ -51,23 +51,12 @@ with open(in_file) as fin:
   y_tab.last_token = -1
   y_tab.doing_typedef = False
   y_tab.typedef_stack = [set()]
-  y_tab.scope = t_def.Scope()
-  y_tab.next_temp_name = 0
-  translation_unit = y_tab.yyparse(
-    t_def.TranslationUnit,
-    scope = y_tab.scope
-  )
+  translation_unit = y_tab.yyparse(t_def.TranslationUnit)
+translation_unit.scope = t_def.Scope()
+translation_unit.post_process(post_process.Context())
 element.serialize(translation_unit, 'a.xml', 'utf-8')
 translation_unit = element.deserialize('a.xml', t_def.factory, 'utf-8')
 translation_unit.fix_type_sharing()
 element.serialize(translation_unit, 'b.xml', 'utf-8')
-translation_unit.strip_scope_analysis()
+translation_unit.strip_redundancy()
 element.serialize(translation_unit, 'c.xml', 'utf-8')
-translation_unit.scope = t_def.Scope()
-translation_unit.post_process(post_process.Context())
-element.serialize(translation_unit, 'd.xml', 'utf-8')
-translation_unit = element.deserialize('d.xml', t_def.factory, 'utf-8')
-translation_unit.fix_type_sharing()
-element.serialize(translation_unit, 'e.xml', 'utf-8')
-#translation_unit.strip_redundancy()
-#element.serialize(translation_unit, 'f.xml', 'utf-8')
index e0f1912..b7dccee 100644 (file)
--- a/ansi_c.t
+++ b/ansi_c.t
@@ -666,65 +666,6 @@ def strip_redundancy(self):
       i += 1
   Node.strip_redundancy(self)
 
-# temporary
-@method(Node)
-def strip_scope_analysis(self):
-  for i in range(len(self.children)):
-    self.children[i] = self.children[i].strip_scope_analysis()
-  return self
-@method(ItemList)
-def strip_scope_analysis(self):
-  self.scope = None
-  return Node.strip_scope_analysis(self)
-@method(EnumSpecifier)
-def strip_scope_analysis(self):
-  self.scope_tag = None
-  return Specifier.strip_scope_analysis(self)
-@method(ExpressionIdentifier)
-def strip_scope_analysis(self):
-  self.scope_identifier = None
-  return Expression.strip_scope_analysis(self)
-@method(FunctionDefinition)
-def strip_scope_analysis(self):
-  self.scope_identifier = None
-  return Node.strip_scope_analysis(self)
-@method(Identifier)
-def strip_scope_analysis(self):
-  self.scope_identifier = None
-  return Node.strip_scope_analysis(self)
-@method(InitDeclarator)
-def strip_scope_analysis(self):
-  self.scope_identifier = None
-  return Node.strip_scope_analysis(self)
-@method(ParameterDeclaration)
-def strip_scope_analysis(self):
-  self.scope_identifier = None
-  return Node.strip_scope_analysis(self)
-@method(StructSpecifier)
-def strip_scope_analysis(self):
-  self.scope_tag = None
-  return Specifier.strip_scope_analysis(self)
-@method(TagIdentifier)
-def strip_scope_analysis(self):
-  self.scope_tag = None
-  return Node.strip_scope_analysis(self)
-@method(TypedefName)
-def strip_scope_analysis(self):
-  self.scope_identifier = None
-  return Specifier.strip_scope_analysis(self)
-@method(UnionSpecifier)
-def strip_scope_analysis(self):
-  self.scope_tag = None
-  return Specifier.strip_scope_analysis(self)
-@method(ExpressionCast)
-def strip_scope_analysis(self):
-  # not really scope analysis but strip casts that were not in the original
-  Expression.strip_scope_analysis(self)
-  if len(self.children[0].children) == 0:
-    return self.children[1]
-  return self
-del strip_scope_analysis
-
 # deserializing the tree creates new copies of primitive types
 # this can waste space if the tree is subsequently modified using
 # primitive types defined in this file -- fix deserialized tree
index b532fa7..4c3d461 100644 (file)
--- a/ansi_c.y
+++ b/ansi_c.y
   # used to suppress TYPEDEF_NAME after '.', PTR_OP, STRUCT, UNION, ENUM token
   last_token = -1
 
-  # this is set to the global scope object before calling yyparse(), and then
-  # it tracks the current scope whilst inside functions and block statements
-  # note: global scope object will be set in the TranslationUnit after parsing
-  scope = None
-
-  # used for parsing function_definition or declaration
-  # as both contain a declaration_specifier_list and at least one declarator,
-  # we don t know what it is until we see the "{" of the function_definition or
-  # the "," or ";" of the declaration -- but either way we need to know the
-  # declaration_specifier_list in order to do scope analysis of the declarator,
-  # so we save the below fields when we parse the declaration_specifier_list
-  # then refer to them when we parse the declarators (they must be associated)
-  _base_type = None
-  storage_class = -1
-
-  # new way
   # used for parsing function_definition or declaration
   # as both contain a declaration_specifier_list and at least one declarator,
   # we don t know what it is until we see the "{" of the function_definition or
   # (but typedef is ignored for function_definition, as it doesn t make sense)
   doing_typedef = False
 
-  # new way
   # stack of sets, pushed when entering a new ItemList (TranslationUnit or
   # BlockItemList), and containing the identifiers of active typedef names
   # note: must be set to [set()] before calling yyparse(), for global scope
   # note: shadowing is not implemented, it is impossible to shadow a typedef
   typedef_stack = []
-
-  # used for parsing function_definition
-  # the expression in the "return" statement will be coerced to this type
-  return_type = None
-
-  # used for parsing switch statement 
-  # the expression in the "case" statement will be coerced to this type
-  switch_type = []
-
-  # used for parsing initializer
-  # the initializer expression will be coerced to this type, or if it is a
-  # compound type, the constituent types will be stacked while parsing { }
-  # the items pushed on the stack look like [type, 0, 0] consisting of the
-  # type, the index (either an array index or a structure member index, for
-  # sequential initialization without designator), and max index seen so far
-  initializer_stack = []
-
-  # next temporary names for anonymous struct etc, set to 0 before yyparse()
-  next_anonymous_name = 0
 %}
 
 %%
 
 primary_expression
-  : expression_identifier {
-    expression_identifier = yy_element_stack[-1].children[0]
-    name = expression_identifier.text[0]
-    #print('ref', name)
-    i = scope
-    while i is not None:
-      if name in i.identifiers:
-        expression_identifier.scope_identifier = i.identifiers[name]
-        break
-      i = i.enclosing_scope
-    else:
-      print('undefined identifier:', name)
-      assert False
-
-    expression_identifier.calc_type()
-    expression_identifier.calc_value()
-  }
+  : expression_identifier
   | constant
   | STRING_LITERAL
   | '(' expression ')'
@@ -139,82 +87,13 @@ type_name_or_default
 
 postfix_expression
   : primary_expression
-  | %space (?E{build, t_def.ExpressionIndex}postfix_expression '[' expression ']')
-  | %space (?E{build, t_def.ExpressionCall}postfix_expression '(' %space (?E{t_def.ArgumentExpressionList}argument_expression_list_opt) ')') {
-    expression_call = yy_element_stack[-1].children[0]
-
-    function_type = expression_call.children[0].type
-    assert isinstance(function_type, t_def.TypeFunction)
-    actual_parameters = expression_call.children[1]
-
-    if isinstance(function_type, t_def.TypeFunctionANSI):
-      n_formal_parameters = len(function_type.formal_parameters)
-      if function_type.varargs:
-        assert len(actual_parameters.children) >= n_formal_parameters
-      else:
-        assert len(actual_parameters.children) == n_formal_parameters
-
-      # process typed parameters
-      for i in range(n_formal_parameters):
-        actual_parameters.children[i] = t_def.add_cast(
-          function_type.formal_parameters[i],
-          actual_parameters.children[i]
-        )
-    elif isinstance(function_type, t_def.TypeFunctionKAndR):
-      n_formal_parameters = 0 # for non-ANSI, treat all parameters as varargs
-    else:
-      assert False
-
-    # process remaining (untyped) parameters
-    for i in range(n_formal_parameters, len(actual_parameters.children)):
-      rank = actual_parameters.children[i].type.rank
-      if rank >= 0 and rank < t_def.INT_RANK:
-        actual_parameters.children[i] = t_def.add_cast(
-          t_def.type_signed_int,
-          actual_parameters.children[i]
-        )
-      elif rank >= t_def.FLOAT_RANK and rank < t_def.DOUBLE_RANK:
-        actual_parameters.children[i] = t_def.add_cast(
-          t_def.rank_to_type[rank + t_def.DOUBLE_RANK - t_def.FLOAT_RANK],
-          actual_parameters.children[i]
-        )
-  }
-  | %space (?E{build, t_def.ExpressionMember}postfix_expression '.' member_identifier)
-  | %space (?E{build, t_def.ExpressionMemberDereference}postfix_expression PTR_OP member_identifier)
-  | %space (?E{build, t_def.ExpressionPostIncrement}postfix_expression INC_OP)
-  | %space (?E{build, t_def.ExpressionPostDecrement}postfix_expression DEC_OP)
-  | %space (?E{build, t_def.ExpressionArrayOrStruct}'(' type_name ')' {
-    type_name = yy_element_stack[-4].children[0]
-    assert isinstance(type_name, t_def.TypeName)
-
-    # this global variable is needed whilst parsing the initializer
-    assert len(initializer_stack) == 0
-    initializer_stack.append([type_name.type, 0, 0])
-  } '{' %space (?E{t_def.DesignatorInitializerList}designator_initializer_list_comma_opt) '}') {
-    # this global variable was needed whilst parsing the initializer
-    _, _, max_index = initializer_stack.pop()
-    assert len(initializer_stack) == 0
-
-    expression_array_or_struct_or_union = yy_element_stack[-1].children[0]
-    _type = expression_array_or_struct_or_union.children[0].type
-    assert (
-      isinstance(_type, t_def.TypeArray) or
-      isinstance(_type, t_def.TypeStructOrUnion)
-    )
-
-    if (
-      isinstance(_type, t_def.TypeArray) and
-      _type.element_count == -1 and
-      len(init_declarator.children) >= 2
-    ):
-      # size of indeterminate sized array can be deduced from initializer
-      element_size = _type.element_type.size
-      assert element_size >= 0 # must be of determinate size
-      _type.size = max_index * element_size
-      _type.element_count = max_index
-    else:
-      assert _type.size >= 0 # must be of determinate size
-  }
+  | %space (?E{t_def.ExpressionIndex}postfix_expression '[' expression ']')
+  | %space (?E{t_def.ExpressionCall}postfix_expression '(' %space (?E{t_def.ArgumentExpressionList}argument_expression_list_opt) ')')
+  | %space (?E{t_def.ExpressionMember}postfix_expression '.' member_identifier)
+  | %space (?E{t_def.ExpressionMemberDereference}postfix_expression PTR_OP member_identifier)
+  | %space (?E{t_def.ExpressionPostIncrement}postfix_expression INC_OP)
+  | %space (?E{t_def.ExpressionPostDecrement}postfix_expression DEC_OP)
+  | %space (?E{t_def.ExpressionArrayOrStruct}'(' type_name ')' '{' %space (?E{t_def.DesignatorInitializerList}designator_initializer_list_comma_opt) '}')
   ;
 
 argument_expression_list_opt
@@ -229,115 +108,107 @@ argument_expression_list
 
 unary_expression
   : postfix_expression
-  | %space (?E{build, t_def.ExpressionPreIncrement}INC_OP unary_expression)
-  | %space (?E{build, t_def.ExpressionPreDecrement}DEC_OP unary_expression)
-  | %space (?E{build, t_def.ExpressionAddressOf}'&' cast_expression)
-  | %space (?E{build, t_def.ExpressionDereference}'*' cast_expression)
-  | %space (?E{build, t_def.ExpressionPlus}'+' cast_expression)
-  | %space (?E{build, t_def.ExpressionMinus}'-' cast_expression)
-  | %space (?E{build, t_def.ExpressionBitwiseNot}'~' cast_expression)
-  | %space (?E{build, t_def.ExpressionLogicalNot}'!' cast_expression)
-  | %space (?E{build, t_def.ExpressionSizeOfExpression}SIZEOF unary_expression)
-  | %space (?E{build, t_def.ExpressionSizeOfType}SIZEOF '(' type_name ')')
-  | %space (?E{build, t_def.ExpressionAlignOfType}ALIGNOF '(' type_name ')')
+  | %space (?E{t_def.ExpressionPreIncrement}INC_OP unary_expression)
+  | %space (?E{t_def.ExpressionPreDecrement}DEC_OP unary_expression)
+  | %space (?E{t_def.ExpressionAddressOf}'&' cast_expression)
+  | %space (?E{t_def.ExpressionDereference}'*' cast_expression)
+  | %space (?E{t_def.ExpressionPlus}'+' cast_expression)
+  | %space (?E{t_def.ExpressionMinus}'-' cast_expression)
+  | %space (?E{t_def.ExpressionBitwiseNot}'~' cast_expression)
+  | %space (?E{t_def.ExpressionLogicalNot}'!' cast_expression)
+  | %space (?E{t_def.ExpressionSizeOfExpression}SIZEOF unary_expression)
+  | %space (?E{t_def.ExpressionSizeOfType}SIZEOF '(' type_name ')')
+  | %space (?E{t_def.ExpressionAlignOfType}ALIGNOF '(' type_name ')')
   ;
 
 cast_expression
   : unary_expression
-  | %space (?E{build, t_def.ExpressionCast}'(' type_name ')' cast_expression)
+  | %space (?E{t_def.ExpressionCast}'(' type_name ')' cast_expression)
   ;
 
 multiplicative_expression
   : cast_expression
-  | %space (?E{build, t_def.ExpressionMultiply}multiplicative_expression '*' cast_expression)
-  | %space (?E{build, t_def.ExpressionDivide}multiplicative_expression '/' cast_expression)
-  | %space (?E{build, t_def.ExpressionModulo}multiplicative_expression '%' cast_expression)
+  | %space (?E{t_def.ExpressionMultiply}multiplicative_expression '*' cast_expression)
+  | %space (?E{t_def.ExpressionDivide}multiplicative_expression '/' cast_expression)
+  | %space (?E{t_def.ExpressionModulo}multiplicative_expression '%' cast_expression)
   ;
 
 additive_expression
   : multiplicative_expression
-  | %space (?E{build, t_def.ExpressionAdd}additive_expression '+' multiplicative_expression)
-  | %space (?E{build, t_def.ExpressionSubtract}additive_expression '-' multiplicative_expression)
+  | %space (?E{t_def.ExpressionAdd}additive_expression '+' multiplicative_expression)
+  | %space (?E{t_def.ExpressionSubtract}additive_expression '-' multiplicative_expression)
   ;
 
 shift_expression
   : additive_expression
-  | %space (?E{build, t_def.ExpressionShiftLeft}shift_expression LEFT_OP additive_expression)
-  | %space (?E{build, t_def.ExpressionShiftRight}shift_expression RIGHT_OP additive_expression)
+  | %space (?E{t_def.ExpressionShiftLeft}shift_expression LEFT_OP additive_expression)
+  | %space (?E{t_def.ExpressionShiftRight}shift_expression RIGHT_OP additive_expression)
   ;
 
 relational_expression
   : shift_expression
-  | %space (?E{build, t_def.ExpressionLessThan}relational_expression '<' shift_expression)
-  | %space (?E{build, t_def.ExpressionGreaterThan}relational_expression '>' shift_expression)
-  | %space (?E{build, t_def.ExpressionLessThanOrEqual}relational_expression LE_OP shift_expression)
-  | %space (?E{build, t_def.ExpressionGreaterThanOrEqual}relational_expression GE_OP shift_expression)
+  | %space (?E{t_def.ExpressionLessThan}relational_expression '<' shift_expression)
+  | %space (?E{t_def.ExpressionGreaterThan}relational_expression '>' shift_expression)
+  | %space (?E{t_def.ExpressionLessThanOrEqual}relational_expression LE_OP shift_expression)
+  | %space (?E{t_def.ExpressionGreaterThanOrEqual}relational_expression GE_OP shift_expression)
   ;
 
 equality_expression
   : relational_expression
-  | %space (?E{build, t_def.ExpressionEqual}equality_expression EQ_OP relational_expression)
-  | %space (?E{build, t_def.ExpressionNotEqual}equality_expression NE_OP relational_expression)
+  | %space (?E{t_def.ExpressionEqual}equality_expression EQ_OP relational_expression)
+  | %space (?E{t_def.ExpressionNotEqual}equality_expression NE_OP relational_expression)
   ;
 
 and_expression
   : equality_expression
-  | %space (?E{build, t_def.ExpressionBitwiseAnd}and_expression '&' equality_expression)
+  | %space (?E{t_def.ExpressionBitwiseAnd}and_expression '&' equality_expression)
   ;
 
 exclusive_or_expression
   : and_expression
-  | %space (?E{build, t_def.ExpressionExclusiveOr}exclusive_or_expression '^' and_expression)
+  | %space (?E{t_def.ExpressionExclusiveOr}exclusive_or_expression '^' and_expression)
   ;
 
 inclusive_or_expression
   : exclusive_or_expression
-  | %space (?E{build, t_def.ExpressionBitwiseOr}inclusive_or_expression '|' exclusive_or_expression)
+  | %space (?E{t_def.ExpressionBitwiseOr}inclusive_or_expression '|' exclusive_or_expression)
   ;
 
 logical_and_expression
   : inclusive_or_expression
-  | %space (?E{build, t_def.ExpressionLogicalAnd}logical_and_expression AND_OP inclusive_or_expression)
+  | %space (?E{t_def.ExpressionLogicalAnd}logical_and_expression AND_OP inclusive_or_expression)
   ;
 
 logical_or_expression
   : logical_and_expression
-  | %space (?E{build, t_def.ExpressionLogicalOr}logical_or_expression OR_OP logical_and_expression)
+  | %space (?E{t_def.ExpressionLogicalOr}logical_or_expression OR_OP logical_and_expression)
   ;
 
 conditional_expression
   : logical_or_expression
-  | %space (?E{build, t_def.ExpressionConditional}logical_or_expression '?' expression ':' conditional_expression)
+  | %space (?E{t_def.ExpressionConditional}logical_or_expression '?' expression ':' conditional_expression)
   ;
 
 /* occurs in array declarator */
 assignment_expression_or_asterisk_opt
-  : %space (?E{build, t_def.ExpressionEmpty})
+  : %space (?E{t_def.ExpressionEmpty})
   | %space (?E{t_def.ExpressionAsterisk}'*')
-  | assignment_expression {
-    container = yy_element_stack[-1]
-    assert isinstance(container.children[0], t_def.Expression)
-    if container.children[0].type != t_def.type_size_t:
-      container.children[0] = t_def.add_cast(
-        t_def.type_size_t,
-        container.children[0]
-      )
-  }
+  | assignment_expression
   ;
 
 assignment_expression
   : conditional_expression
-  | %space (?E{build, t_def.ExpressionEqualAssignment}unary_expression '=' assignment_expression)
-  | %space (?E{build, t_def.ExpressionMultiplyAssignment}unary_expression MUL_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionDivideAssignment}unary_expression DIV_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionModuloAssignment}unary_expression MOD_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionAddAssignment}unary_expression ADD_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionSubtractAssignment}unary_expression SUB_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionShiftLeftAssignment}unary_expression LEFT_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionShiftRightAssignment}unary_expression RIGHT_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionBitwiseAndAssignment}unary_expression AND_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionExclusiveOrAssignment}unary_expression XOR_ASSIGN assignment_expression)
-  | %space (?E{build, t_def.ExpressionBitwiseOrAssignment}unary_expression OR_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionEqualAssignment}unary_expression '=' assignment_expression)
+  | %space (?E{t_def.ExpressionMultiplyAssignment}unary_expression MUL_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionDivideAssignment}unary_expression DIV_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionModuloAssignment}unary_expression MOD_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionAddAssignment}unary_expression ADD_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionSubtractAssignment}unary_expression SUB_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionShiftLeftAssignment}unary_expression LEFT_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionShiftRightAssignment}unary_expression RIGHT_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionBitwiseAndAssignment}unary_expression AND_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionExclusiveOrAssignment}unary_expression XOR_ASSIGN assignment_expression)
+  | %space (?E{t_def.ExpressionBitwiseOrAssignment}unary_expression OR_ASSIGN assignment_expression)
   ;
 
 expression_opt
@@ -347,21 +218,13 @@ expression_opt
 
 expression
   : assignment_expression
-  | %space (?E{build, t_def.ExpressionComma}expression ',' assignment_expression)
+  | %space (?E{t_def.ExpressionComma}expression ',' assignment_expression)
   ;
 
 /* occurs in enumerator */
 equals_constant_expression_opt
   :
-  | '=' constant_expression {
-    container = yy_element_stack[-1]
-    assert isinstance(container.children[0], t_def.Expression)
-    if container.children[0].type != t_def.type_signed_int:
-      container.children[0] = t_def.add_cast(
-        t_def.type_signed_int,
-        container.children[0]
-      )
-  }
+  | '=' constant_expression
   ;
 
 constant_expression
@@ -370,19 +233,6 @@ constant_expression
 
 declaration
   : %space (?E{t_def.Declaration}declaration_specifier_list1 %space (?E{t_def.InitDeclaratorList}init_declarator_list_opt) ';') {
-    global _base_type, storage_class
-
-    # in general the storage class is taken from the ScopeIdentifier when we
-    # regenerate the redundant information, but we also need some information
-    # about the declaration itself to know if the declaration is a forward one
-    declaration = yy_element_stack[-1].children[0]
-    declaration.storage_class = storage_class
-
-    # these globals were needed whilst parsing the list of init declarators
-    _base_type = None
-    storage_class = -1
-
-    # new way
     global doing_typedef
 
     # this global is set by declaration_specifier_list1 if doing typedef,
@@ -395,16 +245,6 @@ declaration
 /* intercept declaration_specifier_list to save _base_type and storage_class */
 declaration_specifier_list1
   : %space (?E{t_def.DeclarationSpecifierList}declaration_specifier_list) {
-    global _base_type, storage_class
-
-    declaration_specifier_list = yy_element_stack[-1].children[0]
-
-    # these globals are needed whilst parsing the function body or init
-    # declarators, we don t know which until we see the '{', ',' or ';'
-    _base_type = declaration_specifier_list.get_base_type()
-    storage_class = declaration_specifier_list.get_storage_class()
-
-    # new way
     global doing_typedef
 
     declaration_specifier_list = yy_element_stack[-1].children[0]
@@ -445,116 +285,13 @@ init_declarator_list
 
 init_declarator
   : %space (?E{t_def.InitDeclarator}declarator {
-    declarator = yy_element_stack[-2].children[0]
-    assert isinstance(declarator, t_def.Declarator)
-
-    # we refer to the global variables for _base_type and storage_class
-    name, _type = declarator.get_name_and_type(_base_type)
-    #print('decl', name)
-
-    if name in scope.identifiers:
-      scope_identifier = scope.identifiers[name]
-      assert scope_identifier.type == _type
-    else:
-      scope_identifier = t_def.Scope.Identifier(
-        name = name,
-        type = _type,
-        storage_class = t_def.STORAGE_CLASS_NONE
-      )
-      scope.identifiers[name] = scope_identifier
-    # save scope_identifier for InitDeclarator when constructed
-    # save storage_class for extern, initializer, array size checks
-    $$ = (scope_identifier, storage_class)
-
-    storage_class1 = storage_class
-    if isinstance(_type, t_def.TypeFunction):
-      assert storage_class1 in {
-        t_def.STORAGE_CLASS_NONE,
-        t_def.STORAGE_CLASS_EXTERN,
-        t_def.STORAGE_CLASS_STATIC
-      }
-    elif storage_class1 not in {
-      t_def.STORAGE_CLASS_EXTERN,
-      t_def.STORAGE_CLASS_TYPEDEF
-    }:
-      if isinstance(_type, t_def.TypeArray):
-        assert _type.element_type.size >= 0 # must be of determinate size
-
-      assert not scope_identifier.defined
-      scope_identifier.defined = True
-
-      if (
-        scope.enclosing_scope is not None and
-        storage_class1 == t_def.STORAGE_CLASS_NONE
-      ):
-        storage_class1 = t_def.STORAGE_CLASS_AUTO
-
-      # don't do this here -- we don't have size of indeterminate array yet
-      #align_m1 = _type.align - 1
-      #scope.size = (scope.size + align_m1) & ~align_m1
-      #scope_identifier.offset = scope.size
-      #if _type.size >= 0: # unknown size treated as 0 bytes (not correct!!)
-      #  scope.size += _type.size
-    elif storage_class1 == t_def.STORAGE_CLASS_TYPEDEF: # TEMPORARY
-      assert not scope_identifier.defined # TEMPORARY
-      scope_identifier.defined = True # TEMPORARY
-
-    if storage_class1 == t_def.STORAGE_CLASS_NONE:
-      pass
-    elif scope_identifier.storage_class == t_def.STORAGE_CLASS_NONE:
-      scope_identifier.storage_class = storage_class1
-    else:
-      assert scope_identifier.storage_class == storage_class1
-
-    # this global variable is needed whilst parsing the initializer
-    assert len(initializer_stack) == 0
-    initializer_stack.append([_type, 0, 0])
-
-    # new way
     # if doing typedef, insert the new typedef into top of typedef_stack
     if doing_typedef:
       declarator = yy_element_stack[-2].children[0]
       declarator_identifier = t_def.get_declarator_identifier(declarator)
       assert declarator_identifier is not None
       typedef_stack[-1].add(declarator_identifier.text[0])
-  } equals_initializer_opt) {
-    # scope_identifier was saved for InitDeclarator when constructed
-    # storage_class was saved for extern, initializer, array size checks
-    scope_identifier, storage_class = $2
-
-    init_declarator = yy_element_stack[-1].children[0]
-    init_declarator.scope_identifier = scope_identifier
-
-    # this global variable was needed whilst parsing the initializer
-    _, _, max_index = initializer_stack.pop()
-    assert len(initializer_stack) == 0
-
-    _type = scope_identifier.type
-    if isinstance(_type, t_def.TypeFunction):
-      assert len(init_declarator.children) < 2 # can t have initializer
-    elif storage_class in {
-      t_def.STORAGE_CLASS_EXTERN,
-      t_def.STORAGE_CLASS_TYPEDEF
-    }:
-      assert len(init_declarator.children) < 2 # can t have initializer
-    else:
-      if (
-        isinstance(_type, t_def.TypeArray) and
-        _type.element_count == -1 and
-        len(init_declarator.children) >= 2
-      ):
-        # size of indeterminate sized array can be deduced from initializer
-        element_size = _type.element_type.size
-        assert element_size >= 0 # must be of determinate size
-        _type.size = max_index * element_size
-        _type.element_count = max_index
-
-      assert _type.size >= 0 # must be of determinate size
-      align_m1 = _type.align - 1
-      scope.size = (scope.size + align_m1) & ~align_m1
-      scope_identifier.offset = scope.size
-      scope.size += _type.size
-  }
+  } equals_initializer_opt)
   ;
 
 storage_class_specifier
@@ -587,150 +324,13 @@ type_specifier
   ;
 
 struct_specifier
-  : %space (?E{t_def.StructSpecifier}STRUCT tag_identifier_opt '{' %space (?E{t_def.StructDeclarationList}struct_declaration_list_opt) '}') {
-    global next_anonymous_name
-
-    struct_specifier = yy_element_stack[-1].children[0]
-    name = struct_specifier.children[0].text[0]
-    if len(name) == 0:
-      name = f'${next_anonymous_name:d}'
-      next_anonymous_name += 1
-
-    if name in scope.struct_tags:
-      scope_tag = scope.struct_tags[name]
-      _type = scope_tag.type
-    else:
-      _type = t_def.TypeStruct()
-      scope_tag = t_def.Scope.Tag(name = name, type = _type)
-      scope.struct_tags[name] = scope_tag
-    struct_specifier.scope_tag = scope_tag
-
-    assert not scope_tag.defined
-    scope_tag.defined = True
-
-    members = []
-    member_name_to_index = {}
-    size = 0
-    align = 1
-    for i in struct_specifier.children[1].children:
-      _base_type = i.children[0].get_base_type()
-      for j in i.children[1].children:
-        member_name, member_type = j.get_name_and_type(_base_type)
-        if len(member_name) == 0: # used for bit fields with no name
-          member_name = f'${next_anonymous_name:d}'
-          next_anonymous_name += 1
-        assert member_name not in member_name_to_index
-        assert member_type.size >= 0 # must be of determinate size
-        align_m1 = member_type.align - 1
-        size = (size + align_m1) & ~align_m1
-        member_name_to_index[member_name] = len(members)
-        members.append(
-          t_def.TypeStructOrUnion.Member(
-            name = member_name,
-            type = member_type,
-            offset = size
-          )
-        )
-        size += member_type.size
-        align = max(align, member_type.align)
-
-    # make the size a multiple of the alignment
-    align_m1 = align - 1
-    size = (size + align_m1) & ~align_m1
-
-    _type.size = size
-    _type.align = align
-    _type.members = members
-    _type.member_name_to_index = member_name_to_index
-  }
-  | %space (?E{t_def.StructSpecifier}STRUCT tag_identifier) {
-    struct_specifier = yy_element_stack[-1].children[0]
-    name = struct_specifier.children[0].text[0]
-
-    i = scope
-    while i is not None:
-      if name in i.struct_tags:
-        scope_tag = i.struct_tags[name]
-        _type = scope_tag.type
-        break
-      i = i.enclosing_scope
-    else:
-      _type = t_def.TypeStruct()
-      scope_tag = t_def.Scope.Tag(name = name, type = _type)
-      scope.struct_tags[name] = scope_tag
-    struct_specifier.scope_tag = scope_tag
-  }
+  : %space (?E{t_def.StructSpecifier}STRUCT tag_identifier_opt '{' %space (?E{t_def.StructDeclarationList}struct_declaration_list_opt) '}')
+  | %space (?E{t_def.StructSpecifier}STRUCT tag_identifier)
   ;
 
 union_specifier
-  : %space (?E{t_def.UnionSpecifier}UNION tag_identifier_opt '{' %space (?E{t_def.StructDeclarationList}struct_declaration_list_opt) '}') {
-    global next_anonymous_name
-
-    union_specifier = yy_element_stack[-1].children[0]
-    name = union_specifier.children[0].text[0]
-    if len(name) == 0:
-      name = f'${next_anonymous_name:d}'
-      next_anonymous_name += 1
-
-    if name in scope.union_tags:
-      scope_tag = scope.union_tags[name]
-      _type = scope_tag.type
-    else:
-      _type = t_def.TypeUnion()
-      scope_tag = t_def.Scope.Tag(name = name, type = _type)
-      scope.union_tags[name] = scope_tag
-    union_specifier.scope_tag = scope_tag
-
-    assert not scope_tag.defined
-    scope_tag.defined = True
-
-    members = []
-    member_name_to_index = {}
-    size = 0
-    align = 1
-    for i in union_specifier.children[1].children:
-      _base_type = i.children[0].get_base_type()
-      for j in i.children[1].children:
-        member_name, member_type = j.get_name_and_type(_base_type)
-        assert member_name not in member_name_to_index
-        assert member_type.size >= 0 # must be of determinate size
-        member_name_to_index[member_name] = len(members)
-        members.append(
-          t_def.TypeStructOrUnion.Member(
-            name = member_name,
-            type = member_type,
-            offset = 0
-          )
-        )
-        size = max(size, member_type.size)
-        align = max(align, member_type.align)
-
-    # make the size a multiple of the alignment
-    align_m1 = align - 1
-    size = (size + align_m1) & ~align_m1
-
-    _type.size = size
-    _type.align = align
-    _type.members = members
-    _type.member_name_to_index = member_name_to_index
-  }
-  | %space (?E{t_def.UnionSpecifier}UNION tag_identifier) {
-    union_specifier = yy_element_stack[-1].children[0]
-    name = union_specifier.children[0].text[0]
-
-    i = scope
-    while i is not None:
-      if name in i.union_tags:
-        scope_tag = i.union_tags[name]
-        _type = scope_tag.type
-        break
-      i = i.enclosing_scope
-    else:
-      _type = t_def.TypeUnion()
-      scope_tag = t_def.Scope.Tag(name = name, type = _type)
-      scope.union_tags[name] = scope_tag
-    union_specifier.scope_tag = scope_tag
-  }
+  : %space (?E{t_def.UnionSpecifier}UNION tag_identifier_opt '{' %space (?E{t_def.StructDeclarationList}struct_declaration_list_opt) '}')
+  | %space (?E{t_def.UnionSpecifier}UNION tag_identifier)
   ;
 
 struct_declaration_list_opt
@@ -769,90 +369,13 @@ struct_declarator_list
   ;
 
 struct_declarator
-  : %space (?E{t_def.StructDeclarator}declarator_opt ':' constant_expression) {
-    struct_declarator = yy_element_stack[-1].children[0]
-    if struct_declarator.children[1].type != t_def.type_signed_int:
-      struct_declarator.children[1] = t_def.add_cast(
-        t_def.type_signed_int,
-        struct_declarator.children[1]
-      )
-  }
+  : %space (?E{t_def.StructDeclarator}declarator_opt ':' constant_expression)
   | declarator
   ;
 
 enum_specifier
-  : %space (?E{t_def.EnumSpecifier}ENUM tag_identifier_opt '{' %space (?E{t_def.EnumeratorList}enumerator_list_comma_opt) '}') {
-    global next_anonymous_name
-
-    enum_specifier = yy_element_stack[-1].children[0]
-    name = enum_specifier.children[0].text[0]
-    if len(name) == 0:
-      name = f'${next_anonymous_name:d}'
-      next_anonymous_name += 1
-
-    if name in scope.enum_tags:
-      scope_tag = scope.enum_tags[name]
-      _type = scope_tag.type
-    else:
-      _type = t_def.TypeEnum(
-        rank = t_def.INT_RANK,
-        size = t_def.INT_SIZE,
-        align = t_def.INT_ALIGN
-      )
-      scope_tag = t_def.Scope.Tag(name = name, type = _type)
-      scope.enum_tags[name] = scope_tag
-    enum_specifier.scope_tag = scope_tag
-
-    assert not scope_tag.defined
-    scope_tag.defined = True
-
-    members = {}
-    value = 0
-    for i in enum_specifier.children[1].children:
-      member_name = i.children[0].text[0]
-      assert member_name not in members
-      if len(i.children) >= 2:
-        expression = i.children[1]
-        assert expression.type == t_def.type_signed_int
-        assert isinstance(expression.value, t_def.ValueInt)
-        value = expression.value.value
-      members[member_name] = t_def.TypeEnum.Member(
-        name = member_name,
-        value = value
-      )
-
-      assert member_name not in scope.identifiers
-      scope.identifiers[member_name] = t_def.Scope.Identifier(
-        name = member_name,
-        type = _type,
-        storage_class = t_def.STORAGE_CLASS_ENUM_MEMBER,
-        defined = True
-      )
-
-      value += 1
-    _type.members = members
-  }
-  | %space (?E{t_def.EnumSpecifier}ENUM tag_identifier) {
-    enum_specifier = yy_element_stack[-1].children[0]
-    name = enum_specifier.children[0].text[0]
-
-    i = scope
-    while i is not None:
-      if name in i.enum_tags:
-        scope_tag = i.enum_tags[name]
-        _type = scope_tag.type
-        break
-      i = i.enclosing_scope
-    else:
-      _type = t_def.TypeEnum(
-        rank = t_def.INT_RANK,
-        size = t_def.INT_SIZE,
-        align = t_def.INT_ALIGN
-      )
-      scope_tag = t_def.Scope.Tag(name = name, type = _type)
-      scope.enum_tags[name] = scope_tag
-    enum_specifier.scope_tag = scope_tag
-  }
+  : %space (?E{t_def.EnumSpecifier}ENUM tag_identifier_opt '{' %space (?E{t_def.EnumeratorList}enumerator_list_comma_opt) '}')
+  | %space (?E{t_def.EnumSpecifier}ENUM tag_identifier)
   ;
 
 enumerator_list_comma_opt
@@ -903,14 +426,7 @@ function_specifier
 
 alignment_specifier
   : %space (?E{t_def.AlignAsType}ALIGNAS '(' type_name ')')
-  | %space (?E{t_def.AlignAsExpression}ALIGNAS '(' constant_expression ')') {
-    align_as_expression = yy_element_stack[-1].children[0]
-    if align_as_expression.children[0].type != t_def.type_size_t:
-      align_as_expression.children[0] = t_def.add_cast(
-        t_def.type_size_t,
-        align_as_expression.children[0]
-      )
-  }
+  | %space (?E{t_def.AlignAsExpression}ALIGNAS '(' constant_expression ')')
   ;
 
 declarator_opt
@@ -948,28 +464,8 @@ parameter_declaration_list
   ;
 
 parameter_declaration
-  : %space (?E{t_def.ParameterDeclaration}(?E{t_def.DeclarationSpecifierList}declaration_specifier_list) declarator) {
-    parameter_declaration = yy_element_stack[-1].children[0]
-
-    (
-      parameter_declaration.name,
-      parameter_declaration.type
-    ) = parameter_declaration.children[1].get_name_and_type(
-      parameter_declaration.children[0].get_base_type()
-    )
-    assert len(parameter_declaration.name)
-  }
-  | %space (?E{t_def.ParameterDeclaration}(?E{t_def.DeclarationSpecifierList}declaration_specifier_list) abstract_declarator) {
-    parameter_declaration = yy_element_stack[-1].children[0]
-
-    (
-      parameter_declaration.name,
-      parameter_declaration.type
-    ) = parameter_declaration.children[1].get_name_and_type(
-      parameter_declaration.children[0].get_base_type()
-    )
-    assert len(parameter_declaration.name) == 0
-  }
+  : %space (?E{t_def.ParameterDeclaration}(?E{t_def.DeclarationSpecifierList}declaration_specifier_list) declarator)
+  | %space (?E{t_def.ParameterDeclaration}(?E{t_def.DeclarationSpecifierList}declaration_specifier_list) abstract_declarator)
   ;
 
 identifier_list_opt
@@ -983,14 +479,7 @@ identifier_list
   ;
 
 type_name
-  : %space (?E{t_def.TypeName}(?E{t_def.SpecifierQualifierList}specifier_qualifier_list) abstract_declarator) {
-    type_name = yy_element_stack[-1].children[0]
-
-    name, type_name.type = type_name.children[1].get_name_and_type(
-      type_name.children[0].get_base_type()
-    )
-    assert len(name) == 0
-  }
+  : %space (?E{t_def.TypeName}(?E{t_def.SpecifierQualifierList}specifier_qualifier_list) abstract_declarator)
   ;
 
 abstract_declarator
@@ -1023,19 +512,8 @@ equals_initializer_opt
   ;
 
 initializer
-  : %space (?E{t_def.InitializerArrayOrStruct}'{' %space (?E{t_def.DesignatorInitializerList}designator_initializer_list_comma_opt) '}') {
-    initializer_array_or_struct = yy_element_stack[-1].children[0]
-    initializer_array_or_struct.type = initializer_stack[-1][0]
-  }
-  | %space (?E{t_def.InitializerExpression}assignment_expression) {
-    initializer_expression = yy_element_stack[-1].children[0]
-    if initializer_expression.children[0].type != initializer_stack[-1][0]:
-      initializer_expression.children[0] = t_def.add_cast(
-        initializer_stack[-1][0],
-        initializer_expression.children[0]
-      )
-    initializer_expression.type = initializer_stack[-1][0]
-  }
+  : %space (?E{t_def.InitializerArrayOrStruct}'{' %space (?E{t_def.DesignatorInitializerList}designator_initializer_list_comma_opt) '}')
+  | %space (?E{t_def.InitializerExpression}assignment_expression)
   ;
 
 designator_initializer_list_comma_opt
@@ -1050,63 +528,7 @@ designator_initializer_list
   ;
 
 designator_initializer
-  : %space (?E{t_def.DesignatorInitializer}designator_list_equals_opt {
-    designator_list = yy_element_stack[-2].children[0]
-    assert isinstance(designator_list, t_def.DesignatorList)
-
-    _type, index, max_index = initializer_stack[-1]
-    if len(designator_list.children):
-      # with designator, the designator says which element to fill
-      # note: this resets index position, but only for the first designator
-      # for example, [1][3] resets index position to 1, and the next is [2]
-      indices = []
-      for i in designator_list.children:
-        if isinstance(i, t_def.DesignatorIndex):
-          assert isinstance(_type, t_def.TypeArray)
-
-          # get numeric index from designator
-          expression = i.children[0]
-          assert expression.type == t_def.type_ssize_t
-          assert isinstance(expression.value, t_def.ValueInt)
-          j = expression.value.value
-
-          assert j >= 0
-          assert _type.element_count == -1 or j < _type.element_count
-          _type = _type.element_type
-        elif isinstance(i, t_def.DesignatorMember):
-          assert isinstance(_type, t_def.TypeStructOrUnion)
-          member_identifier = i.children[0]
-          j = _type.member_name_to_index[member_identifier.text[0]]
-          member_identifier.type = _type
-          member_identifier.index = j
-          _type = _type.members[j].type
-        else:
-          assert False
-        indices.append(j)
-    else:
-      # without designator, the elements are filled in sequentially
-      if isinstance(_type, t_def.TypeArray):
-        assert _type.element_count == -1 or index < _type.element_count
-        _type =_type.element_type
-      elif isinstance(_type, t_def.TypeStructOrUnion):
-        assert index < len(_type.members)
-        _type =_type.members[index].type
-      else:
-        assert False
-      indices = [index]
-    $$ = indices # for DesignatorInitializer when constructed
-    index = indices[0] + 1
-    initializer_stack[-1][1] = index
-    if index > max_index:
-      initializer_stack[-1][2] = index
-    initializer_stack.append([_type, 0, 0])
-  } initializer) {
-    initializer_stack.pop()
-
-    designator_initializer = yy_element_stack[-1].children[0]
-    designator_initializer.type = initializer_stack[-1][0]
-    designator_initializer.indices = $2
-  }
+  : %space (?E{t_def.DesignatorInitializer}designator_list_equals_opt initializer)
   ;
 
 designator_list_equals_opt
@@ -1120,148 +542,35 @@ designator_list
   ;
 
 designator
-  : %space (?E{t_def.DesignatorIndex}'[' constant_expression ']') {
-    designator_index = yy_element_stack[-1].children[0]
-    if designator_index.children[0].type != t_def.type_ssize_t:
-      designator_index.children[0] = t_def.add_cast(
-        t_def.type_ssize_t,
-        designator_index.children[0]
-      )
-  }
+  : %space (?E{t_def.DesignatorIndex}'[' constant_expression ']')
   | %space (?E{t_def.DesignatorMember}'.' member_identifier)
   ;
 
 static_assert_declaration
-  : %space (?E{t_def.StaticAssertDeclaration}STATIC_ASSERT '(' constant_expression ',' STRING_LITERAL ')' ';') {
-    static_assert_declaration = yy_element_stack[-1].children[0]
-    if static_assert_declaration.children[0].type != t_def.type_bool:
-      static_assert_declaration.children[0] = t_def.add_cast(
-        t_def.type_bool,
-        static_assert_declaration.children[0]
-      )
-  }
+  : %space (?E{t_def.StaticAssertDeclaration}STATIC_ASSERT '(' constant_expression ',' STRING_LITERAL ')' ';')
   ;
 
 statement
   : %space (?E{t_def.StatementLabel}identifier ':' statement)
-  | %space (?E{t_def.StatementCase}CASE constant_expression ':' statement) {
-    assert len(switch_type) # can only occur within switch
-    statement_case = yy_element_stack[-1].children[0]
-    if statement_case.children[0].type != switch_type[-1]:
-      statement_case.children[0] = t_def.add_cast(
-        switch_type[-1],
-        statement_case.children[0]
-      )
-  }
+  | %space (?E{t_def.StatementCase}CASE constant_expression ':' statement)
   | %space (?E{t_def.StatementDefault}DEFAULT ':' statement)
   | %space (?E{t_def.StatementBlock}'{' {
-    global scope
-
-    scope = t_def.Scope(enclosing_scope = scope)
-
-    # new way
     typedef_stack.append(set())
   } %space (?E{t_def.BlockItemList}block_item_list_opt) '}') {
-    global scope
-
-    statement_block = yy_element_stack[-1].children[0]
-    statement_block.children[0].scope = scope
-    scope = scope.enclosing_scope
-
-    # new way
     typedef_stack.pop()
   }
-  | %space (?E{t_def.StatementExpression}expression_opt ';') {
-    statement_expression = yy_element_stack[-1].children[0]
-    if not isinstance(statement_expression.children[0].type, t_def.TypeVoid):
-      statement_expression.children[0] = t_def.add_cast(
-        t_def.type_void,
-        statement_expression.children[0]
-      )
-  }
-  | %space (?E{t_def.StatementIf}IF '(' expression ')' statement ELSE statement) {
-    statement_if_else = yy_element_stack[-1].children[0]
-    if not isinstance(statement_if_else.children[0].type, t_def.TypeBool):
-      statement_if_else.children[0] = t_def.add_cast(
-        t_def.type_bool,
-        statement_if_else.children[0]
-      )
-  }
-  | %space (?E{t_def.StatementIf}IF '(' expression ')' statement) {
-    statement_if = yy_element_stack[-1].children[0]
-    if not isinstance(statement_if.children[0].type, t_def.TypeBool):
-      statement_if.children[0] = t_def.add_cast(
-        t_def.type_bool,
-        statement_if.children[0]
-      )
-  }
-  | %space (?E{t_def.StatementSwitch}SWITCH '(' expression ')' {
-    expression = yy_element_stack[-4].children[0]
-    assert isinstance(expression, t_def.Expression)
-    assert isinstance(expression.type, t_def.TypeInt)
-    switch_type.append(expression.type)
-  } statement) {
-    switch_type.pop()
-  }
-  | %space (?E{t_def.StatementWhile}WHILE '(' expression ')' statement) {
-    statement_while = yy_element_stack[-1].children[0]
-    if not isinstance(statement_while.children[0].type, t_def.TypeBool):
-      statement_while.children[0] = t_def.add_cast(
-        t_def.type_bool,
-        statement_while.children[0]
-      )
-  }
-  | %space (?E{t_def.StatementDoWhile}DO statement WHILE '(' expression ')' ';') {
-    statement_do_while = yy_element_stack[-1].children[0]
-    if not isinstance(statement_do_while.children[1].type, t_def.TypeBool):
-      statement_do_while.children[1] = t_def.add_cast(
-        t_def.type_bool,
-        statement_do_while.children[1]
-      )
-  }
-  | %space (?E{t_def.StatementFor}FOR '(' %space (?E{t_def.StatementExpression}expression_opt ';') expression_opt ';' expression_opt ')' statement) {
-    statement_for = yy_element_stack[-1].children[0]
-    statement_expression = statement_for.children[0]
-    if not isinstance(statement_expression.children[0].type, t_def.TypeVoid):
-      statement_expression.children[0] = t_def.add_cast(
-        t_def.type_void,
-        statement_expression.children[0]
-      )
-    if not isinstance(statement_for.children[1].type, t_def.TypeBool):
-      statement_for.children[1] = t_def.add_cast(
-        t_def.type_bool,
-        statement_for.children[1]
-      )
-    if not isinstance(statement_for.children[2].type, t_def.TypeVoid):
-      statement_for.children[2] = t_def.add_cast(
-        t_def.type_void,
-        statement_for.children[2]
-      )
-  }
-  | %space (?E{t_def.StatementFor}FOR '(' declaration expression_opt ';' expression_opt ')' statement) {
-    statement_for = yy_element_stack[-1].children[0]
-    if not isinstance(statement_for.children[1].type, t_def.TypeBool):
-      statement_for.children[1] = t_def.add_cast(
-        t_def.type_bool,
-        statement_for.children[1]
-      )
-    if not isinstance(statement_for.children[2].type, t_def.TypeVoid):
-      statement_for.children[2] = t_def.add_cast(
-        t_def.type_void,
-        statement_for.children[2]
-      )
-  }
+  | %space (?E{t_def.StatementExpression}expression_opt ';')
+  | %space (?E{t_def.StatementIf}IF '(' expression ')' statement ELSE statement)
+  | %space (?E{t_def.StatementIf}IF '(' expression ')' statement)
+  | %space (?E{t_def.StatementSwitch}SWITCH '(' expression ')' statement)
+  | %space (?E{t_def.StatementWhile}WHILE '(' expression ')' statement)
+  | %space (?E{t_def.StatementDoWhile}DO statement WHILE '(' expression ')' ';')
+  | %space (?E{t_def.StatementFor}FOR '(' %space (?E{t_def.StatementExpression}expression_opt ';') expression_opt ';' expression_opt ')' statement)
+  | %space (?E{t_def.StatementFor}FOR '(' declaration expression_opt ';' expression_opt ')' statement)
   | %space (?E{t_def.StatementGoto}GOTO identifier ';')
   | %space (?E{t_def.StatementContinue}CONTINUE ';')
   | %space (?E{t_def.StatementBreak}BREAK ';')
-  | %space (?E{t_def.StatementReturn}RETURN expression_opt ';') {
-    statement_return = yy_element_stack[-1].children[0]
-    if statement_return.children[0].type != return_type:
-      statement_return.children[0] = t_def.add_cast(
-        return_type,
-        statement_return.children[0]
-      )
-  }
+  | %space (?E{t_def.StatementReturn}RETURN expression_opt ';')
   ;
 
 block_item_list_opt
@@ -1296,112 +605,15 @@ external_declaration
 
 function_definition
   : %space (?E{t_def.FunctionDefinition}declaration_specifier_list1 declarator %space (?E{t_def.DeclarationList}declaration_list_opt) '{' {
-    global scope, _base_type, storage_class, return_type
-
-    # add function definition to the outer scope
-
-    # we refer to the global variables for _base_type and storage_class
-    declarator = yy_element_stack[-6].children[0]
-    name, _type = declarator.get_name_and_type(_base_type)
-    #print('func', name)
-
-    assert isinstance(_type, t_def.TypeFunction)
-    assert storage_class in {
-      t_def.STORAGE_CLASS_NONE,
-      t_def.STORAGE_CLASS_EXTERN,
-      t_def.STORAGE_CLASS_STATIC
-    }
-
-    if name in scope.identifiers:
-      scope_identifier = scope.identifiers[name]
-      assert scope_identifier.type == _type
-    else:
-      scope_identifier = t_def.Scope.Identifier(
-        name = name,
-        type = _type,
-        storage_class = t_def.STORAGE_CLASS_NONE
-      )
-      scope.identifiers[name] = scope_identifier
-    $$ = scope_identifier # for FunctionDefinition when constructed
-
-    assert not scope_identifier.defined
-    scope_identifier.defined = True
-
-    if storage_class == t_def.STORAGE_CLASS_NONE:
-      pass
-    elif scope_identifier.storage_class == t_def.STORAGE_CLASS_NONE:
-      scope_identifier.storage_class = storage_class
-    else:
-      assert scope_identifier.storage_class == storage_class
-
-    # now create the inner scope and add formal parameters
-
-    scope = t_def.Scope(enclosing_scope = scope)
-
-    declarator_function = t_def.get_declarator_function(declarator)
-    assert declarator_function is not None
-    if isinstance(declarator_function, t_def.DeclaratorFunctionANSI):
-      parameter_declarations = declarator_function.children[1].children
-      if (
-        len(parameter_declarations) != 1 or
-        len(parameter_declarations[0].name) or
-        not isinstance(parameter_declarations[0].type, t_def.TypeVoid)
-      ):
-        for i in parameter_declarations:
-          name = i.name
-          _type = t_def.array_decay(i.type)
-          #print('param', name)
-
-          assert name not in scope.identifiers
-          scope_identifier = t_def.Scope.Identifier(
-            name = name,
-            type = _type,
-            storage_class = t_def.STORAGE_CLASS_AUTO,
-            defined = True
-          )
-          scope.identifiers[name] = scope_identifier
-          i.scope_identifier = scope_identifier
-
-          assert _type.size >= 0 # must be of determinate size
-          align_m1 = _type.align - 1
-          scope.size = (scope.size + align_m1) & ~align_m1
-          scope_identifier.offset = scope.size
-          scope.size += _type.size
-    elif isinstance(declarator_function, t_def.DeclaratorFunctionKAndR):
-      # has no information about formal parameter types, ignore for now
-      pass
-    else:
-      assert False
-
-    # these globals were needed whilst parsing the header of the function
-    _base_type = None
-    storage_class = -1
-
-    # this global is needed for parsing the body of the function
-    return_type = $$.type.return_type
-
-    # new way
     global doing_typedef
 
     # this global is set by declaration_specifier_list1 if doing typedef,
     # it needs to be cleared as soon as we finish all of the declarators
+    # POSSIBLE BUG: SHOULDN T IT BE CLEARED BEFORE THE DECLARATION LIST?
     doing_typedef = False
 
-    # new way
     typedef_stack.append(set())
   } %space (?E{t_def.BlockItemList}block_item_list_opt) '}') {
-    global scope, return_type
-
-    function_definition = yy_element_stack[-1].children[0]
-    function_definition.scope_identifier = $5
-
-    function_definition.children[3].scope = scope
-    scope = scope.enclosing_scope
-
-    # this global was needed for parsing the body of the function
-    return_type = None
-
-    # new way
     typedef_stack.pop()
   }
   ;
@@ -1456,13 +668,6 @@ def yyerror(loc, msg):
   print(f'{in_file:s}({loc.first_line:d},{loc.first_column:d}..{loc.last_line:d},{loc.last_column:d}): {msg:s}')
   sys.exit(1)
 
-# helper factory to construct Expression object and analyze type and value
-def build(factory, *args, **kwargs):
-  expression = factory(*args, **kwargs)
-  expression.calc_type()
-  expression.calc_value()
-  return expression
-
 # intercept calls to yylex() for typedef processing
 no_typedef_tokens = {ord('.'), PTR_OP, STRUCT, UNION, ENUM}
 def yylex_typedef():
@@ -1470,23 +675,10 @@ def yylex_typedef():
 
   token = lex_yy.yylex()
   if token == IDENTIFIER and last_token not in no_typedef_tokens:
-    i = scope
-    while i is not None:
-      if lex_yy.yytext in i.identifiers:
-        scope_identifier = i.identifiers[lex_yy.yytext]
-        if scope_identifier.storage_class == t_def.STORAGE_CLASS_TYPEDEF:
-          token = TYPEDEF_NAME
-          yylval = scope_identifier
-        break
-      i = i.enclosing_scope
-
-    # new way (just for testing at the moment)
     for i in range(len(typedef_stack) - 1, -1, -1):
       if lex_yy.yytext in typedef_stack[i]:
-        assert token == TYPEDEF_NAME
+        token = TYPEDEF_NAME
         break
-    else:
-      assert token != TYPEDEF_NAME
 
   last_token = token
   return token
index 188328e..ee6b9dc 100644 (file)
@@ -28,20 +28,36 @@ def get_name_and_type(self, _base_type):
   )
 @t_def.method(t_def.DeclaratorFunctionANSI)
 def get_name_and_type(self, _base_type):
-  parameter_declarations = self.children[1].children
+  formal_parameters = []
+  parameter_declaration_list = self.children[1]
+  if not t_def.parameter_declaration_list_is_void(
+    parameter_declaration_list
+  ):
+    for parameter_declaration in parameter_declaration_list.children:
+      parameter_name, parameter_type = ( # TEMPORARY parameter_name
+        parameter_declaration.children[1].get_name_and_type(
+          parameter_declaration.children[0].get_base_type()
+        )
+      )
+      parameter_type = t_def.array_decay(parameter_type)
+      formal_parameters.append(parameter_type)
+      parameter_declaration.name = parameter_name # TEMPORARY
+      parameter_declaration.type = parameter_type # TEMPORARY
+  else: # TEMPORARY
+    parameter_declaration = parameter_declaration_list.children[0]
+    parameter_name, parameter_type = (
+      parameter_declaration.children[1].get_name_and_type(
+        parameter_declaration.children[0].get_base_type()
+      )
+    )
+    parameter_type = t_def.array_decay(parameter_type)
+    parameter_declaration.name = parameter_name
+    parameter_declaration.type = parameter_type
   return self.children[0].get_name_and_type(
     t_def.TypeFunctionANSI(
       return_type = _base_type,
       varargs = self.varargs,
-      formal_parameters = (
-        []
-      if (
-        len(parameter_declarations) == 1 and
-        len(parameter_declarations[0].name) == 0 and
-        isinstance(parameter_declarations[0].type, t_def.TypeVoid)
-      ) else
-        [t_def.array_decay(i.type) for i in parameter_declarations]
-      )
+      formal_parameters = formal_parameters
     )
   )
 @t_def.method(t_def.DeclaratorFunctionKAndR)
index 08fb7ed..ac30579 100644 (file)
@@ -82,6 +82,7 @@ def post_process(self, context):
   assert context.base_type is None
   context.base_type = self.children[0].get_base_type()
   context.storage_class = self.children[0].get_storage_class()
+  self.storage_class = context.storage_class # for the pretty printer
   self.children[1].post_process(context)
   context.base_type = None