예제 #1
0
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()
예제 #2
0
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()
    '''
예제 #3
0
	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		
예제 #4
0
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()
예제 #5
0
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()
예제 #6
0
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())
예제 #7
0
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)
예제 #8
0
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()
예제 #9
0
  }
}
 '''
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))
예제 #10
0
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)
예제 #11
0
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")
예제 #12
0
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'),
    )
예제 #13
0
def parse(source, debug=True):
    lexer = Lexer()
    lexer.build()
    yacc.yacc(debug=debug)
    return yacc.parse(source, lexer=lexer.lexer)
예제 #14
0
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
예제 #15
0
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'),
    )
예제 #16
0
파일: parser.py 프로젝트: ah450/unification
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)
예제 #17
0
파일: parser.py 프로젝트: porigonop/code_v2
    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()
예제 #18
0
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
예제 #19
0
def parse(source, debug=True):
    lexer = Lexer()
    lexer.build()
    yacc.yacc(debug=debug)
    return yacc.parse(source, lexer=lexer.lexer)
예제 #20
0
파일: parsing.py 프로젝트: devknoll/ddl
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