def check_while_loop(): lexer = Lexer() lexer.build() parser = Parser() Interpret = Interpreter() while_loop_tree = parser.parse_text(""" INT i=0; DO { INT b=0; DO { INT c=0; DO { PRINT("(",i,",",b,",",c,")"); c=c+1; }WHILE(c<2) b=b+1; }WHILE(b<2) i=i+1; } WHILE (i<2) """) Interpret.interpret(while_loop_tree) Interpret.print_variables()
def testing_variables(): lexer = Lexer() lexer.build() parser = Parser() Interpret = Interpreter() a_assign = parser.parse_text( 'PRINT(NOT TRUE==(NOT (NOT TRUE)) & (TRUE !=0));') print(a_assign) (Interpret.interpret(a_assign)) Interpret.print_variables() '''
def feed(self, text): lexer = Lexer() lexer.build() # TODO is this a hack self.tokens = lexer.tokens parser = yacc.yacc(module=self) parser.parse(text,lexer=lexer.lexer) self.errors = lexer.errors # print self.classes
def check_structs(): lexer = Lexer() lexer.build() parser = Parser() Interpret = Interpreter() a_assign = parser.parse_text( 'STRUCT BookStruct {INT a; STRING name; INT b;}; BookStruct Book1;Book1.a=10;PRINT(Book1.a);' ) (Interpret.interpret(a_assign)) Interpret.print_variables()
def testing_expressions(): lexer = Lexer() lexer.build() Interpret = Interpreter() parser = Parser() a_assign = parser.parse_text( 'INT a=1;INT b=4;b=b+1;DOUBLE c=(1.5+0.5+2);DOUBLE determinant= b^2-4*a*c;DOUBLE quadratic_root1=(determinant^0.5-b)/(2.0*a);PRINT (quadratic_root1);PRINT("hello");' ) print(a_assign) Interpret.assign_tree(a_assign) Interpret.interpret() Interpret.print_variables()
def testing(): lexer = Lexer() lexer.build() parser = Parser() line1 = parser.parse_text('INT x=2') line2 = parser.parse_text('STRING a="start"') Interpret = Interpreter(line1[0]) (Interpret.interpret()) Interpret.assign_tree(line2[0]) (Interpret.interpret())
def main(): files = open("test_cases/" + sys.argv[1], 'r') all_code = files.read() lexer = Lexer() lexer.build() parser = Parser() Interpret = Interpreter() print("Welcome to G0C Interpreter") AST = parser.parse_text(all_code) Interpret.interpret(AST)
def check_expr(): lexer = Lexer() lexer.build() parser = Parser() Interpret = Interpreter() bool_assign = parser.parse_text('BOOL d=False;') Interpret.assign_tree(bool_assign[0]) (Interpret.interpret()) print_assign = parser.parse_text('(2 & 2 ) | (3 & (2 &2));') Interpret.assign_tree(print_assign[0]) #print(Interpret.interpret()) Interpret.print_variables()
} } ''' empty_data = '' test = ''' class Program{ static void maine(){ int a = 3; int b = 4 * a; int var = a/ (-b + 32 << 2); } } ''' data = test l = Lexer() lexer = l.build() lexer.input(data) types = [] lexemes = [] attrs = [] while True: tok = lexer.token() # print(dir(tok)) # break if not tok: break # print(tok.lexer,end='\t\t') if tok.type == 'TOKEN_ID': lexemes.append(tok.value) tok.value = 'Index_ID ' + str(l.ids.index(tok.value))
class Parser(object): def __init__(self): self.lexer = Lexer() self.tokens = self.lexer.tokens self.literals = self.lexer.literals self.entity_arguments = {} self.predicate_arguments = {} self.predicate_entities = {} self.label_classes = {} self.label_types = {} self.files = {} self.rulesets = [] self.groupby = [] self.dbmodule = None self.dbclass = None self.femodule = None self.feclass = None self.scmodule = None def p_model(self, p): "model : instructionlist" pass def p_instructionlist(self, p): ''' instructionlist : instructionlist instruction ';' | instruction ';' ''' pass def p_instruction_entity(self, p): "instruction : ENTITY ':' VARSTRING ',' ARGUMENTS ':' '[' argumentdeflist ']'" name = p[3][1:len(p[3]) - 1] self.entity_arguments[name] = p[8] ## rules for parsing "predicate" creation def p_instruction_predicate(self, p): "instruction : PREDICATE ':' VARSTRING ',' ARGUMENTS ':' '[' VARPRED ',' VARPRED ']'" name = p[3][1:len(p[3]) - 1] arg1 = copy.deepcopy(self.entity_arguments[p[8]][0]) arg2 = copy.deepcopy(self.entity_arguments[p[10]][0]) arg1.name = arg1.name + "_1" arg2.name = arg2.name + "_2" self.predicate_arguments[name] = [arg1, arg2] self.predicate_entities[name] = [p[8], p[10]] def p_argument_def_list(self, p): ''' argumentdeflist : argumentdeflist ',' argumentdef | argumentdef ''' if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] p[0].append(p[3]) def p_argument(self, p): "argumentdef : VARSTRING ':' ':' type" arg_name = p[1][1:len(p[1]) - 1] p[0] = ArgumentDefinition(arg_name, p[4]) def p_type_string(self, p): "type : ARGSTRING" p[0] = ArgumentType.String def p_type_string_id(self, p): "type : ARGSTRINGID" p[0] = ArgumentType.UniqueString def p_type_int(self, p): "type : ARGINT" p[0] = ArgumentType.Integer def p_type_double(self, p): "type : ARGDOUBLE" p[0] = ArgumentType.Double def p_type_id(self, p): "type : ARGID" p[0] = ArgumentType.UniqueID ## rules for parsing "label" creation def p_instruction_label(self, p): "instruction : LABEL ':' VARSTRING ',' LBCLASSES ':' NUMBER ',' LBTYPE ':' labeltype" label = p[3][1:len(p[3]) - 1] self.label_classes[label] = p[7] self.label_types[label] = p[11] def p_labeltype_multilabel(self, p): "labeltype : LBMULTILABEL" p[0] = LabelType.Multilabel def p_labeltype_multiclass(self, p): "labeltype : LBMULTICLASS" p[0] = LabelType.Multiclass def p_labeltype_binary(self, p): "labeltype : LBBINARY" p[0] = LabelType.Binary ## rules for parsing "load" instructions def p_instruction_load(self, p): "instruction : LOAD ':' VARSTRING ',' FILE ':' VARSTRING" name = p[3][1:len(p[3]) - 1] filename = p[7][1:len(p[7]) - 1] self.files[name] = filename ## rules for parsing "rules" over predicates def p_instruction_ruleset(self, p): "instruction : RULESET '{' rulelist '}' GROUPBY ':' GROUPARG" self.rulesets.append(p[3]) dot_index = p[7].index('.') gb_table = p[7][:dot_index] gb_arg = p[7][dot_index + 1:] self.groupby.append((gb_table, gb_arg)) def p_instruction_dbmodule(self, p): "instruction : DBMODULE ':' VARSTRING" self.dbmodule = p[3][1:len(p[3]) - 1] def p_instruction_dbclass(self, p): "instruction : DBCLASS ':' VARSTRING" self.dbclass = p[3][1:len(p[3]) - 1] def p_instruction_femodule(self, p): "instruction : FEMODULE ':' VARSTRING" self.femodule = p[3][1:len(p[3]) - 1] def p_instruction_feclass(self, p): "instruction : FECLASS ':' VARSTRING" self.feclass = p[3][1:len(p[3]) - 1] def p_instruction_scmodule(self, p): "instruction : SCMODULE ':' VARSTRING" self.scmodule = p[3][1:len(p[3]) - 1] def p_rulelist(self, p): ''' rulelist : rulelist rule ';' | rule ';' ''' if len(p) == 3: p[0] = {} if p[1].isconstr: p[0]['constr'] = [p[1]] else: p[0]['rule'] = [p[1]] else: p[0] = p[1] if (type(p[2]) is RuleTemplate and p[2].isconstr) or (type(p[2]) is EquationTemplate): if 'constr' not in p[0]: p[0]['constr'] = [p[2]] else: p[0]['constr'].append(p[2]) else: p[0]['rule'].append(p[2]) def p_rule(self, p): ''' rule : RULE ':' proposition filters lambda scoring featureconf dbconf splitconf target ''' (body, head) = p[3] filters = p[4]; lambda_ = p[5]; scoring = p[6] feature_funcs = p[7]; dbfunc = p[8] (split_on, label_type) = p[9]; target = p[10] p[0] = RuleTemplate(body, head, filters, feature_funcs, lambda_, target, isconstr=False, split_on=split_on, label_type=label_type, dbfunc=dbfunc, scoring_function=scoring) def p_lambda(self, p): ''' lambda : LAMBDA ':' FLOAT ',' | ''' if len(p) == 5: p[0] = float(p[3]) else: p[0] = 1.0 def p_splitconf(self, p): ''' splitconf : SPLITCLASSIF ':' VARINSTANCE ':' ':' labeltype ',' | ''' if len(p) == 8: p[0] = (p[3], p[6]) else: p[0] = (None, None) def p_target(self, p): ''' target : TARGET ':' VARINSTANCE ''' p[0] = p[3] def p_filters(self, p): ''' filters : CONDS ':' '[' condlist ']' ',' | ''' if len(p) == 1: p[0] = [] else: p[0] = p[4] def p_cond_list(self, p): ''' condlist : condlist ',' condition | condition ''' if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] p[0].append(p[3]) def p_condition_string(self, p): "condition : VARINSTANCE '.' VARARG '=' VARSTRING" p[0] = (p[1], p[3], "'" + p[5][1:len(p[5]-1)] + "'") def p_condition_number(self, p): "condition : VARINSTANCE '.' VARARG '=' NUMBER" p[0] = (p[1], p[3], p[5]) def p_condition_float(self, p): "condition : VARINSTANCE '.' VARARG '=' FLOAT" p[0] = (p[1], p[3], p[5]) def p_features(self, p): "featureconf : FEFUNC ':' '[' featurelist ']' ','" p[0] = p[4] def p_dbfunction(self, p): ''' dbconf : DBFUNC ':' VARSTRING ',' | DBFUNC ':' VARSTRING | ''' if len(p) == 1: p[0] = None else: p[0] = p[3][1:len(p[3]) - 1] def p_scoring_function(self, p): ''' scoring : NETWORK ':' VARSTRING ',' | SCORE ':' RULESET '.' NUMBER ',' | SCORE ':' VARSTRING ',' ''' if len (p) == 5: if p[1] == "network": p[0] = ScoringFunction(ScoringType.NNet) elif p[1] == "score": p[0] = ScoringFunction(ScoringType.Func, scfunc=p[3][1:len(p[3])-1]) elif len(p) == 7: p[0] = ScoringFunction(ScoringType.NNetRef, scref=int(p[5])) def p_feature_list(self, p): ''' featurelist : featurelist ',' featurefunc | featurefunc ''' if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] p[0].append(p[3]) def p_feature_func(self, p): ''' featurefunc : EMBEDDING '(' VARSTRING ',' VARSTRING ',' VARSTRING ',' VARSTRING ',' VARSTRING ')' | VECTOR '(' VARSTRING ')' | INPUT '(' VARSTRING ')' ''' feature_name = p[3][1:len(p[3])-1] if len(p) == 13: emb_container = p[5][1:len(p[5])-1] vocab_size = p[7][1:len(p[7])-1] emb_size = p[9][1:len(p[9])-1] vocab_index = p[11][1:len(p[11])-1] p[0] = FeatureFunction(feature_name, FeatureType.Embedding, emb_container, vocab_size, emb_size, vocab_index) elif p[1] == "vector": p[0] = FeatureFunction(feature_name, FeatureType.Vector) elif p[1] == "input": p[0] = FeatureFunction(feature_name, FeatureType.Input) def p_hard_constraint_rule(self, p): ''' rule : HARDCONSTRAINT ':' proposition filters dbconf ''' (body, head) = p[3] print p[5] if len(p) == 8: p[0] = RuleTemplate(body, head, p[5], None, float('inf'), None, True, None, None, p[7], None) else: p[0] = RuleTemplate(body, head, [], None, float('inf'), None, True, None, None, p[5], None) # OJO: this would change when head hand side stops being a single predicate def p_proposition(self, p): ''' proposition : conjunction IMPL instance ',' proposition : conjunction IMPL instance ''' # returns (body_list, head_instance) p[0] = (p[1], p[3]) def p_conjunction(self, p): ''' conjunction : conjunction '&' instance | instance ''' if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] p[0].append(p[3]) def p_instance(self, p): "instance : VARPRED '(' argumentlist ')'" p[0] = PredicateTemplate(p[1], p[3]) def p_instance_neg(self, p): "instance : '~' VARPRED '(' argumentlist ')'" p[0] = PredicateTemplate(p[2], p[4], isneg=True) def p_instance_target(self, p): "instance : VARPRED '(' argumentlist ')' '^' '?'" p[0] = PredicateTemplate(p[1], p[3], isobs=False) def p_instance_neg_target(self, p): "instance : '~' VARPRED '(' argumentlist ')' '^' '?'" p[0] = PredicateTemplate(p[2], p[4], isneg=True, isobs=False) def p_instance_select(self, p): "instance : VARPRED '(' argumentlist ')' '*'" p[0] = PredicateTemplate(p[1], p[3], select=True) def p_instance_neg_select(self, p): "instance : '~' VARPRED '(' argumentlist ')' '*'" p[0] = PredicateTemplate(p[1], p[3], isneg=True, select=True) def p_instance_target_select(self, p): "instance : VARPRED '(' argumentlist ')' '^' '?' '*'" p[0] = PredicateTemplate(p[1], p[3], isobs=False, select=True) def p_instance_neg_target_select(self, p): "instance : '~' VARPRED '(' argumentlist ')' '^' '?' '*'" p[0] = PredicateTemplate(p[1], p[3], isneg=True, isobs=False, select=True) def p_argument_list(self, p): ''' argumentlist : argumentlist ',' argument | argument ''' if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] p[0].append(p[3]) def p_argument_variable(self, p): "argument : VARINSTANCE" p[0] = Argument(p[1], isconstant=False) def p_argument_constant(self, p): "argument : VARSTRING" p[0] = Argument(p[1][1:len(p[1]) - 1], isconstant=True) def p_argument_target(self, p): "argument : VARINSTANCE '^' VARPRED '?'" p[0] = Argument(p[1], isconstant=False, isobs=False, label=Label(p[3], self.label_types[p[3]], self.label_classes[p[3]])) def p_argument_constant_target(self, p): "argument : VARSTRING '^' VARPRED '?'" p[0] = Argument(p[1][1:len(p[1]) - 1], isconstant=True, isobs=False, label=Label(p[3], self.label_types[p[3]], self.label_classes[p[3]])) def p_error(self, p): if p is not None: print "Syntax error at '%s'" % p.value def build(self, **kwargs): self.lexer.build() self.parser = yacc.yacc(module=self, **kwargs) def parse(self, filename): with open(filename) as f: text = f.read() self.parser.parse(text)
class Parser(object): precedence = ( ('left', 'EQUAL', 'NOT_EQUAL'), ('left', 'LT', 'LE', 'GT', 'GE'), ('left', 'PLUS', 'MINUS'), ('left', 'TIMES', 'DIV'), ) def __init__(self): self.error_count = 0 self.lexer = Lexer() self.lexer.build(optimize=False, debug=True) self.tokens = self.lexer.tokens self.parser = yacc.yacc(module=self, optimize=False, debug=True) def parse(self, input_text): return self.parser.parse(input_text) def p_translation_unit(self, p): """translation_unit : external_declaration | translation_unit external_declaration""" if len(p) == 3: p[0] = p[1] p[0].children.append(p[2]) else: p[0] = TranslationUnitList([p[1]]) def p_external_declaration(self, p): """external_declaration : function_definition | declaration """ p[0] = p[1] def p_function_definition(self, p): """function_definition : type_specifier IDENTIFIER LPAREN parameters RPAREN compound_statement""" identifier = Identifier(p[2][0]) identifier.coord = Coord(p[2][1], p[2][2]) p[0] = FunctionDefinition(identifier, p[1], p[4], p[6]) def p_parameters(self, p): """parameters : parameter_list | """ if len(p) == 2: p[0] = p[1] else: p[0] = ParameterList([]) def p_parameter_list(self, p): """parameter_list : parameter_list COMMA type_specifier IDENTIFIER | type_specifier IDENTIFIER """ if len(p) == 5: identifier = Identifier(p[4][0], p[3]) identifier.coord = Coord(p[4][1], p[4][2]) declaration = Declaration(p[3], identifier) declaration.coord = identifier.coord p[0] = p[1] p[0].children.append(declaration) else: identifier = Identifier(p[2][0], p[1]) identifier.coord = Coord(p[2][1], p[2][2]) declaration = Declaration(p[1], identifier) declaration.coord = identifier.coord p[0] = ParameterList([declaration]) def p_declaration_list(self, p): """declarations : declarations declaration | """ if len(p) == 3: p[0] = p[1] p[0].children.append(p[2]) else: p[0] = DeclarationList([]) def p_declaration(self, p): """declaration : type_specifier IDENTIFIER SEMICOLON""" identifier = Identifier(p[2][0], p[1]) identifier.coord = Coord(p[2][1], p[2][2]) p[0] = Declaration(p[1], identifier) p[0].coord = identifier.coord def p_statement_list(self, p): """statements : statements statement | """ if len(p) == 3: p[0] = p[1] p[0].children.append(p[2]) else: p[0] = StatementList([]) def p_control_if(self, p): """statement : IF LPAREN expression RPAREN statement | IF LPAREN expression RPAREN statement ELSE statement """ if len(p) == 6: p[0] = If(p[3], p[5]) else: p[0] = If(p[3], p[5], p[7]) def p_while_loop(self, p): """statement : WHILE LPAREN expression RPAREN statement""" p[0] = While(p[2], p[3]) def p_for_loop(self, p): """statement : FOR LPAREN expression_statement expression_statement RPAREN statement | FOR LPAREN expression_statement expression_statement expression RPAREN statement""" if len(p) == 7: p[0] = For(p[3], p[4], None, p[6]) else: p[0] = For(p[3], p[4], p[5], p[7]) def p_assignment(self, p): """statement : IDENTIFIER ASSIGN expression SEMICOLON""" identifier = Identifier(p[1][0]) identifier.coord = Coord(p[1][1], p[1][2]) p[0] = Assignment(identifier, p[3]) p[0].coord = identifier.coord def p_compound_statement(self, p): """statement : compound_statement""" p[0] = p[1] def p_expression_statement(self, p): """statement : expression_statement""" p[0] = p[1] def p_compound(self, p): """compound_statement : LBRACE declarations statements RBRACE""" p[0] = CompoundStatement(p[2], p[3]) def p_expression_semi(self, p): """expression_statement : SEMICOLON | expression SEMICOLON""" if len(p) == 2: p[0] = None else: p[0] = p[1] def p_binary_expression(self, p): """expression : unary_expression | expression LT expression | expression LE expression | expression GT expression | expression GE expression | expression PLUS expression | expression MINUS expression | expression TIMES expression | expression DIV expression""" if len(p) == 2: p[0] = p[1] else: binary_op = BinaryOperator(p[2][0], p[1], p[3]) binary_op.coord = Coord(p[2][1], p[2][2]) p[0] = binary_op def p_unary_expression(self, p): """unary_expression : primary_expression | unary_operator unary_expression""" if len(p) == 2: p[0] = p[1] else: p[0] = UnaryOperator(p[1], p[2]) def p_expression_paren(self, p): """primary_expression : LPAREN expression RPAREN""" p[0] = p[2] def p_primary_expression_number(self, p): """primary_expression : NUMBER""" if '.' in p[1][0]: p[0] = Constant(p[1][0], floatTypeDescriptor) else: p[0] = Constant(p[1][0], integerTypeDescriptor) def p_primary_expression_ref(self, p): """primary_expression : IDENTIFIER""" reference = Reference(p[1][0]) reference.coord = Coord(p[1][1], p[1][2]) p[0] = reference def p_unary_operator(self, p): """unary_operator : NOT | MINUS | PLUS""" p[0] = p[1][0] def p_type_specifier(self, p): """type_specifier : CHAR | INT | FLOAT""" if p[1][0] == "char": p[0] = charTypeDescriptor elif p[1][0] == "int": p[0] = integerTypeDescriptor else: p[0] = floatTypeDescriptor def p_error(self, p): self.error_count += 1 if p is not None: Error.syntax_error("unexpected token '%s'" % p.value[0], p.value[1], p.value[2]) while True: token = self.parser.token() if token is None \ or token.type == "SEMICOLON" \ or token.type == "LBRACE": break self.parser.errok() return token else: Error.syntax_error("unexpected end-of-file")
class Parser(): def _type_modify_decl(self, decl, modifier): """ Tacks a type modifier on a declarator, and returns the modified declarator. Note: the declarator and modifier may be modified """ modifier_head = modifier modifier_tail = modifier # The modifier may be a nested list. Reach its tail. while modifier_tail.type: modifier_tail = modifier_tail.type # If the decl is a basic type, just tack the modifier onto it if isinstance(decl, VarDecl): modifier_tail.type = decl return modifier else: # Otherwise, the decl is a list of modifiers. Reach # its tail and splice the modifier onto the tail, # pointing to the underlying basic type. decl_tail = decl while not isinstance(decl_tail.type, VarDecl): decl_tail = decl_tail.type modifier_tail.type = decl_tail.type decl_tail.type = modifier_head return decl def _fix_decl_name_type(self, decl, typename): """ Fixes a declaration. Modifies decl. """ # Reach the underlying basic type t = decl while not isinstance(t, VarDecl): t = t.type decl.name = t.name # The typename is a list of types. If any type in this # list isn't an Type, it must be the only # type in the list. # If all the types are basic, they're collected in the # Type holder. # make a copy of typename t.type = self.copyType(typename) return decl def copyType(self, typename): n = Type(names=[]) n.arrayLevel = typename.arrayLevel for t in typename.names: n.names.append(t) return n def _build_declarations(self, spec, decls): """ Builds a list of declarations all sharing the given specifiers. """ declarations = [] for decl in decls: assert decl['decl'] is not None declaration = Decl(name=None, type=decl['decl'], init=decl.get('init'), coord=decl['decl'].coord) fixed_decl = self._fix_decl_name_type(declaration, spec) declarations.append(fixed_decl) return declarations def _token_coord(self, p, token_idx): last_cr = p.lexer.lexer.lexdata.rfind('\n', 0, p.lexpos(token_idx)) if last_cr < 0: last_cr = -1 column = (p.lexpos(token_idx) - (last_cr)) return Coord(p.lineno(token_idx), column) def print_error(msg, x, y): print('Lexical error: %s at %d:%d' % (msg, x, y)) def __init__(self): self.lexer = Lexer(error_func=self.print_error) self.lexer.build() self.tokens = self.lexer.tokens self.parser = yacc.yacc(module=self, start='program') def parse(self, data, filename='', deb=False): return self.parser.parse(input=data, lexer=self.lexer, debug=deb) def p_program(self, p): """ program : global_declaration_list """ p[0] = Program(p[1], coord=self._token_coord(p, 1)) def p_global_declaration_list(self, p): """ global_declaration_list : global_declaration | global_declaration_list global_declaration """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_global_declaration1(self, p): """ global_declaration : declaration """ p[0] = GlobalDecl(p[1], coord=self._token_coord(p, 1)) def p_global_declaration2(self, p): """ global_declaration : function_definition """ p[0] = p[1] def p_declaration_list(self, p): """ declaration_list : declaration | declaration_list declaration """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_declaration_list_opt(self, p): """ declaration_list_opt : declaration_list | empty """ p[0] = p[1] def p_function_definition(self, p): """ function_definition : type_specifier declarator declaration_list_opt compound_statement """ decl = p[2] decls = self._build_declarations(spec=p[1], decls=[dict(decl=decl, init=None)])[0] p[0] = FuncDef(decl=decls, type=p[1], dl=p[3], cs=p[4], coord=p[2].coord) def p_function_definition1(self, p): """ function_definition : declarator declaration_list_opt compound_statement """ t = Type(['int'], coord=self._token_coord(p, 1)) decl = p[1] decls = self._build_declarations(spec=t, decls=[dict(decl=decl, init=None)])[0] p[0] = FuncDef(decls, None, p[2], p[3], coord=p[1].coord) def p_identifier(self, p): """ identifier : ID """ p[0] = ID(p[1], coord=self._token_coord(p, 1)) def p_string(self, p): """ string : STRING_LITERAL """ p[0] = Constant('string', p[1], coord=self._token_coord(p, 1)) def p_integer_constant(self, p): """ integer_constant : INT_CONST """ p[0] = Constant('int', int(p[1]), coord=self._token_coord(p, 1)) def p_character_constant(self, p): """ character_constant : CHAR_CONST """ p[0] = Constant('char', p[1], coord=self._token_coord(p, 1)) def p_floating_constant(self, p): """ floating_constant : FLOAT_CONST """ p[0] = Constant('float', float(p[1]), coord=self._token_coord(p, 1)) def p_type_specifier(self, p): """ type_specifier : VOID | CHAR | INT | FLOAT """ p[0] = Type([p[1]], coord=self._token_coord(p, 1)) def p_identifier_list(self, p): """ identifier_list : identifier | identifier_list identifier """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_identifier_list_opt(self, p): """ identifier_list_opt : identifier_list | empty """ p[0] = p[1] def p_declarator(self, p): """ declarator : direct_declarator | pointer direct_declarator """ if len(p) == 2: p[0] = p[1] else: p[0] = self._type_modify_decl(p[2], p[1]) def p_pointer(self, p): """ pointer : TIMES | TIMES pointer """ if len(p) == 2: p[0] = PtrDecl([p[1]], self._token_coord(p, 1)) else: p[2].stars.append(p[1]) p[0] = p[2] def p_direct_declarator(self, p): """ direct_declarator : identifier | LPAREN declarator RPAREN | direct_declarator LBRACKET constant_expression RBRACKET """ if len(p) == 2: p[0] = VarDecl(p[1], coord=p[1].coord) elif len(p) == 4: p[0] = p[2] elif len(p) == 5: arr = ArrayDecl(None, p[3], coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=arr) def p_direct_declarator2(self, p): """ direct_declarator : direct_declarator LBRACKET RBRACKET | direct_declarator LPAREN parameter_list RPAREN """ if len(p) == 4: arr = ArrayDecl(None, None, coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=arr) elif len(p) == 5: func = FuncDecl(args=p[3], type=None, coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=func) def p_direct_declarator3(self, p): """ direct_declarator : direct_declarator LPAREN identifier_list_opt RPAREN """ func = FuncDecl(args=p[3], type=None, coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=func) def p_constant_expression(self, p): """ constant_expression : binary_expression """ p[0] = p[1] def p_binary_expression(self, p): """ binary_expression : cast_expression | binary_expression TIMES binary_expression | binary_expression DIVIDE binary_expression | binary_expression MOD binary_expression | binary_expression PLUS binary_expression | binary_expression MINUS binary_expression | binary_expression LT binary_expression | binary_expression LE binary_expression | binary_expression GT binary_expression | binary_expression GE binary_expression | binary_expression EQ binary_expression | binary_expression NE binary_expression | binary_expression AND binary_expression | binary_expression OR binary_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = BinaryOp(p[2], p[1], p[3], coord=p[1].coord) def p_cast_expression(self, p): """ cast_expression : unary_expression | LPAREN type_specifier RPAREN cast_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = Cast(p[2], p[4], coord=self._token_coord(p, 1)) def p_unary_expression(self, p): """ unary_expression : postfix_expression | PLUSPLUS unary_expression | MINUSMINUS unary_expression | unary_operator cast_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = UnaryOp(p[1], p[2], coord=p[2].coord) def p_postfix_expression(self, p): """ postfix_expression : primary_expression | postfix_expression PLUSPLUS | postfix_expression MINUSMINUS | postfix_expression LPAREN expression_opt RPAREN """ if len(p) == 2: p[0] = p[1] elif len(p) == 3: p[0] = UnaryOp('p' + p[2], p[1], coord=p[1].coord) else: p[0] = FuncCall(p[1], p[3], coord=p[1].coord) def p_postfix_expression2(self, p): """ postfix_expression : postfix_expression LBRACKET expression RBRACKET """ p[0] = ArrayRef(p[1], p[3], coord=p[1].coord) def p_primary_expression(self, p): """ primary_expression : identifier | constant | string | LPAREN expression RPAREN """ if len(p) == 2: # (id,constant and string) p[0] = p[1] else: # (expression) p[0] = p[2] def p_constant(self, p): """ constant : integer_constant | character_constant | floating_constant """ p[0] = p[1] def p_expression(self, p): """ expression : assignment_expression | expression COMMA assignment_expression """ if len(p) == 2: # single expression p[0] = ExprList([p[1]], coord=p[1].coord) else: p[1].list.append(p[3]) p[0] = p[1] def p_expression_opt(self, p): """ expression_opt : expression | empty """ p[0] = p[1] def p_expression_statement(self, p): """ expression_statement : expression_opt SEMI """ if p[1] is None: p[0] = EmptyStatement(coord=self._token_coord(p, 1)) else: p[0] = p[1] def p_assignment_expression(self, p): """ assignment_expression : binary_expression | unary_expression assignment_operator assignment_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = Assignment(p[2], p[1], p[3], p[1].coord) def p_assignment_operator(self, p): """ assignment_operator : EQUALS | TIMESEQUAL | DIVEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL """ p[0] = p[1] def p_unary_operator(self, p): """ unary_operator : ADDRESS | TIMES | PLUS | MINUS | NOT """ p[0] = p[1] def p_parameter_list(self, p): """ parameter_list : parameter_declaration | parameter_list COMMA parameter_declaration """ if len(p) == 2: # single parameter p[0] = ParamList([p[1]], p[1].coord) else: p[1].list.append(p[3]) p[0] = p[1] def p_parameter_declaration(self, p): """ parameter_declaration : type_specifier declarator """ p[0] = self._build_declarations(spec=p[1], decls=[dict(decl=p[2])])[0] def p_init_declarator_list(self, p): """ init_declarator_list : init_declarator | init_declarator_list COMMA init_declarator """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[3]] def p_init_declarator_list_opt(self, p): """ init_declarator_list_opt : init_declarator_list | empty """ p[0] = p[1] def p_decl_body(self, p): """ decl_body : type_specifier init_declarator_list_opt """ if p[2] is None: decls = None # decls = [Decl(name=None,type=p[1],init=None,coord=p[1].coord)] else: decls = self._build_declarations(spec=p[1], decls=p[2]) p[0] = decls def p_declaration(self, p): """ declaration : decl_body SEMI """ p[0] = p[1] def p_init_declarator(self, p): """ init_declarator : declarator | declarator EQUALS initializer """ p[0] = dict(decl=p[1], init=(p[3] if len(p) > 2 else None)) def p_initializer(self, p): """ initializer : assignment_expression | LBRACE initializer_list RBRACE | LBRACE initializer_list COMMA RBRACE """ if len(p) == 2: p[0] = p[1] else: p[0] = InitList(p[2], coord=p[2][0].coord) def p_initializer_list(self, p): """ initializer_list : initializer | initializer_list COMMA initializer """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[3]] def p_block_item(self, p): """ block_item : declaration | statement """ p[0] = p[1] if isinstance(p[1], list) else [p[1]] def p_block_item_list(self, p): """ block_item_list : block_item | block_item_list block_item """ # Empty block items (plain ';') produce [None], so ignore them p[0] = p[1] if (len(p) == 2 or p[2] == [None]) else p[1] + p[2] def p_block_item_list_opt(self, p): """ block_item_list_opt : block_item_list | empty """ p[0] = p[1] def p_compound_statement(self, p): """ compound_statement : LBRACE block_item_list_opt RBRACE """ p[0] = Compound(p[2], coord=self._token_coord(p, 1)) def p_statement(self, p): """ statement : expression_statement | compound_statement | selection_statement | jump_statement | assert_statement | print_statement | read_statement | iteration_statement """ p[0] = p[1] def p_selection_statement(self, p): """ selection_statement : IF LPAREN expression RPAREN statement | IF LPAREN expression RPAREN statement ELSE statement """ if len(p) == 6: p[0] = If(p[3], p[5], None, coord=self._token_coord(p, 1)) else: p[0] = If(p[3], p[5], p[7], coord=self._token_coord(p, 1)) def p_iteration_statement(self, p): """ iteration_statement : WHILE LPAREN expression RPAREN statement | FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement | FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement """ if len(p) == 6: # while p[0] = While(p[3], p[5], coord=self._token_coord(p, 1)) elif len(p) == 10: p[0] = For(p[3], p[5], p[7], p[9], coord=self._token_coord(p, 1)) else: # for p[0] = For(DeclList(decls=p[3], coord=self._token_coord(p, 1)), p[4], p[6], p[8], coord=self._token_coord(p, 1)) def p_jump_statement(self, p): """ jump_statement : BREAK SEMI | RETURN expression_opt SEMI """ if len(p) == 3: p[0] = Break(coord=self._token_coord(p, 1)) else: p[0] = Return(p[2], coord=self._token_coord(p, 1)) def p_assert_statement(self, p): """ assert_statement : ASSERT expression SEMI """ p[0] = Assert(p[2], coord=self._token_coord(p, 1)) def p_print_statement(self, p): """ print_statement : PRINT LPAREN expression RPAREN SEMI | PRINT LPAREN RPAREN SEMI """ if len(p) == 6: p[0] = Print(p[3], coord=self._token_coord(p, 1)) else: p[0] = Print(None, coord=self._token_coord(p, 1)) def p_read_statement(self, p): """ read_statement : READ LPAREN expression RPAREN SEMI """ p[0] = Read(p[3], coord=self._token_coord(p, 1)) def p_empty(self, p): """empty : """ p[0] = None def p_error(self, p): if p: print("Error near the symbol %s at line %d" % (p.value, p.lineno)) else: print("Error at the end of input") precedence = ( ('left', 'OR'), ('left', 'AND'), ('left', 'EQ', 'NE'), ('left', 'LT', 'LE', 'GT', 'GE'), ('left', 'PLUS', 'MINUS'), ('left', 'TIMES', 'DIVIDE', 'MOD'), ('left', 'ADDRESS', 'NOT'), )
def parse(source, debug=True): lexer = Lexer() lexer.build() yacc.yacc(debug=debug) return yacc.parse(source, lexer=lexer.lexer)
class Parser(object): def __init__(self, program=""): self.program = program tokens = tokenrules.tokens # program def p_program_ex(self, p): '''program : external-declaration''' p[0] = ast.ExternalDeclarationList(p[1]) def p_program_prog(self, p): '''program : program external-declaration''' p[1].append(p[2]) p[0] = p[1] # declaration def p_external_declaration(self, p): '''external-declaration : declaration | function-prototype | function-definition''' p[0] = p[1] def p_declaration(self, p): '''declaration : type-specifier declarator-list SEMICOLON''' p[0] = ast.Declaration(p[1], p[2]) # declarator def p_declarator_list(self, p): '''declarator-list : declarator''' p[0] = ast.DeclaratorList(p[1]) def p_declarator_list_list(self, p): '''declarator-list : declarator-list COMMA declarator''' p[1].append(p[3]) p[0] = p[1] def p_declarator(self, p): '''declarator : direct-declarator''' p[0] = ast.Declarator("NORMAL", p[1]) def p_declarator_val(self, p): '''declarator : TIMES direct-declarator''' p[0] = ast.Declarator("POINTER", p[2]) def p_direct_declarator(self, p): '''direct-declarator : identifier''' p[0] = ast.DirectDeclarator(p[1]) def p_direct_declarator_array(self, p): '''direct-declarator : identifier LBRACKET constant RBRACKET''' p[0] = ast.DirectArrayDeclarator(p[1], p[3]) # function def p_function_prototype(self, p): '''function-prototype : type-specifier function-declarator SEMICOLON''' p[0] = ast.FunctionPrototype(p[1], p[2]) def p_function_declarator(self, p): '''function-declarator : identifier LPAREN parameter-type-list RPAREN''' p[0] = ast.FunctionDeclarator("NORMAL", p[1], p[3]) def p_function_declarator_noparam(self, p): '''function-declarator : identifier LPAREN RPAREN''' p[0] = ast.FunctionDeclarator("NORMAL", p[1], ast.NullNode()) def p_function_declarator_pointer(self, p): '''function-declarator : TIMES identifier LPAREN parameter-type-list RPAREN''' p[0] = ast.FunctionDeclarator("POINTER", p[2], p[4]) def p_function_declarator_pointer_noparam(self, p): '''function-declarator : TIMES identifier LPAREN RPAREN''' p[0] = ast.FunctionDeclarator("POINTER", p[2], ast.NullNode()) def p_fuction_definition(self, p): '''function-definition : type-specifier function-declarator compound-statement''' p[0] = ast.FunctionDefinition(p[1], p[2], p[3]) # parameter def p_parameter_type_list_declaration(self, p): '''parameter-type-list : parameter-declaration''' p[0] = ast.ParameterTypeList(p[1]) def p_parameter_type_list_list(self, p): '''parameter-type-list : parameter-type-list COMMA parameter-declaration''' p[1].append(p[3]) p[0] = p[1] def p_parameter_declaration(self, p): '''parameter-declaration : type-specifier parameter-declarator''' p[0] = ast.ParameterDeclaration(p[1], p[2]) def p_parameter_declarator(self, p): '''parameter-declarator : identifier''' p[0] = ast.ParameterDeclarator("NORMAL", p[1]) def p_paramenter_declarator_pointer(self, p): '''parameter-declarator : TIMES identifier''' p[0] = ast.ParameterDeclarator("POINTER", p[2]) # type specifier def p_type_specifier(self, p): '''type-specifier : INT | VOID''' p[0] = ast.TypeSpecifier(p[1]) # statement def p_statement_semicolon(self, p): '''statement : SEMICOLON''' p[0] = ast.NullNode() def p_statement_expression(self, p): '''statement : expression SEMICOLON''' p[0] = ast.ExpressionStatement(p[1]) def p_statement_compound_statement(self, p): '''statement : compound-statement''' p[0] = p[1] # if statement def p_statement_if(self, p): '''statement : IF LPAREN expression RPAREN statement''' p[0] = ast.IfStatement(p[3], p[5], ast.NullNode(), p.lineno(1)) def p_statement_if_else(self, p): '''statement : IF LPAREN expression RPAREN statement ELSE statement''' p[0] = ast.IfStatement(p[3], p[5], p[7], p.lineno(1)) # while loop def p_statement_while(self, p): '''statement : WHILE LPAREN expression RPAREN statement''' p[0] = ast.WhileLoop(p[3], p[5], p.lineno(1)) # for loop def p_statement_for(self, p): '''statement : FOR LPAREN expression SEMICOLON expression SEMICOLON expression RPAREN statement''' p[9].statement_list.append(ast.ExpressionStatement(p[7])) p[0] = ast.ForLoop(ast.ExpressionStatement(p[3]), ast.WhileLoop(p[5], p[9], p.lineno(1))) def p_statement_for_noinit(self, p): '''statement : FOR LPAREN SEMICOLON expression SEMICOLON expression RPAREN statement''' p[8].statement_list.append(ast.ExpressionStatement(p[6])) p[0] = ast.ForLoop(ast.NullNode(), ast.WhileLoop(p[4], p[8], p.lineno(1))) def p_statement_for_noend(self, p): '''statement : FOR LPAREN expression SEMICOLON SEMICOLON expression RPAREN statement''' p[8].statement_list.append(ast.ExpressionStatement(p[6])) p[0] = ast.ForLoop(ast.ExpressionStatement(p[3]), ast.WhileLoop(ast.Number(1), p[8], p.lineno(1))) def p_statement_for_novar(self, p): '''statement : FOR LPAREN expression SEMICOLON expression SEMICOLON RPAREN statement''' p[0] = ast.ForLoop(ast.ExpressionStatement(p[3]), ast.WhileLoop(p[5], p[8], p.lineno(1))) def p_statement_for_onlyinit(self, p): '''statement : FOR LPAREN expression SEMICOLON SEMICOLON RPAREN statement''' p[0] = ast.ForLoop(ast.ExpressionStatement(p[3]), ast.WhileLoop(ast.Number(1), p[7], p.lineno(1))) def p_statement_for_onlyend(self, p): '''statement : FOR LPAREN SEMICOLON expression SEMICOLON RPAREN statement''' p[0] = ast.ForLoop(ast.NullNode(), ast.WhileLoop(p[4], p[7], p.lineno(1))) def p_statement_for_onlyvar(self, p): '''statement : FOR LPAREN SEMICOLON SEMICOLON expression RPAREN statement''' p[7].statement_list.append(ast.ExpressionStatement(p[5])) p[0] = ast.ForLoop(ast.NullNode(), ast.WhileLoop(ast.Number(1), p[7], p.lineno(1))) def p_statement_for_noexp(self, p): '''statement : FOR LPAREN SEMICOLON SEMICOLON RPAREN statement''' p[0] = ast.ForLoop(ast.NullNode(), ast.WhileLoop(ast.Number(1), p[6], p.lineno(1))) # return statement def p_statement_return_void(self, p): '''statement : RETURN SEMICOLON''' p[0] = ast.ReturnStatement(ast.NullNode()) def p_statement_return(self, p): '''statement : RETURN expression SEMICOLON''' p[0] = ast.ReturnStatement(p[2]) # compound statement def p_compound_statement_empty(self, p): '''compound-statement : LBRACE RBRACE''' p[0] = ast.CompoundStatement(ast.DeclarationList(ast.NullNode()), ast.StatementList(ast.NullNode())) def p_compound_statement_declaration(self, p): '''compound-statement : LBRACE declaration-list RBRACE''' # p[0] = ast.CompoundStatement(ast.DeclarationList(p[2]), ast.StatementList(ast.NullNode())) p[0] = ast.CompoundStatement(p[2], ast.StatementList(ast.NullNode())) def p_compound_statement_statement(self, p): '''compound-statement : LBRACE statement-list RBRACE''' # p[0] = ast.CompoundStatement(ast.DeclarationList(ast.NullNode()), ast.StatementList(p[2])) p[0] = ast.CompoundStatement(ast.DeclarationList(ast.NullNode()), p[2]) def p_compound_statement_declaration_statement(self, p): '''compound-statement : LBRACE declaration-list statement-list RBRACE''' # p[0] = ast.CompoundStatement(ast.DeclarationList(p[2]), ast.StatementList(p[3])) p[0] = ast.CompoundStatement(p[2], p[3]) # declaration list def p_declaration_list(self, p): '''declaration-list : declaration''' p[0] = ast.DeclarationList(p[1]) def p_declaration_list_declaration_list(self, p): '''declaration-list : declaration-list declaration''' p[1].append(p[2]) p[0] = p[1] # statement list def p_statement_list(self, p): '''statement-list : statement''' # if isinstance(p[1], ast.StatementList): # p[0].append(p[1]) # else: # p[0] = ast.StatementList(p[1]) p[0] = ast.StatementList(p[1]) def p_statement_list_statement_list(self, p): '''statement-list : statement-list statement''' p[1].append(p[2]) p[0] = p[1] # expression def p_expression_assign_expr(self, p): '''expression : assign-expr''' p[0] = p[1] def p_expression_expression(self, p): '''expression : expression COMMA assign-expr''' p[0] = p[1].append(p[3]) # assign def p_assign_expr_or(self, p): '''assign-expr : logical-OR-expr''' p[0] = p[1] def p_assign_expr_assign(self, p): '''assign-expr : logical-OR-expr ASSIGN assign-expr''' p[0] = ast.BinaryOperators("ASSIGN", p[1], p[3], p.lineno(2)) def p_plus_equal(self, p): '''assign-expr : logical-OR-expr PLUS_EQ assign-expr''' p[0] = ast.BinaryOperators("ASSIGN", p[1], ast.BinaryOperators("PLUS", p[1], p[3], p.lineno(2)), p.lineno(2)) def p_minus_equal(self, p): '''assign-expr : logical-OR-expr MINUS_EQ assign-expr''' p[0] = ast.BinaryOperators("ASSIGN", p[1], ast.BinaryOperators("MINUS", p[1], p[3], p.lineno(2)), p.lineno(2)) # logical expression def p_logical_OR_expr_and(self, p): '''logical-OR-expr : logical-AND-expr''' p[0] = p[1] def p_logical_OR_expr_or(self, p): '''logical-OR-expr : logical-OR-expr OR logical-AND-expr''' p[0] = ast.BinaryOperators("OR", p[1], p[3], p.lineno(2)) def p_logical_AND_expr_equal(self, p): '''logical-AND-expr : equality-expr''' p[0] = p[1] def p_logical_AND_expr_and(self, p): '''logical-AND-expr : logical-AND-expr AND equality-expr''' p[0] = ast.BinaryOperators("AND", p[1], p[3], p.lineno(2)) # relational operation def p_equality_expr_rel(self, p): '''equality-expr : relational-expr''' p[0] = p[1] def p_equality_expr_eq(self, p): '''equality-expr : equality-expr EQUAL relational-expr''' p[0] = ast.BinaryOperators("EQUAL", p[1], p[3], p.lineno(2)) def p_equality_expr_neq(self, p): '''equality-expr : equality-expr NEQ relational-expr''' p[0] = ast.BinaryOperators("NEQ", p[1], p[3], p.lineno(2)) def p_relational_expr_add(self, p): '''relational-expr : add-expr''' p[0] = p[1] def p_relational_expr_lt(self, p): '''relational-expr : relational-expr LT add-expr''' p[0] = ast.BinaryOperators("LT", p[1], p[3], p.lineno(2)) def p_relational_expr_gt(self, p): '''relational-expr : relational-expr GT add-expr''' p[0] = ast.BinaryOperators("GT", p[1], p[3], p.lineno(2)) def p_relational_expr_leq(self, p): '''relational-expr : relational-expr LEQ add-expr''' p[0] = ast.BinaryOperators("LEQ", p[1], p[3], p.lineno(2)) def p_relational_expr_geq(self, p): '''relational-expr : relational-expr GEQ add-expr''' p[0] = ast.BinaryOperators("GEQ", p[1], p[3], p.lineno(2)) # arithmetic operation def p_add_expr_mult(self, p): '''add-expr : mult-expr''' p[0] = p[1] def p_add_expr_plus(self, p): '''add-expr : add-expr PLUS mult-expr''' p[0] = ast.BinaryOperators("PLUS", p[1], p[3], p.lineno(2)) def p_add_expr_minus(self, p): '''add-expr : add-expr MINUS mult-expr''' p[0] = ast.BinaryOperators("MINUS", p[1], p[3], p.lineno(2)) def p_mult_expr_unary(self, p): '''mult-expr : unary-expr''' p[0] = p[1] def p_mult_expr_times(self, p): '''mult-expr : mult-expr TIMES unary-expr''' p[0] = ast.BinaryOperators("TIMES", p[1], p[3], p.lineno(2)) def p_mult_expr_divide(self, p): '''mult-expr : mult-expr DIVIDE unary-expr''' p[0] = ast.BinaryOperators("DIVIDE", p[1], p[3], p.lineno(2)) # unary expression def p_unary_expr_post(self, p): '''unary-expr : postfix-expr''' p[0] = p[1] def p_unary_expr_minus(self, p): '''unary-expr : MINUS unary-expr''' # p[0] = ast.Negative(p[2]) p[0] = ast.BinaryOperators("MINUS", ast.Number(0), p[2], p.lineno(2)) def p_unary_expr_addr(self, p): '''unary-expr : ADDRESS unary-expr''' if isinstance(p[2], ast.Pointer): p[0] = p[2].expression else: p[0] = ast.Address(p[2], p.lineno(1)) def p_unary_expr_val(self, p): '''unary-expr : TIMES unary-expr''' p[0] = ast.Pointer(p[2], p.lineno(1)) def p_unary_expr_inc(self, p): '''unary-expr : identifier INC''' # p[0] = ast.Increment(p[1]) p[0] = ast.BinaryOperators("ASSIGN", p[1], ast.BinaryOperators("PLUS", p[1], ast.Number(1), p.lineno(2)), p.lineno(2)) def p_unary_expr_dec(self, p): '''unary-expr : identifier DEC''' # p[0] = ast.Decrement(p[1]) p[0] = ast.BinaryOperators("ASSIGN", p[1], ast.BinaryOperators("MINUS", p[1], ast.Number(1), p.lineno(2)), p.lineno(2)) # postfix expression def p_postfix_expr_primary(self, p): '''postfix-expr : primary-expr''' p[0] = p[1] def p_postfix_expr_array(self, p): '''postfix-expr : postfix-expr LBRACKET expression RBRACKET''' # p[0] = ast.ArrayExpression(p[1], p[3]) p[0] = ast.Pointer(ast.BinaryOperators("PLUS", p[1], p[3], p.lineno(2)), p.lineno(2)) def p_postfix_expr_nullarg(self, p): '''postfix-expr : identifier LPAREN RPAREN''' p[0] = ast.FunctionExpression(p[1], ast.ArgumentExpressionList(), p[1].lineno) def p_postfix_expr_arg(self, p): '''postfix-expr : identifier LPAREN argument-expression-list RPAREN''' p[0] = ast.FunctionExpression(p[1], p[3], p[1].lineno) # primary expression def p_primary_expr_id(self, p): '''primary-expr : identifier''' p[0] = p[1] def p_primary_expr_const(self, p): '''primary-expr : constant''' p[0] = p[1] def p_primary_expr_expr(self, p): '''primary-expr : LPAREN expression RPAREN''' p[0] = p[2] # argument expression def p_argument_expression_list_assign(self, p): '''argument-expression-list : assign-expr''' p[0] = ast.ArgumentExpressionList(p[1]) def p_argument_expression_list_list(self, p): '''argument-expression-list : argument-expression-list COMMA assign-expr''' p[1].append(p[3]) p[0] = p[1] # identifier def p_identifier(self, p): '''identifier : ID''' p[0] = ast.Identifier(p[1], p.lineno(1)) # constant def p_constant(self, p): '''constant : NUMBER''' p[0] = ast.Number(p[1]) # def p_empty(self, p): # '''empty : ''' # p[0] = ast.NullNode() def p_error(self, p): if p: sys.exit("Syntax error at token", p.type) # Just discard the token and tell the parser it's okay. self.parser.errok() else: sys.exit("Syntax error at EOF") # 解析実行部 def build(self, debug=False, **kwargs): # 字句解析 self.lexer = Lexer() self.lexer.build(debug=debug) # 構文解析 self.parser = yacc.yacc(module=self, debug=debug) def parse(self, data): result = self.parser.parse(data) return result
class Parser(): def print_error(msg, x, y): print('Lexical error: %s at %d:%d' % (msg, x, y)) def __init__(self): self.lexer = Lexer(error_func=self.print_error) self.lexer.build() self.tokens = self.lexer.tokens self.parser = yacc.yacc(module=self, start='program') def parse(self, data): return self.parser.parse(input=data, lexer=self.lexer) def p_program(self, p): """ program : global_declaration_list """ p[0] = ('Program', p[1]) def p_global_declaration_list(self, p): """ global_declaration_list : global_declaration | global_declaration_list global_declaration """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_global_declaration(self, p): """ global_declaration : function_definition | declaration """ p[0] = ('global', p[1]) def p_declaration_list(self, p): """ declaration_list : declaration | declaration_list declaration """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_declaration_list_opt(self, p): """ declaration_list_opt : declaration_list | empty """ p[0] = p[1] def p_function_definition(self, p): """ function_definition : type_specifier declarator declaration_list_opt compound_statement | declarator declaration_list_opt compound_statement """ if len(p) == 5: p[0] = ('function', p[1], p[2], p[3], p[4]) else: p[0] = ('function', 'void', p[1], p[2], p[3]) def p_identifier(self, p): """ identifier : ID """ p[0] = ('Id', p[1]) def p_string(self, p): """ string : STRING_LITERAL """ p[0] = p[1] def p_integer_constant(self, p): """ integer_constant : INT_CONST """ p[0] = p[1] def p_character_constant(self, p): """ character_constant : CHAR_CONST """ p[0] = p[1] def p_floating_constant(self, p): """ floating_constant : FLOAT_CONST """ p[0] = p[1] def p_type_specifier(self, p): """ type_specifier : VOID | CHAR | INT | FLOAT """ p[0] = p[1] def p_identifier_list(self, p): """ identifier_list : identifier | identifier_list identifier """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_identifier_list_opt(self, p): """ identifier_list_opt : identifier_list | empty """ p[0] = p[1] def p_direct_declarator(self, p): """ direct_declarator : identifier | LPAREN declarator RPAREN | direct_declarator LBRACKET constant_expression RBRACKET """ if len(p) == 2: p[0] = p[1] elif len(p) == 4: p[0] = p[2] elif len(p) == 5: p[0] = p[1] + p[2] + p[3] + p[4] def p_direct_declarator2(self, p): """ direct_declarator : direct_declarator LBRACKET RBRACKET | direct_declarator LPAREN parameter_list RPAREN """ if len(p) == 4: p[0] = p[1] + p[2] + p[3] elif len(p) == 5: p[0] = (p[1], p[3]) def p_direct_declarator3(self, p): """ direct_declarator : direct_declarator LPAREN identifier_list_opt RPAREN """ p[0] = (p[1], p[3]) def p_declarator(self, p): """ declarator : direct_declarator """ p[0] = p[1] def p_constant_expression(self, p): """ constant_expression : binary_expression """ p[0] = p[1] def p_binary_expression(self, p): """ binary_expression : cast_expression | binary_expression TIMES binary_expression | binary_expression DIVIDE binary_expression | binary_expression MOD binary_expression | binary_expression PLUS binary_expression | binary_expression MINUS binary_expression | binary_expression LT binary_expression | binary_expression LE binary_expression | binary_expression GT binary_expression | binary_expression GE binary_expression | binary_expression EQ binary_expression | binary_expression NE binary_expression | binary_expression AND binary_expression | binary_expression OR binary_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = (p[2], p[1], p[3]) def p_cast_expression(self, p): """ cast_expression : unary_expression | LPAREN type_specifier RPAREN cast_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = ('cast', p[2], p[4]) def p_unary_expression(self, p): """ unary_expression : postfix_expression | PLUSPLUS unary_expression | MINUSMINUS unary_expression | unary_operator cast_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = (p[1], p[2]) def p_assignment_expression_list(self, p): """ assignment_expression_list : assignment_expression | assignment_expression_list assignment_expression """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_assignment_expression_list_opt(self, p): """ assignment_expression_list_opt : assignment_expression_list | empty """ p[0] = p[1] def p_postfix_expression(self, p): """ postfix_expression : primary_expression | postfix_expression PLUSPLUS | postfix_expression MINUSMINUS | postfix_expression LBRACKET expression RBRACKET | postfix_expression LPAREN assignment_expression_list_opt RPAREN """ if len(p) == 2: p[0] = p[1] elif len(p) == 3: p[0] = (p[1], p[2]) else: p[0] = (p[1], p[2], p[3], p[4]) def p_primary_expression(self, p): """ primary_expression : identifier | constant | string | LPAREN expression RPAREN """ if len(p) == 2: # (id,constant and string) p[0] = p[1] else: # (expression) p[0] = p[2] def p_constant(self, p): """ constant : integer_constant | character_constant | floating_constant """ p[0] = p[1] def p_expression(self, p): """ expression : assignment_expression | expression COMMA assignment_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = (p[2], p[1], p[3]) def p_assignment_expression(self, p): """ assignment_expression : binary_expression | unary_expression assignment_operator assignment_expression """ if len(p) == 2: p[0] = p[1] else: p[0] = (p[2], p[1], p[3]) def p_assignment_operator(self, p): """ assignment_operator : EQUALS | TIMESEQUAL | DIVEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL """ p[0] = p[1] def p_unary_operator(self, p): """ unary_operator : ADDRESS | TIMES | PLUS | MINUS | NOT """ p[0] = p[1] def p_parameter_list(self, p): """ parameter_list : parameter_declaration | parameter_list COMMA parameter_declaration """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[3]] def p_parameter_declaration(self, p): """ parameter_declaration : type_specifier declarator """ p[0] = (p[1], p[2]) def p_init_declarator_list(self, p): """ init_declarator_list : init_declarator | init_declarator_list init_declarator """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_init_declarator_list_opt(self, p): """ init_declarator_list_opt : init_declarator_list | empty """ p[0] = p[1] def p_declaration(self, p): """ declaration : type_specifier init_declarator_list_opt SEMI """ p[0] = (p[1], p[2]) def p_init_declarator(self, p): """ init_declarator : declarator | declarator EQUALS initializer """ if len(p) == 2: p[0] = p[1] else: p[0] = ('=', p[1], p[3]) def p_initializer(self, p): """ initializer : assignment_expression | LBRACE initializer_list RBRACE | LBRACE initializer_list COMMA RBRACE """ if len(p) == 2: p[0] = p[1] else: p[0] = p[2] def p_initializer_list(self, p): """ initializer_list : initializer | initializer_list COMMA initializer """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[3]] def p_statement_list(self, p): """ statement_list : statement | statement_list statement """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_statement_list_opt(self, p): """ statement_list_opt : statement_list | empty """ def p_compound_statement(self, p): """ compound_statement : LBRACE declaration_list_opt statement_list_opt RBRACE """ p[0] = (p[2], p[3]) def p_statement(self, p): """ statement : expression_statement | compound_statement | selection_statement | iteration_statement | jump_statement | assert_statement | print_statement | read_statement """ p[0] = p[1] def p_expression_opt(self, p): """ expression_opt : expression | empty """ def p_expression_statement(self, p): """ expression_statement : expression_opt SEMI """ p[0] = p[1] def p_selection_statement(self, p): """ selection_statement : IF LPAREN expression RPAREN statement else_opt """ p[0] = ('if', p[3], p[5], p[6]) def p_else_opt(self, p): """ else_opt : empty | ELSE statement """ if len(p) == 3: p[0] = ('else', p[2]) else: p[0] = p[1] def p_iteration_statement(self, p): """ iteration_statement : WHILE LPAREN expression RPAREN statement | FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement """ if len(p) == 6: # while p[0] = (p[1], p[3], p[5]) else: # for p[0] = (p[1], p[3], p[5], p[7], p[9]) def p_jump_statement(self, p): """ jump_statement : BREAK SEMI | RETURN expression_opt SEMI """ if len(p) == 3: p[0] = p[1] else: p[0] = (p[1], p[2]) def p_assert_statement(self, p): """ assert_statement : ASSERT expression SEMI """ p[0] = ('assert', p[2]) def p_expression_list(self, p): """ expression_list : expression | expression_list expression """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_print_statement(self, p): """ print_statement : PRINT LPAREN expression_list RPAREN SEMI | PRINT LPAREN RPAREN SEMI """ if len(p) == 6: p[0] = (p[1], p[3]) else: p[0] = p[1] def p_declarator_list(self, p): """ declarator_list : declarator | declarator_list declarator """ if len(p) == 2: p[0] = [p[1]] else: p[0] = p[1] + [p[2]] def p_read_statement(self, p): """ read_statement : READ LPAREN declarator_list RPAREN SEMI """ p[0] = (p[1], p[3]) def p_empty(self, p): """empty : """ p[0] = None def p_error(self, p): if p: print("Error near the symbol %s at line %d" % (p.value, p.lineno)) else: print("Error at the end of input") precedence = ( ('left', 'OR'), ('left', 'AND'), ('left', 'EQ', 'NE'), ('left', 'LT', 'LE', 'GT', 'GE'), ('left', 'PLUS', 'MINUS'), ('left', 'TIMES', 'DIVIDE', 'MOD'), ('left', 'ADDRESS', 'NOT'), )
class Parser(object): """FOPL formula parser""" def __init__(self): self.tokens = Lexer.tokens def p_start_1(self, p): 'start : atom' p[0] = p[1] def p_start_2(self, p): 'start : start BINARY_OP start' token = p[2] if token == ur'\u21D2': # Material Implication p[0] = Implication(p[1], p[3]) elif token == ur'\u21D4': # Material Equivalence p[0] = Equivalence(p[1], p[3]) elif token == ur'\u2227': # Conjuction p[0] = And(p[1], p[3]) else: # token == ur'\u2228' Disjunction p[0] = Or(p[1], p[3]) p[0].lhs.parent = p[0].rhs.parent = p[0] def p_start_3(self, p): 'start : start BINARY_OP LB start RB' token = p[2] if token == ur'\u21D2': # Material Implication p[0] = Implication(p[1], p[4]) elif token == ur'\u21D4': # Material Equivalence p[0] = Equivalence(p[1], p[4]) elif token == ur'\u2227': # Conjuction p[0] = And(p[1], p[4]) else: # token == ur'\u2228' Disjunction p[0] = Or(p[1], p[4]) p[0].lhs.parent = p[0].rhs.parent = p[0] def p_start_4(self, p): 'start : UNARY_OP start' p[0] = Not(p[2]) p[0].lhs.parent = p[0] def p_start_5(self, p): 'start : quantifier LB start RB' p[1].lhs = p[3] p[1].lhs.parent = p[1] p[0] = p[1] def p_term_1(self, p): 'term : VAR_OR_FUNC LB term_list RB' p[0] = Func(p[1], p[3]) p[0].lhs.parent = p[0].rhs.parent = p[0] def p_term_2(self, p): 'term : VAR_OR_FUNC' p[0] = Term(p[1]) def p_term_list_1(self, p): 'term_list : term_list term' p[0] = p[1] + [p[2]] def p_term_list_2(self, p): 'term_list : term' p[0] = [p[1]] def p_predicate(self, p): 'predicate : PREDICATE LB term_list RB' p[0] = Predicate(p[1], p[3]) # Name and terms def p_atom_1(self, p): 'atom : predicate' p[0] = p[1] # def p_atom_2(self, p): # 'atom : quantifier LB atom RB' # p[1].lhs = p[3] # p[0] = p[1] def p_quantifier_1(self, p): 'quantifier : FOR_ALL var_list' p[0] = ForAll(p[2], None) def p_quantifier_2(self, p): 'quantifier : EXISTS var_list' p[0] = Exists(p[2], None) def p_var_list_1(self, p): 'var_list : var_list VAR_OR_FUNC' p[0] = p[1] + [p[2]] def p_var_list_2(self, p): 'var_list : VAR_OR_FUNC' p[0] = [Term(p[1])] def build(self, **kwargs): self.lex = Lexer() self.lex.build() self.yacc = yacc.yacc(module=self, **kwargs) def parse(self, string): return self.yacc.parse(string, debug=0, lexer=self.lex)
p[0] = ast.Identifier(p[1]) def p_assignment(p): ''' assignment : ID ASSIGN expression ''' p[0] = ast.Assignment(ast.Identifier(p[1]), p[3]) # Error rule for syntax errors def p_error(p): print("Syntax error in input!") # Build the parser parser = yacc.yacc() lexer = Lexer() lexer.build() interpretor = interpreter.Interpreter() while True: try: s = input('calc > ') except EOFError: print() break if not s: continue result = parser.parse(s, lexer=lexer.lexer) result.accept(pretty_print.PrettyPrint()) result.accept(interpretor) print() print('=', end=' ') interpretor.print_result()
class Parser(object): """ A parser object for the sire langauge. """ def __init__(self, error, lex_optimise=True, lextab='lextab', yacc_optimise=True, parsetab='parsetab', yacc_debug=False): """ Create a new parser. """ self.error = error # Instantiate and build the lexer self.lexer = Lexer(error_func=self.lex_error) self.lexer.build( optimize=lex_optimise, lextab=lextab) self.tokens = self.lexer.tokens # Create and instantiate the parser self.parser = yacc.yacc( module=self, debug=yacc_debug, optimize=yacc_optimise) def parse(self, text, filename='', debug=0): """ Parse a file and return the AST. """ if filename: self.filename = os.path.basename(filename) else: self.filename = 'stdin' self.lexer.filename = self.filename self.lexer.reset() return self.parser.parse(text, lexer=self.lexer, debug=debug, tracking=True) def coord(self, p, index=1): """ Return a coordinate for a production. """ return Coord(file=self.filename, line=p.lineno(index), column=self.lexer.findcol(self.lexer.data(), p.lexpos(index))) def tcoord(self, t): """ Return a coordinate for a token. """ return Coord(file=self.filename, line=t.lineno, column=self.lexer.findcol(self.lexer.data(), t.lexpos)) def lex_error(self, msg, line, col): self.error.report_error(msg, Coord(line, col)) def parse_error(self, msg, coord=None, discard=True): self.error.report_error(msg, coord) # Define operator presidence precedence = ( ('nonassoc', 'LT', 'GT', 'LE', 'GE', 'EQ', 'NE'), ('left', 'LSHIFT', 'RSHIFT'), ('left', 'AND', 'OR', 'XOR'), ('left', 'PLUS', 'MINUS'), ('left', 'MULT', 'DIV', 'REM'), ('right', 'UMINUS', 'UNOT') ) start = 'program' # Program declaration ====================================== def p_program(self, p): 'program : val_defs proc_defs' p[0] = ast.Program(p[1], p[2], self.coord(p, 1)) # Program declaration error def p_program_error(self, p): 'program : error' self.parse_error('Syntax error', p, 1) p[0] = None # Value definitions ======================================== def p_val_defs_empty(self, p): 'val_defs : empty' p[0] = [] def p_val_defs(self, p): 'val_defs : val_def_seq' p[0] = p[1] # Variable declaration sequence (return a single list) def p_val_def_seq(self, p): 'val_def_seq : val_def SEQSEP' p[0] = [p[1]] # Variable declaration sequence (return a single list) def p_val_def_seq_(self, p): 'val_def_seq : val_def SEQSEP val_def_seq' p[0] = [p[1]] + p[3] if p[3] else [p[1]] # Variable declaration sequence error def p_val_def_seq_err(self, p): '''val_def_seq : error SEQSEP | error SEQSEP val_def_seq''' self.parse_error('value definitions', self.coord(p)) # Single variable declaration def p_val_def(self, p): 'val_def : VAL name IS expr' p[0] = ast.VarDecl(p[2], T_VAL_SINGLE, p[4], self.coord(p)) # Variable declarations ==================================== def p_var_decls_empty(self, p): 'var_decls : empty' p[0] = [] def p_var_decls(self, p): 'var_decls : var_decl_seq' p[0] = p[1] # Variable declaration sequence (return a single list) def p_var_decl_seq(self, p): 'var_decl_seq : var_decl SEQSEP' p[0] = [p[1]] # Variable declaration sequence (return a single list) def p_var_decl_seq_(self, p): 'var_decl_seq : var_decl SEQSEP var_decl_seq' p[0] = [p[1]] + p[3] if p[3] else [p[1]] # Variable declaration sequence error def p_var_decl_seq_err(self, p): '''var_decl_seq : error SEQSEP | error SEQSEP var_decl_seq''' self.parse_error('declarations', self.coord(p)) # Single variable declaration def p_var_decl_var(self, p): 'var_decl : VAR name' p[0] = ast.VarDecl(p[2], T_VAR_SINGLE, None, self.coord(p)) # Single channel declaration def p_var_decl_chan(self, p): 'var_decl : CHAN name' p[0] = ast.VarDecl(p[2], T_CHAN_SINGLE, None, self.coord(p)) # Single channel declaration def p_var_decl_chanend(self, p): 'var_decl : CHANEND name' p[0] = ast.VarDecl(p[2], T_CHANEND_SINGLE, None, self.coord(p)) # Single server channel declaration def p_var_decl_chanend_server(self, p): 'var_decl : CHANEND SERVER name' p[0] = ast.VarDecl(p[2], T_CHANEND_SERVER_SINGLE, None, self.coord(p)) # Single client channel declaration def p_var_decl_chanend_client(self, p): 'var_decl : CHANEND CLIENT name' p[0] = ast.VarDecl(p[2], T_CHANEND_CLIENT_SINGLE, None, self.coord(p)) # Array reference declaration def p_var_decl_array_ref(self, p): 'var_decl : VAR name LBRACKET RBRACKET' p[0] = ast.VarDecl(p[2], T_REF_ARRAY, None, self.coord(p)) # Array declaration def p_var_decl_array(self, p): 'var_decl : VAR name LBRACKET expr RBRACKET' p[0] = ast.VarDecl(p[2], T_VAR_ARRAY, p[4], self.coord(p)) # Channel array declaration def p_var_decl_chan_array(self, p): 'var_decl : CHAN name LBRACKET expr RBRACKET' p[0] = ast.VarDecl(p[2], T_CHAN_ARRAY, p[4], self.coord(p)) # Abbreviations #VAL name is name #VAR name ([])? is name #CHAN name ([])? is name #CHANEND name ([])? is name # Server declarations ====================================== def p_server_decls_empty(self, p): 'server_decls : empty' p[0] = [] def p_server_decls(self, p): 'server_decls : server_decls_seq' p[0] = p[1] def p_server_decls_seq(self, p): 'server_decls_seq : server_decl' p[0] = [p[1]] def p_server_decls_seq_(self, p): 'server_decls_seq : server_decl COMMA server_decls_seq' p[0] = [p[1]] + p[3] # Single chanend parameter def p_server_decl_chan(self, p): 'server_decl : CHAN name' p[0] = ast.Param(p[2], T_CHAN_SINGLE, None, self.coord(p)) # Array reference parameter def p_server_decl_chan_array(self, p): 'server_decl : CHAN name LBRACKET expr RBRACKET' p[0] = ast.Param(p[2], T_CHAN_ARRAY, p[4], self.coord(p)) # Procedure declarations =================================== def p_proc_defs_empty(self, p): 'proc_defs : empty' p[0] = [] def p_proc_defs(self, p): 'proc_defs : proc_def_seq' p[0] = p[1] # Procedure sequence (return a single list) def p_proc_def_seq(self, p): 'proc_def_seq : proc_def' p[0] = [p[1]] # Procedure sequence (return a single list) def p_proc_def_seq_(self, p): 'proc_def_seq : proc_def proc_def_seq' p[0] = [p[1]] + p[2] if p[2] else [p[1]] # Process prototype def p_proc_prototype_proc(self, p): 'proc_def : PROC name LPAREN formals RPAREN SEQSEP' p[0] = ast.ProcDef(p[2], T_PROC, p[4], None, None, self.coord(p)) # Function prototype def p_proc_prototype_func(self, p): 'proc_def : FUNC name LPAREN formals RPAREN SEQSEP' p[0] = ast.ProcDef(p[2], T_FUNC, p[4], None, None, self.coord(p)) # Process def p_proc_def_proc(self, p): 'proc_def : PROC name LPAREN formals RPAREN IS stmt' p[0] = ast.ProcDef(p[2], T_PROC, p[4], p[7], self.coord(p)) # Function def p_proc_def_func(self, p): 'proc_def : FUNC name LPAREN formals RPAREN IS stmt' p[0] = ast.ProcDef(p[2], T_FUNC, p[4], p[7], self.coord(p)) # Procedure errors def p_proc_def_proc_err(self, p): '''proc_def : PROC error IS stmt | PROC name LPAREN formals RPAREN IS error''' self.parse_error('process declaration', self.coord(p)) # Function errors def p_proc_def_func_err(self, p): '''proc_def : FUNC error IS stmt | FUNC name LPAREN formals RPAREN IS error''' self.parse_error('function declaration', self.coord(p)) # Formal declarations ====================================== def p_formals_empty(self, p): 'formals : empty' p[0] = [] def p_formals(self, p): 'formals : formals_seq' p[0] = p[1] # Formal parameter sequence (return a single list) def p_formals_seq(self, p): 'formals_seq : param_decl' p[0] = [p[1]] # Formal parameter sequence (return a single list) def p_formals_seq_(self, p): 'formals_seq : param_decl COMMA formals_seq' p[0] = [p[1]] + p[3] # Single value parameter def p_param_decl_val(self, p): 'param_decl : VAL name' p[0] = ast.Param(p[2], T_VAL_SINGLE, None, self.coord(p)) # Single reference parameter def p_param_decl_ref(self, p): 'param_decl : VAR name' p[0] = ast.Param(p[2], T_REF_SINGLE, None, self.coord(p)) # Single chanend parameter def p_param_decl_chanend(self, p): 'param_decl : CHANEND name' p[0] = ast.Param(p[2], T_CHANEND_SINGLE, None, self.coord(p)) # Array reference parameter def p_param_decl_chanend_array(self, p): 'param_decl : CHANEND name LBRACKET expr RBRACKET' p[0] = ast.Param(p[2], T_CHANEND_ARRAY, p[4], self.coord(p)) # Single chanend parameter def p_param_decl_chan(self, p): 'param_decl : CHAN name' p[0] = ast.Param(p[2], T_CHAN_SINGLE, None, self.coord(p)) # Array reference parameter def p_param_decl_chan_array(self, p): 'param_decl : CHAN name LBRACKET expr RBRACKET' p[0] = ast.Param(p[2], T_CHAN_ARRAY, p[4], self.coord(p)) # Array reference parameter # TODO: record where the reference is 'var' or 'val'. def p_param_decl_array_ref(self, p): '''param_decl : VAL name LBRACKET expr RBRACKET | VAR name LBRACKET expr RBRACKET''' p[0] = ast.Param(p[2], T_REF_ARRAY, p[4], self.coord(p)) # Statement blocks ========================================= # Seq block def p_stmt_seq_block(self, p): 'stmt : START var_decls stmt_seq END' p[0] = ast.StmtSeq(p[2], p[3], self.coord(p)) # Seq def p_stmt_seq(self, p): 'stmt_seq : stmt' p[0] = [p[1]] # Seq def p_stmt_seq_(self, p): 'stmt_seq : stmt SEQSEP stmt_seq' p[0] = [p[1]] + p[3] if p[3] else [p[1]] # Par block def p_stmt_par_block(self, p): 'stmt : START var_decls stmt_par END' p[0] = ast.StmtPar(p[2], p[3], False, self.coord(p)) # Par block distribute def p_stmt_par_block_distribute(self, p): 'stmt : START var_decls stmt_par END DISTRIBUTE' p[0] = ast.StmtPar(p[2], p[3], True, self.coord(p)) # Par def p_stmt_par(self, p): 'stmt_par : stmt PARSEP stmt' p[0] = [p[1]] + [p[3]] def p_stmt_par_seq(self, p): 'stmt_par : stmt PARSEP stmt_par' p[0] = [p[1]] + p[3] # Seq error def p_stmt_seq_err(self, p): 'stmt_seq : error SEQSEP stmt_seq' self.parse_error('in a sequential block', self.coord(p)) # Par error def p_stmt_par_err(self, p): 'stmt_par : error PARSEP stmt_par' self.parse_error('in a parallel block', self.coord(p)) # Statements ========================================== def p_stmt_skip(self, p): 'stmt : SKIP' p[0] = ast.StmtSkip(self.coord(p)) def p_stmt_pcall(self, p): 'stmt : name LPAREN expr_list RPAREN' p[0] = ast.StmtPcall(p[1], p[3], self.coord(p)) def p_stmt_ass(self, p): 'stmt : left ASS expr' p[0] = ast.StmtAss(p[1], p[3], self.coord(p)) def p_stmt_in(self, p): 'stmt : left INP expr' p[0] = ast.StmtIn(p[1], p[3], self.coord(p)) def p_stmt_out(self, p): 'stmt : left OUT expr' p[0] = ast.StmtOut(p[1], p[3], self.coord(p)) def p_stmt_intag(self, p): 'stmt : left INTAG expr' p[0] = ast.StmtInTag(p[1], p[3], self.coord(p)) def p_stmt_outtag(self, p): 'stmt : left OUTTAG expr' p[0] = ast.StmtOutTag(p[1], p[3], self.coord(p)) def p_stmt_alias(self, p): 'stmt : left ALIASES elem' p[0] = ast.StmtAlias(p[1], p[3], self.coord(p)) def p_stmt_connect_master(self, p): 'stmt : CONNECT left COLON expr TO SLAVE expr' p[0] = ast.StmtConnect(p[2], p[4], p[7], CONNECT_MASTER, self.coord(p)) def p_stmt_connect_slave(self, p): 'stmt : CONNECT left COLON expr TO MASTER expr' p[0] = ast.StmtConnect(p[2], p[4], p[7], CONNECT_SLAVE, self.coord(p)) def p_stmt_connect_client(self, p): 'stmt : CONNECT left COLON expr TO SERVER expr' p[0] = ast.StmtConnect(p[2], p[4], p[7], CONNECT_CLIENT, self.coord(p)) def p_stmt_connect_server(self, p): 'stmt : CONNECT left COLON expr TO CLIENT' p[0] = ast.StmtConnect(p[2], p[4], None, CONNECT_SERVER, self.coord(p)) def p_stmt_server(self, p): 'stmt : SERVER LPAREN server_decls RPAREN stmt stmt' p[0] = ast.StmtServer(p[3], p[5], p[6], False, self.coord(p)) def p_stmt_server_distribute(self, p): 'stmt : SERVER DISTRIBUTE LPAREN server_decls RPAREN stmt stmt' p[0] = ast.StmtServer(p[4], p[6], p[7], True, self.coord(p)) def p_stmt_if(self, p): 'stmt : IF expr THEN stmt ELSE stmt' p[0] = ast.StmtIf(p[2], p[4], p[6], self.coord(p)) def p_stmt_while(self, p): 'stmt : WHILE expr DO stmt' p[0] = ast.StmtWhile(p[2], p[4], self.coord(p)) # for <index-range> do ... def p_stmt_for(self, p): 'stmt : FOR elem DO stmt' p[0] = ast.StmtFor(p[2], p[4], self.coord(p)) # par <index_range, >+ do ... def p_stmt_rep(self, p): 'stmt : PAR index_list DO stmt' p[0] = ast.StmtRep(p[2], p[4], self.coord(p)) def p_rep_indices(self, p): 'index_list : elem' p[0] = [p[1]] def p_rep_indices_(self, p): 'index_list : elem COMMA index_list' p[0] = [p[1]] + p[3] def p_stmt_on(self, p): 'stmt : ON expr DO stmt' p[0] = ast.StmtOn(p[2], p[4], self.coord(p)) def p_stmt_assert(self, p): 'stmt : ASSERT expr' p[0] = ast.StmtAssert(p[2], self.coord(p)) def p_stmt_return(self, p): 'stmt : RETURN expr' p[0] = ast.StmtReturn(p[2], self.coord(p)) # Expressions ============================================== def p_expr_list_empty(self, p): 'expr_list : empty' p[0] = [] def p_expr_list(self, p): 'expr_list : expr_seq' p[0] = p[1] def p_expr_seq(self, p): '''expr_seq : expr | expr COMMA expr_seq''' p[0] = [p[1]] if len(p)==2 else [p[1]] + p[3] def p_expr_single(self, p): 'expr : elem' p[0] = ast.ExprSingle(p[1]) def p_expr_unary(self, p): '''expr : MINUS elem %prec UMINUS | NOT elem %prec UNOT''' p[0] = ast.ExprUnary(p[1], p[2] if len(p)>2 else None, self.coord(p)) def p_expr_binary_arithmetic(self, p): '''expr : elem PLUS right | elem MINUS right | elem MULT right | elem DIV right | elem REM right | elem OR right | elem AND right | elem XOR right | elem LSHIFT right | elem RSHIFT right''' p[0] = ast.ExprBinop(p[2], p[1], p[3], self.coord(p)) def p_expr_binary_relational(self, p): '''expr : elem LT right | elem GT right | elem LE right | elem GE right | elem EQ right | elem NE right''' p[0] = ast.ExprBinop(p[2], p[1], p[3], self.coord(p)) def p_right_single(self, p): 'right : elem' p[0] = ast.ExprSingle(p[1]) # Associative def p_right(self, p): '''right : elem AND right | elem OR right | elem XOR right | elem PLUS right | elem MINUS right | elem REM right | elem DIV right | elem MULT right''' p[0] = ast.ExprBinop(p[2], p[1], p[3], self.coord(p)) # Elements ================================================= def p_elem_group(self, p): 'elem : LPAREN expr RPAREN' p[0] = ast.ElemGroup(p[2], self.coord(p)) def p_left_name(self, p): 'left : name' p[0] = ast.ElemId(p[1], self.coord(p)) def p_left_sub(self, p): 'left : name LBRACKET expr RBRACKET' p[0] = ast.ElemSub(p[1], p[3], self.coord(p)) def p_elem_name(self, p): 'elem : name' p[0] = ast.ElemId(p[1], self.coord(p)) def p_elem_sub(self, p): 'elem : name LBRACKET expr RBRACKET' p[0] = ast.ElemSub(p[1], p[3], self.coord(p)) # Slice: '<name>[<base> for <limit>]' def p_elem_slice(self, p): 'elem : name LBRACKET expr FOR expr RBRACKET' p[0] = ast.ElemSlice(p[1], p[3], p[5], self.coord(p)) # Index: '<index> in [<init> for <bound>]' def p_elem_index_range(self, p): 'elem : name IN LBRACKET expr FOR expr RBRACKET' p[0] = ast.ElemIndexRange(p[1], p[4], p[6], self.coord(p)) def p_elem_fcall(self, p): 'elem : name LPAREN expr_list RPAREN' p[0] = ast.ElemFcall(p[1], p[3], self.coord(p)) def p_elem_number(self, p): '''elem : HEXLITERAL | DECLITERAL | BINLITERAL''' p[0] = ast.ElemNumber(p[1], self.coord(p)) def p_elem_boolean_true(self, p): 'elem : TRUE' p[0] = ast.ElemBoolean(p[1], self.coord(p)) def p_elem_boolean_false(self, p): 'elem : FALSE' p[0] = ast.ElemBoolean(p[1], self.coord(p)) def p_elem_string(self, p): 'elem : STRING' p[0] = ast.ElemString(p[1], self.coord(p)) def p_elem_char(self, p): 'elem : CHAR' p[0] = ast.ElemChar(p[1], self.coord(p)) # Identifier ========================================== def p_name(self, p): 'name : ID' p[0] = p[1] # Empty rule def p_empty(self, p): 'empty :' pass # Error rule for syntax errors def p_error(self, t): if t: self.parse_error('before: {}'.format(t.value), self.tcoord(t)) else: #self.parse_error('at end of input', discard=False) pass
class Parser(): def __init__(self): self.lexer = Lexer() self.lexer.build() self.tokens = self.lexer.tokens self.parser = ply.yacc.yacc(module=self, start='file') def parse(self, text): return self.parser.parse(text, lexer=self.lexer) precedence = ( ('left', 'OR'), ('left', 'XOR'), ('left', 'AND'), ('left', 'RSHIFT', 'LSHIFT'), ('left', 'PLUS', 'MINUS'), ('left', 'TIMES', 'DIVIDE', 'MOD') ) def p_file(self, p): """ file : namespace_decl_list | """ if len(p) == 2: p[0] = File(p[1]) else: p[0] = File([]) def p_namespace_decl_list(self, p): """ namespace_decl_list : namespace_decl | namespace_decl namespace_decl_list """ if len(p) == 2: p[0] = [p[1]] else: p[2].append(p[1]) p[0] = p[2] def p_namespace_decl(self, p): """ namespace_decl : NAMESPACE scope_decl LBRACE toplevel_decl_list RBRACE """ p[0] = Namespace(p[2], p[4]) def p_toplevel_decl_list(self, p): """ toplevel_decl_list : toplevel_decl toplevel_decl_list | empty """ if len(p) == 3: p[2].append(p[1]) p[0] = p[2] else: p[0] = [] def p_toplevel_decl(self, p): """ toplevel_decl : namespace_decl | type_decl """ p[0] = p[1] def p_scope_decl(self, p): """ scope_decl : ID | scope_decl PERIOD ID """ if len(p) == 2: p[0] = [p[1]] else: p[1].append(p[3]) p[0] = p[1] def p_type_decl(self, p): """ type_decl : struct_decl | enum_decl | flags_decl """ p[0] = p[1] def p_declaration_list(self, p): """ declaration_list : declaration declaration_list | empty """ if len(p) == 3: p[2].append(p[1]) p[0] = p[2] else: p[0] = [] def p_declaration(self, p): """ declaration : type_decl | member_decl | const_decl """ p[0] = p[1] def p_struct_decl(self, p): """ struct_decl : STRUCT ID LBRACE declaration_list RBRACE | STRUCT ID COLON ID LBRACE declaration_list RBRACE """ if len(p) == 6: p[0] = Struct(p[2], None, p[4]) else: p[0] = Struct(p[2], p[4], p[6]) def p_enum_decl(self, p): """ enum_decl : ENUM ID LBRACE enum_list RBRACE """ p[0] = Enum(p[2], p[4]) def p_enum_list(self, p): """ enum_list : enumerator | enum_list COMMA | enum_list COMMA enumerator | """ if len(p) == 2: p[0] = [[p[1]]] elif len(p) == 3: p[0] = p[1] elif len(p) == 4: p[1].append(p[3]) p[0] = p[1] else: p[0] = [] def p_enumerator(self, p): """ enumerator : ID | ID EQUALS const_expression """ if len(p) == 2: p[0] = Enumerator(p[1], None) else: p[0] = Enumerator(p[1], p[3]) def p_flags_decl(self, p): """ flags_decl : FLAGS ID LBRACE RBRACE """ pass def p_member_decl(self, p): """ member_decl : type ID SEMI | type ID EQUALS const_expression SEMI """ p[0] = Member(p[2], p[1], p[4] if len(p) > 4 else None, False) def p_const_decl(self, p): """ const_decl : CONST type ID EQUALS const_expression SEMI """ p[0] = Member(p[3], p[2], p[5], True) def p_type_val(self, p): """ type_val : ID | F32 | F64 | U8 | U16 | U32 | U64 | S8 | S16 | S32 | S64 | BOOL | STRING | STRINGID """ p[0] = p[1] def p_type(self, p): """ type : type_val | type_val TIMES """ p[0] = Type(p[1], len(p) == 3) def p_const_numeric_1(self, p): """ const_numeric : CONST_INT_DEC | CONST_INT_OCT | CONST_INT_HEX | CONST_INT_BIN | CONST_FLOAT | CONST_CHAR """ pass def p_const_val(self, p): """ const_val : const_numeric | CONST_STRING | ID """ pass def p_const_expression(self, p): """ const_expression : const_val | LPAREN const_expression RPAREN | const_expression TIMES const_expression | const_expression DIVIDE const_expression | const_expression MOD const_expression | const_expression PLUS const_expression | const_expression MINUS const_expression | const_expression RSHIFT const_expression | const_expression LSHIFT const_expression | const_expression AND const_expression | const_expression OR const_expression | const_expression XOR const_expression """ pass def p_empty(self, p): """ empty : """ pass