def arrow_operator(tokens, symbol_table, primary_exp): l = loc(consume(tokens)) _ = error_if_not_type(c_type(primary_exp), PointerType), \ error_if_not_type(c_type(c_type(primary_exp)), (StructType, UnionType)) member_name = error_if_not_type(consume(tokens, EOFLocation), IDENTIFIER) return ElementSelectionThroughPointerExpression( primary_exp, member_name, c_type(member(c_type(c_type(primary_exp)), member_name))(l), l)
def arrow_operator(tokens, symbol_table, primary_exp): l = loc(consume(tokens)) _ = error_if_not_type(c_type(primary_exp), PointerType), \ error_if_not_type(c_type(c_type(primary_exp)), (StructType, UnionType)) member_name = error_if_not_type(consume(tokens, EOFLocation), IDENTIFIER) return ElementSelectionThroughPointerExpression( primary_exp, member_name, c_type(member(c_type(c_type(primary_exp)), member_name))(l), l )
def dot_oper(tokens, symbol_table, primary_exp): l = (error_if_not_type(c_type(primary_exp), (StructType, UnionType)) or 1) and loc( consume(tokens)) member_name = error_if_not_type(consume(tokens, ''), IDENTIFIER) return ElementSelectionExpression( primary_exp, member_name, c_type(member(c_type(primary_exp), member_name))(l), l)
def subscript_oper(tokens, symbol_table, primary_exp): location = error_if_not_type(c_type(primary_exp), PointerType) and loc( consume(tokens)) expr = symbol_table['__ expression __']( tokens, symbol_table) # subscript must be of Integral Type. _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) and error_if_not_type( c_type(expr), IntegralType) return ArraySubscriptingExpression(primary_exp, expr, c_type(c_type(primary_exp))(location), location)
def UNDEF(token_seq, macros): line = get_line(token_seq) macro_name = consume(line) and error_if_not_type( consume(line, EOFLocation), (IDENTIFIER, KEYWORD)) _ = macro_name in macros and macros.pop(macro_name) _ = error_if_not_empty(line) yield IGNORE(location=loc(macro_name))
def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start,), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), ) ) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset(start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8*size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table)
def __init__(self, c_decl, body): _ = error_if_not_type(c_type(c_decl), FunctionType) if not all(isinstance(arg, Declarator) for arg in c_type(c_decl)): raise ValueError('{l} FunctionDef must have concrete declarators as params'.format(l=loc(c_type(c_decl)))) if not isinstance(body, CompoundStatement): raise ValueError('{l} FunctionDef body is not a compound statement, got {g}'.format(l=loc(c_decl), g=body)) super(FunctionDefinition, self).__init__(name(c_decl), c_type(c_decl), body, loc(c_decl), c_decl.storage_class)
def unary_operator(tokens, symbol_table): operator = consume(tokens) if operator == TOKENS.LOGICAL_AND: return AddressOfLabelExpression( error_if_not_type(consume(tokens, ''), IDENTIFIER), void_pointer_type(loc(operator)), loc(operator) ) cast_exp = symbol_table['__ cast_expression __'](tokens, symbol_table) return rules(unary_operator)[operator](cast_exp, operator)
def unary_operator(tokens, symbol_table): operator = consume(tokens) if operator == TOKENS.LOGICAL_AND: return AddressOfLabelExpression( error_if_not_type(consume(tokens, ''), IDENTIFIER), void_pointer_type(loc(operator)), loc(operator)) cast_exp = symbol_table['__ cast_expression __'](tokens, symbol_table) return rules(unary_operator)[operator](cast_exp, operator)
def function_call(tokens, symbol_table, primary_exp): l = loc(consume(tokens)) func_type = error_if_not_type(c_type(c_type(primary_exp)), FunctionType) # get expression arguments. expression_argument_list = ArgumentExpressionList(tuple(get_args(tokens, symbol_table, func_type)), l) return error_if_not_value(tokens, TOKENS.RIGHT_PARENTHESIS) and FunctionCallExpression( primary_exp, expression_argument_list, c_type(func_type)(l), l )
def get_new_instr(addr_operand, default): if isinstance(referenced_obj(addr_operand, None), Reference) and id(addr_operand) in new_references: # replace Reference by instruction default = addr_operand.obj = error_if_not_type(new_references[id(addr_operand)].obj, Reference) # if id(addr_operand.obj) not in new_instructions: # print 'no address !!!', id(addr_operand.obj) # else: # print id(addr_operand.obj), ' --> ', id(new_instructions[id(addr_operand.obj)]) return new_instructions.get(id(addr_operand.obj), default)
def parse_enum_members(tokens, symbol_table): constant_expression = symbol_table['__ constant_expression __'] location, members, current_value = loc(consume(tokens)), OrderedDict(), 0 while peek(tokens, TOKENS.RIGHT_BRACE) != TOKENS.RIGHT_BRACE: ident = error_if_not_type(consume(tokens, ''), IDENTIFIER) value = ConstantExpression(current_value, IntegerType(location), location) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): value = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(value), IntegerType) current_value = error_if_not_type(exp(value), (int, long)) symbol_table[ident] = value # Add value to symbol_table members[ident] = Definition(ident, c_type(value), value, location) _ = peek_or_terminal(tokens) == TOKENS.COMMA and consume(tokens) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACE) return members
def function_call(tokens, symbol_table, primary_exp): l = loc(consume(tokens)) func_type = error_if_not_type(c_type(c_type(primary_exp)), FunctionType) # get expression arguments. expression_argument_list = ArgumentExpressionList( tuple(get_args(tokens, symbol_table, func_type)), l) return error_if_not_value( tokens, TOKENS.RIGHT_PARENTHESIS) and FunctionCallExpression( primary_exp, expression_argument_list, c_type(func_type)(l), l)
def parse_default_offset_designated_expr(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp(desig_expr) if isinstance(expr, DesignatedExpression) and error_if_not_type(ctype, (StructType, ArrayType)): parse_designated_expr(expr, default_values[desig]) elif isinstance(expr, Initializer): default_values = default_values[desig] if isinstance(ctype, (StructType, ArrayType)) else default_values set_default_initializer(expr, default_values) else: update_default_value(desig_expr, default_values)
def initialization(self, value): _ = value and c_type(self) and not safe_type_coercion(c_type(self), c_type(value)) and raise_error( '{l} Could not coerce types from {from_type} to {to_type}'.format( l=loc(self), from_type=c_type(value), to_type=c_type(self) )) if isinstance(c_type(self), ArrayType): _ = error_if_not_type(value, (ConstantExpression, CompoundLiteral, Initializer, EmptyExpression)) if c_type(self).length is None and isinstance(value, (Initializer, CompoundLiteral)): c_type(self).length = len(value) self._initialization = value
def get_new_instr(addr_operand, default): if isinstance(referenced_obj(addr_operand, None), Reference) and id(addr_operand) in new_references: # replace Reference by instruction default = addr_operand.obj = error_if_not_type( new_references[id(addr_operand)].obj, Reference) # if id(addr_operand.obj) not in new_instructions: # print 'no address !!!', id(addr_operand.obj) # else: # print id(addr_operand.obj), ' --> ', id(new_instructions[id(addr_operand.obj)]) return new_instructions.get(id(addr_operand.obj), default)
def __init__(self, c_decl, body): _ = error_if_not_type(c_type(c_decl), FunctionType) if not all(isinstance(arg, Declarator) for arg in c_type(c_decl)): raise ValueError( '{l} FunctionDef must have concrete declarators as params'. format(l=loc(c_type(c_decl)))) if not isinstance(body, CompoundStatement): raise ValueError( '{l} FunctionDef body is not a compound statement, got {g}'. format(l=loc(c_decl), g=body)) super(FunctionDefinition, self).__init__(name(c_decl), c_type(c_decl), body, loc(c_decl), c_decl.storage_class)
def dimensions(tokens): while peek(tokens) == TOKENS.LEFT_BRACKET: location = loc(consume(tokens)) if peek(tokens) == TOKENS.RIGHT_BRACKET: size = None else: const_exp = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(const_exp), IntegralType) if exp(const_exp) < 0: raise ValueError('{l} array size is negative'.format(l=loc(const_exp))) size = exp(const_exp) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) yield size, location
def parse_default_offset_designated_expr(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp( desig_expr) if isinstance(expr, DesignatedExpression) and error_if_not_type( ctype, (StructType, ArrayType)): parse_designated_expr(expr, default_values[desig]) elif isinstance(expr, Initializer): default_values = default_values[desig] if isinstance( ctype, (StructType, ArrayType)) else default_values set_default_initializer(expr, default_values) else: update_default_value(desig_expr, default_values)
def body(self, location, arguments=(), macros=()): if peek_or_terminal(arguments) == TOKENS.LEFT_PARENTHESIS and consume( arguments): name = error_if_not_type(consume(arguments, EOFLocation), (IDENTIFIER, KEYWORD)) _ = error_if_not_value(arguments, TOKENS.RIGHT_PARENTHESIS) elif isinstance(peek_or_terminal(arguments), (IDENTIFIER, KEYWORD)): name = consume(arguments) else: raise ValueError( '{l} Expected either LEFT_PARENTHESIS or IDENTIFIER for function macro defined got {g}' .format(l=location or EOLLocation, g=peek(arguments, ''))) yield INTEGER(str(int(name in macros)), loc(name))
def dimensions(tokens): while peek(tokens) == TOKENS.LEFT_BRACKET: location = loc(consume(tokens)) if peek(tokens) == TOKENS.RIGHT_BRACKET: size = None else: const_exp = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(const_exp), IntegralType) if exp(const_exp) < 0: raise ValueError( '{l} array size is negative'.format(l=loc(const_exp))) size = exp(const_exp) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) yield size, location
def declarations(tokens, symbol_table): # storage_class_specifier? type_name? init_declarator_list (';' or compound_statement) # declaration storage_class_specifier, specifier_qualifier_list, statement = imap( symbol_table.__getitem__, ('__ storage_class_specifier __', '__ specifier_qualifier_list __', '__ statement __')) storage_class = storage_class_specifier(tokens, symbol_table) base_type = specifier_qualifier_list(tokens, symbol_table) expecting_token = TOKENS.SEMICOLON if peek_or_terminal(tokens) == TOKENS.SEMICOLON: yield EmptyDeclaration(loc(consume(tokens)), storage_class) elif peek_or_terminal(tokens) is terminal: raise_error( '{l} Expected TOKENS.COMMA TOKENS.EQUAL TOKENS.SEMICOLON TOKENS.LEFT_BRACE got `{got}`' .format(l=loc(peek(tokens, EOFLocation)), got=peek(tokens, ''))) else: for dec in init_declarator_list(tokens, symbol_table, base_type=base_type, storage_class=storage_class): dec.storage_class = storage_class if isinstance( storage_class, TypeDef ): # init_declarator_list adds the symbol as a decl to symbol_table symbol_table[name(dec)] = (symbol_table.pop( name(dec)) or 1) and c_type(dec) # replace dec by ctype elif peek_or_terminal( tokens) == TOKENS.LEFT_BRACE and not error_if_not_type( c_type(dec), FunctionType): symbol_table = push(symbol_table) symbol_table.update( chain( imap( lambda a: ( name(a), a ), # add non variable list parameters to the symbol table ... ifilterfalse( lambda c: isinstance(c_type(c), VAListType), c_type(dec))), (('__ RETURN_TYPE __', c_type(c_type(dec))), ('__ LABELS __', SymbolTable())))) yield FunctionDefinition(dec, next(statement(tokens, symbol_table))) expecting_token = (pop(symbol_table) or 1) and '' else: yield dec expecting_token = TOKENS.SEMICOLON _ = expecting_token and error_if_not_value(tokens, expecting_token)
def _func_macro_arguments(line): symbol_table = SymbolTable() while peek(line, TOKENS.RIGHT_PARENTHESIS) != TOKENS.RIGHT_PARENTHESIS: if peek(line) == TOKENS.ELLIPSIS: arg = FunctionMacroVariadicArgument(IDENTIFIER('__VA_ARGS__', loc(consume(line)))) else: arg = FunctionMacroArgument(error_if_not_type(consume(line, EOFLocation), (IDENTIFIER, KEYWORD))) if peek_or_terminal(line) == TOKENS.ELLIPSIS: arg = FunctionMacroVariadicArgument(IDENTIFIER(arg, loc(consume(line)))) symbol_table[arg] = arg # check for duplicate argument name yield arg # if ok add to the rest ... if isinstance(arg, FunctionMacroVariadicArgument): # if variadic argument break ... break # consume expected comma if we don't see a right parenthesis ... _ = peek(line, TOKENS.RIGHT_PARENTHESIS) != TOKENS.RIGHT_PARENTHESIS \ and error_if_not_value(line, TOKENS.COMMA, loc(arg))
def case(tokens, symbol_table): location = loc(loc(consume(tokens))) constant_expression, statement = imap( symbol_table.__getitem__, ('__ constant_expression __', '__ statement __')) expr = constant_expression(tokens, symbol_table) _, _ = error_if_not_value(tokens, TOKENS.COLON), error_if_not_type( c_type(expr), IntegralType) switch_cases = symbol_table['__ SWITCH STATEMENT __'] switch_exp = symbol_table['__ SWITCH EXPRESSION __'] if c_type(expr) != c_type(switch_exp): raise ValueError( '{l} case exp type {g} differs from switch exp type {e}'.format( l=location, g=c_type(expr), e=c_type(switch_exp))) switch_cases[exp(expr)] = CaseStatement(expr, statement(tokens, symbol_table), location) yield switch_cases[exp(expr)]
def conditional_expression(tokens, symbol_table): # logical_or_expression ('?' expression ':' conditional_expression)? exp = logical_or_expression(tokens, symbol_table) if peek(tokens, '') in rules(conditional_expression): location = loc(error_if_not_value(tokens, TOKENS.QUESTION)) _ = error_if_not_type(c_type(exp), NumericType) if_exp_is_true = assignment_expression(tokens, symbol_table) _ = error_if_not_value(tokens, TOKENS.COLON) if_exp_is_false = conditional_expression(tokens, symbol_table) ctype_1, ctype_2 = imap(c_type, (if_exp_is_true, if_exp_is_false)) if safe_type_coercion(ctype_1, ctype_2): ctype = ctype_1(location) elif safe_type_coercion(ctype_2, ctype_1): ctype = ctype_2(location) else: raise ValueError('{l} Could not determine type for ternary-expr, giving the types {t1} and {t2}'.format( t1=ctype_1, t2=ctype_2 )) return TernaryExpression(exp, if_exp_is_true, if_exp_is_false, ctype, location) return exp
def _func_macro_arguments(line): symbol_table = SymbolTable() while peek(line, TOKENS.RIGHT_PARENTHESIS) != TOKENS.RIGHT_PARENTHESIS: if peek(line) == TOKENS.ELLIPSIS: arg = FunctionMacroVariadicArgument( IDENTIFIER('__VA_ARGS__', loc(consume(line)))) else: arg = FunctionMacroArgument( error_if_not_type(consume(line, EOFLocation), (IDENTIFIER, KEYWORD))) if peek_or_terminal(line) == TOKENS.ELLIPSIS: arg = FunctionMacroVariadicArgument( IDENTIFIER(arg, loc(consume(line)))) symbol_table[arg] = arg # check for duplicate argument name yield arg # if ok add to the rest ... if isinstance(arg, FunctionMacroVariadicArgument ): # if variadic argument break ... break # consume expected comma if we don't see a right parenthesis ... _ = peek(line, TOKENS.RIGHT_PARENTHESIS) != TOKENS.RIGHT_PARENTHESIS \ and error_if_not_value(line, TOKENS.COMMA, loc(arg))
def conditional_expression(tokens, symbol_table): # logical_or_expression ('?' expression ':' conditional_expression)? exp = logical_or_expression(tokens, symbol_table) if peek(tokens, '') in rules(conditional_expression): location = loc(error_if_not_value(tokens, TOKENS.QUESTION)) _ = error_if_not_type(c_type(exp), NumericType) if_exp_is_true = assignment_expression(tokens, symbol_table) _ = error_if_not_value(tokens, TOKENS.COLON) if_exp_is_false = conditional_expression(tokens, symbol_table) ctype_1, ctype_2 = imap(c_type, (if_exp_is_true, if_exp_is_false)) if safe_type_coercion(ctype_1, ctype_2): ctype = ctype_1(location) elif safe_type_coercion(ctype_2, ctype_1): ctype = ctype_2(location) else: raise ValueError( '{l} Could not determine type for ternary-expr, giving the types {t1} and {t2}' .format(t1=ctype_1, t2=ctype_2)) return TernaryExpression(exp, if_exp_is_true, if_exp_is_false, ctype, location) return exp
def declarations(tokens, symbol_table): # storage_class_specifier? type_name? init_declarator_list (';' or compound_statement) # declaration storage_class_specifier, specifier_qualifier_list, statement = imap( symbol_table.__getitem__, ('__ storage_class_specifier __', '__ specifier_qualifier_list __', '__ statement __') ) storage_class = storage_class_specifier(tokens, symbol_table) base_type = specifier_qualifier_list(tokens, symbol_table) expecting_token = TOKENS.SEMICOLON if peek_or_terminal(tokens) == TOKENS.SEMICOLON: yield EmptyDeclaration(loc(consume(tokens)), storage_class) elif peek_or_terminal(tokens) is terminal: raise_error('{l} Expected TOKENS.COMMA TOKENS.EQUAL TOKENS.SEMICOLON TOKENS.LEFT_BRACE got `{got}`'.format( l=loc(peek(tokens, EOFLocation)), got=peek(tokens, '') )) else: for dec in init_declarator_list(tokens, symbol_table, base_type=base_type, storage_class=storage_class): dec.storage_class = storage_class if isinstance(storage_class, TypeDef): # init_declarator_list adds the symbol as a decl to symbol_table symbol_table[name(dec)] = (symbol_table.pop(name(dec)) or 1) and c_type(dec) # replace dec by ctype elif peek_or_terminal(tokens) == TOKENS.LEFT_BRACE and not error_if_not_type(c_type(dec), FunctionType): symbol_table = push(symbol_table) symbol_table.update(chain( imap( lambda a: (name(a), a), # add non variable list parameters to the symbol table ... ifilterfalse(lambda c: isinstance(c_type(c), VAListType), c_type(dec)) ), (('__ RETURN_TYPE __', c_type(c_type(dec))), ('__ LABELS __', SymbolTable())) )) yield FunctionDefinition(dec, next(statement(tokens, symbol_table))) expecting_token = (pop(symbol_table) or 1) and '' else: yield dec expecting_token = TOKENS.SEMICOLON _ = expecting_token and error_if_not_value(tokens, expecting_token)
def _goto(tokens, symbol_table): location = loc(consume(tokens)) return GotoStatement(error_if_not_type(consume(tokens, EOFLocation), IDENTIFIER), location)
def __init__(self, ctype, location): error_if_not_type(ctype, IntegralType) super(IntegralExpression, self).__init__(ctype, location)
def dot_oper(tokens, symbol_table, primary_exp): l = (error_if_not_type(c_type(primary_exp), (StructType, UnionType)) or 1) and loc(consume(tokens)) member_name = error_if_not_type(consume(tokens, ''), IDENTIFIER) return ElementSelectionExpression(primary_exp, member_name, c_type(member(c_type(primary_exp), member_name))(l), l)
def address_of_label(tokens, symbol_table): operator = consume(tokens) return AddressOfLabelExpression( error_if_not_type(consume(tokens, ''), IDENTIFIER), void_pointer_type(loc(operator)), loc(operator))
def evaluate_expression(arguments, macros): return error_if_not_type( exp(constant_expression(expand(arguments, macros))), (long, int, float))
def __new__(cls, designation): _ = error_if_not_type(designation, (int, long)) and designation < 0 and raise_error( '{l} array indices must be greater than or equal to 0 got {g}'.format(l=loc(value), g=exp(value))) return super(NumericalDesignation, cls).__new__(cls, designation)
def constant_identifier(tokens, symbol_table): expr = symbol_table[peek(tokens)] return ConstantExpression(error_if_not_type(exp(expr), (int, long, float)), c_type(expr)(loc(peek(tokens))), loc(consume(tokens)))
def tilde_operator(cast_exp, operator): _ = error_if_not_type(c_type(cast_exp), IntegralType) return UnaryExpression(operator, cast_exp, c_type(cast_exp)(loc(operator)), loc(operator))
def evaluate_expression(arguments, macros): return error_if_not_type(exp(constant_expression(expand(arguments, macros))), (long, int, float))
def identifier_direct_declarator(tokens, symbol_table): ident = error_if_not_type(consume(tokens), IDENTIFIER) return Declarator(ident, CType(loc(ident)), None, loc(ident))
def _if_not_def_block(token_seq, macros): arguments = get_line(token_seq) argument = consume(arguments) and error_if_not_type(consume(arguments), (IDENTIFIER, KEYWORD)) _ = error_if_not_empty(arguments) return __calc_if(argument not in macros, token_seq, macros)
def subscript_oper(tokens, symbol_table, primary_exp): location = error_if_not_type(c_type(primary_exp), PointerType) and loc(consume(tokens)) expr = symbol_table['__ expression __'](tokens, symbol_table) # subscript must be of Integral Type. _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) and error_if_not_type(c_type(expr), IntegralType) return ArraySubscriptingExpression(primary_exp, expr, c_type(c_type(primary_exp))(location), location)
def __new__(cls, designation): _ = error_if_not_type( designation, (int, long)) and designation < 0 and raise_error( '{l} array indices must be greater than or equal to 0 got {g}'. format(l=loc(value), g=exp(value))) return super(NumericalDesignation, cls).__new__(cls, designation)
def dereference(cast_exp, operator): _ = error_if_not_type(c_type(cast_exp), PointerType) return DereferenceExpression(cast_exp, c_type(c_type(cast_exp))(loc(operator)), loc(operator))
def UNDEF(token_seq, macros): line = get_line(token_seq) macro_name = consume(line) and error_if_not_type(consume(line, EOFLocation), (IDENTIFIER, KEYWORD)) _ = macro_name in macros and macros.pop(macro_name) _ = error_if_not_empty(line) yield IGNORE(location=loc(macro_name))
def numeric_operator(cast_exp, operator): _ = error_if_not_type(c_type(cast_exp), NumericType) return UnaryExpression(operator, cast_exp, c_type(cast_exp)(loc(operator)), loc(operator))
def _if_not_def_block(token_seq, macros): arguments = get_line(token_seq) argument = consume(arguments) and error_if_not_type( consume(arguments), (IDENTIFIER, KEYWORD)) _ = error_if_not_empty(arguments) return __calc_if(argument not in macros, token_seq, macros)
def excl_operator(cast_exp, operator): _ = error_if_not_type(c_type(cast_exp), NumericType) return UnaryExpression(operator, cast_exp, logical_type(loc(operator)), loc(operator))
def constant_identifier(tokens, symbol_table): expr = symbol_table[peek(tokens)] return ConstantExpression( error_if_not_type(exp(expr), (int, long, float)), c_type(expr)(loc(peek(tokens))), loc(consume(tokens)) )
def address_of_label(tokens, symbol_table): operator = consume(tokens) return AddressOfLabelExpression( error_if_not_type(consume(tokens, ''), IDENTIFIER), void_pointer_type(loc(operator)), loc(operator) )
def identifier_designated_expr(tokens, symbol_table): # '.'IDENTIFIER identifier = error_if_not_value(tokens, TOKENS.DOT) and error_if_not_type(consume(tokens), IDENTIFIER) return IdentifierDesignatedExpression(identifier, _expr_or_designated_expr(tokens, symbol_table), loc(identifier))
def identifier_designated_expr(tokens, symbol_table): # '.'IDENTIFIER identifier = error_if_not_value(tokens, TOKENS.DOT) and error_if_not_type( consume(tokens), IDENTIFIER) return IdentifierDesignatedExpression( identifier, _expr_or_designated_expr(tokens, symbol_table), loc(identifier))