OpenCores
URL https://opencores.org/ocsvn/tcp_socket/tcp_socket/trunk

Subversion Repositories tcp_socket

[/] [tcp_socket/] [trunk/] [chips2/] [chips/] [compiler/] [parser.py,cover] - Rev 2

Go to most recent revision | Compare with Previous | Blame | View Log

> __author__ = "Jon Dawson"
> __copyright__ = "Copyright (C) 2012, Jonathan P Dawson"
> __version__ = "0.1"
  
> from parse_tree import *
> from tokens import Tokens
> from allocator import Allocator
  
> def optimise_if(if_statement):
>     try:
>         if value(if_statement.expression):
>             return if_statement.true_statement
>         elif if_statement.false_statement:
>             return if_statement.false_statement
>         else:
>             null_instruction = Block()
>             null_instruction.statements = []
>             return null_instruction
>     except NotConstant:
>         return if_statement
  
> class Parser:
  
>     """Turn the C input file into a tree of expressions and statements."""
  
>     def __init__(self, input_file, reuse):
>         self.scope = {}
>         self.function = None
>         self.loop = None
>         self.tokens = Tokens(input_file)
>         self.allocator = Allocator(reuse)
>         self.structs = []
  
>     def parse_process(self):
>         process = Process()
>         process.allocator = self.allocator
>         process.inputs = []
>         process.outputs = []
>         process.functions = []
>         while not self.tokens.end():
>             if self.tokens.peek() == "struct":
>                 self.parse_define_struct()
>             elif self.tokens.peek() == "typedef":
>                 self.parse_typedef_struct()
>             else:
>                 process.functions.append(self.parse_function())
>         process.main = self.main
>         return process
  
>     def parse_function(self):
>         function = Function()
>         function.allocator = self.allocator
>         stored_scope = self.scope
>         type_ = self.tokens.get()
>         name = self.tokens.get()
          
          #check if it is a global declaration
>         if self.tokens.peek() != "(":
>             if type_ not in ["int", "short", "long", "char"] + self.structs:
!                 self.tokens.error("unknown type")
>             return self.parse_global_declaration(type_, name)
  
          #otherwise continue parsing a function
>         self.tokens.expect("(")
>         function.name = name
>         function.type_ = type_
>         function.return_address = self.allocator.new(function.name+" return address")
>         if type_ not in ["int", "short", "long", "char", "void"]:
!             self.tokens.error("unknown type")
>         if type_ != "void":
>             function.return_value = self.allocator.new(function.name+" return value")
>         function.arguments = []
>         while self.tokens.peek() != ")":
>             type_ = self.tokens.get()
>             if type_ not in ["int", "short", "long", "char"]:
!                 self.tokens.error("unknown type")
>             argument = self.tokens.get()
>             if self.tokens.peek() == "[":
>                 self.tokens.expect("[")
>                 self.tokens.expect("]")
>                 type_+="[]"
>             function.arguments.append(Argument(argument, type_, self))
>             if self.tokens.peek() == ",":
>                 self.tokens.expect(",")
>             else:
>                 break
>         self.tokens.expect(")")
>         self.function = function
>         function.statement = self.parse_statement()
>         if type_ != "void" and not hasattr(function, "return_statement"):
>             self.tokens.error("Function must have a return statement")
>         self.function = None
>         self.scope = stored_scope
>         self.scope[function.name] = function
          #main thread is last function
>         self.main = function
>         return function
  
>     def parse_break(self):
>         break_ = Break()
>         break_.loop = self.loop
>         self.tokens.expect("break")
>         self.tokens.expect(";")
>         return break_
  
>     def parse_continue(self):
>         continue_ = Continue()
>         continue_.loop = self.loop
>         self.tokens.expect("continue")
>         self.tokens.expect(";")
>         return continue_
  
>     def parse_return(self):
>         return_ = Return()
>         return_.function = self.function
>         self.function.return_statement = return_
>         self.tokens.expect("return")
>         if hasattr(self.function, "return_value"):
>             return_.expression = self.parse_expression()
>         self.tokens.expect(";")
>         return return_
  
>     def parse_assert(self):
>         assert_ = Assert()
>         assert_.allocator = self.allocator
>         self.tokens.expect("assert")
>         self.tokens.expect("(")
>         assert_.expression = self.parse_expression()
>         self.tokens.expect(")")
>         self.tokens.expect(";")
>         assert_.line = self.tokens.lineno
>         assert_.filename = self.tokens.filename
>         return assert_
  
>     def parse_report(self):
>         report_ = Report()
>         report_.allocator = self.allocator
>         self.tokens.expect("report")
>         self.tokens.expect("(")
>         report_.expression = self.parse_expression()
>         self.tokens.expect(")")
>         self.tokens.expect(";")
>         report_.line = self.tokens.lineno
>         report_.filename = self.tokens.filename
>         return report_
  
>     def parse_wait_clocks(self):
>         wait_clocks = WaitClocks()
>         wait_clocks.allocator = self.allocator
>         self.tokens.expect("wait_clocks")
>         self.tokens.expect("(")
>         wait_clocks.expression = self.parse_expression()
>         self.tokens.expect(")")
>         self.tokens.expect(";")
>         wait_clocks.line = self.tokens.lineno
>         return wait_clocks
  
>     def parse_statement(self):
>         if self.tokens.peek() in ["int", "short", "long", "char"] + self.structs:
>             return self.parse_compound_declaration()
>         elif self.tokens.peek() == "struct":
>             return self.parse_struct_declaration()
>         elif self.tokens.peek() == "if":
>             return self.parse_if()
>         elif self.tokens.peek() == "while":
>             return self.parse_while()
>         elif self.tokens.peek() == "for":
>             return self.parse_for()
>         elif self.tokens.peek() == "return":
>             return self.parse_return()
>         elif self.tokens.peek() == "break":
>             return self.parse_break()
>         elif self.tokens.peek() == "continue":
>             return self.parse_continue()
>         elif self.tokens.peek() == "{":
>             return self.parse_block()
>         elif self.tokens.peek() == "assert":
>             return self.parse_assert()
>         elif self.tokens.peek() == "report":
>             return self.parse_report()
>         elif self.tokens.peek() == "switch":
>             return self.parse_switch()
>         elif self.tokens.peek() == "case":
>             return self.parse_case()
>         elif self.tokens.peek() == "default":
>             return self.parse_default()
>         elif self.tokens.peek() == "wait_clocks":
>             return self.parse_wait_clocks()
>         else:
>             expression = self.parse_discard()
>             self.tokens.expect(";")
>             return expression
  
>     def parse_discard(self):
>         return DiscardExpression(self.parse_expression(), self.allocator)
  
>     def parse_assignment(self):
>         assignment_operators = [
>             "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=", 
>             "++", "--"
>         ]
>         lvalue = self.parse_ternary_expression()
>         if self.tokens.peek() in assignment_operators:
>             if not hasattr(lvalue, "declaration"):
>                 self.tokens.error(
>                     "left hand operand of assignment is not modifiable"
>                 )
>             operator = self.tokens.get()
>             if operator == "=":
>                 expression = self.parse_ternary_expression()
>             elif operator in ["++", "--"]:
>                 expression = Binary(
>                     operator[:-1],
>                     lvalue, 
>                     Constant(1), 
>                     self.allocator
>                 )
>             else:
>                 expression = Binary(
>                     operator[:-1], 
>                     lvalue, 
>                     self.parse_ternary_expression(), 
>                     self.allocator
>                 )
>             if lvalue.type_ != expression.type_:
>                 self.tokens.error(
>                     "type mismatch in assignment"
>                 )
>             return Assignment(lvalue, expression, self.allocator)
>         else:
>             return lvalue
  
  
>     def parse_if(self):
>         if_ = If()
>         if_.allocator = self.allocator
>         self.tokens.expect("if")
>         self.tokens.expect("(")
>         if_.expression = self.parse_expression()
>         if if_.expression.type_ not in ["int", "short", "long", "char"]:
>             self.tokens.error(
>                 "if statement conditional must be an integer like expression"
>             )
>         self.tokens.expect(")")
>         if_.true_statement = self.parse_statement()
>         if self.tokens.peek() == "else":
>             self.tokens.expect("else")
>             if_.false_statement = self.parse_statement()
>         else:
>             if_.false_statement = None
>         return optimise_if(if_)
  
>     def parse_switch(self):
>         switch = Switch()
>         switch.cases = {}
>         self.tokens.expect("switch")
>         self.tokens.expect("(")
>         expression = self.parse_expression()
>         if expression.type_ not in ["int", "short", "long", "char"]:
>             self.tokens.error(
>                 "switch statement expression must be an integer like expression"
>             )
>         self.tokens.expect(")")
>         stored_loop = self.loop
>         self.loop = switch
>         statement = self.parse_statement()
>         self.loop = stored_loop
>         switch.expression = expression
>         switch.allocator = self.allocator
>         switch.statement = statement
>         return switch
  
>     def parse_case(self):
>         self.tokens.expect("case")
>         expression = self.parse_expression()
>         if expression.type_ not in ["int", "short", "long", "char"]:
>             self.tokens.error(
>                 "case expression must be an integer like expression"
>             )
>         self.tokens.expect(":")
>         try:
>             expression = value(expression)
>             case = Case()
>             self.loop.cases[expression] =    case
>         except NotConstant:
>             self.tokens.error("case expression must be constant")
>         except AttributeError:
>             self.tokens.error(
>                 "case statements may only be use inside a switch statment"
>             )
>         return case
  
>     def parse_default(self):
>         self.tokens.expect("default")
>         self.tokens.expect(":")
>         default = Default()
>         if not hasattr(self.loop, "cases"):
>             self.tokens.error(
>                 "default statements may only be used inside a switch statment"
>             )
>         if hasattr(self.loop, "default"):
>             self.tokens.error(
>                 "A switch statement may only have one default statement"
>             )
>         self.loop.default=default
>         return default
  
>     def parse_while(self):
>         loop = Loop()
>         self.tokens.expect("while")
>         self.tokens.expect("(")
>         expression = self.parse_expression()
>         self.tokens.expect(")")
>         stored_loop = self.loop
>         self.loop = loop
>         statement = self.parse_statement()
>         self.loop = stored_loop
  
>         if_ = If()
>         break_ = Break()
>         break_.loop = loop
>         if_.allocator = self.allocator
>         if expression.type_ not in ["int", "short", "long", "char"]:
>             self.tokens.error(
>                 "if statement conditional must be an integer like expression"
>             )
>         if_.expression = expression
>         if_.false_statement = break_
>         if_.true_statement = statement
  
>         loop.statement = optimise_if(if_)
>         return loop
  
>     def parse_for(self):
>         for_ = For()
>         for_.allocator = self.allocator
>         self.tokens.expect("for")
>         self.tokens.expect("(")
>         if self.tokens.peek() != ";":
>             for_.statement1 = self.parse_discard()
>         self.tokens.expect(";")
>         if self.tokens.peek() != ";":
>             for_.expression = self.parse_expression()
>             if for_.expression.type_ not in ["int", "short", "long", "char"]:
>                 self.tokens.error(
>                     "for statement conditional must be an integer like expression"
>                 )
>         self.tokens.expect(";")
>         if self.tokens.peek() != ")":
>             for_.statement2 = self.parse_discard()
>         self.tokens.expect(")")
>         stored_loop = self.loop
>         self.loop = for_
>         for_.statement3 = self.parse_statement()
>         self.loop = stored_loop
>         return for_
  
>     def parse_block(self):
>         block = Block()
>         stored_scope = self.scope
>         self.tokens.expect("{")
>         block.statements = []
>         while self.tokens.peek() != "}":
>             block.statements.append(self.parse_statement())
>         self.tokens.expect("}")
>         self.scope = stored_scope
>         return block
  
>     def parse_struct_body(self):
>         self.tokens.expect("{")
>         members = {}
>         while self.tokens.peek() != "}":
>             type_ = self.tokens.get()
>             name = self.tokens.get()
>             members[name] = self.parse_declaration(type_, name)
>             self.tokens.expect(";")
>         self.tokens.expect("}")
>         return members
  
>     def parse_typedef_struct(self):
>         self.tokens.expect("typedef")
>         self.tokens.expect("struct")
>         declaration = StructDeclaration(self.parse_struct_body())
>         name = self.tokens.get()
>         self.tokens.expect(";")
>         self.scope[name] = declaration
>         self.structs.append(name)
  
>     def parse_define_struct(self):
>         self.tokens.expect("struct")
>         name = self.tokens.get()
>         declaration = StructDeclaration(self.parse_struct_body())
>         self.tokens.expect(";")
>         self.scope[name] = declaration
  
>     def parse_struct_declaration(self):
>         self.tokens.expect("struct")
>         struct_name = self.tokens.get()
>         name = self.tokens.get()
>         self.tokens.expect(";")
>         instance = self.scope[struct_name].instance()
>         self.scope[name] = instance
>         return instance
  
>     def parse_global_declaration(self, type_, name):
>         instances = []
>         while True:
>             instance = self.parse_declaration(type_, name).instance()
>             self.scope[name] = instance
>             instances.append(instance)
>             if self.tokens.peek() == ",":
>                 self.tokens.expect(",")
>             else:
>                 break
>             name = self.tokens.get()
>         self.tokens.expect(";")
>         return CompoundDeclaration(instances)
  
>     def parse_compound_declaration(self):
>         type_ = self.tokens.get()
>         instances = []
>         while True:
>             name = self.tokens.get()
>             instance = self.parse_declaration(type_, name).instance()
>             self.scope[name] = instance
>             instances.append(instance)
>             if self.tokens.peek() == ",":
>                 self.tokens.expect(",")
>             else:
>                 break
>             name = None
>         self.tokens.expect(";")
>         return CompoundDeclaration(instances)
  
>     def parse_declaration(self, type_, name):
          #struct declaration
>         if type_ in self.structs:
>             declaration = self.scope[type_]
>         elif type_ in ["int", "short", "long", "char"]:
              #array declaration 
>             if self.tokens.peek() == "[":
>                 size = None
>                 self.tokens.expect("[")
>                 if self.tokens.peek() != "]":
>                     size = self.tokens.get()
>                 self.tokens.expect("]")
>                 initializer = None
>                 if self.tokens.peek() == "=":
>                     self.tokens.expect("=")
>                     initializer = self.tokens.get()
>                     initializer = [ord(i) for i in initializer.strip('"')] + [0]
>                     size = len(initializer)
>                 if size is None:
>                     self.tokens.error("array size must be specified if not initialized")
>                 type_+="[]"
>                 declaration = ArrayDeclaration(self.allocator, size, type_, initializer)
  
              #simple variable declaration 
>             else:
>                 if self.tokens.peek() == "=":
>                     self.tokens.expect("=")
>                     initializer = self.parse_ternary_expression()
>                 else:
>                     initializer = Constant(0)
>                 declaration = VariableDeclaration(
>                     self.allocator, 
>                     initializer, 
>                     name,
>                     type_
>                 )
  
>         return declaration
  
>     def parse_expression(self):
>         expression = self.parse_assignment()
>         return expression
  
>     def parse_ternary_expression(self):
>         expression = constant_fold(self.parse_or_expression())
>         while self.tokens.peek() in ["?"]:
>             self.tokens.expect("?")
>             true_expression = constant_fold(self.parse_or_expression())
>             self.tokens.expect(":")
>             false_expression = constant_fold(self.parse_or_expression())
>             expression = OR(AND(expression, true_expression), false_expression)
>         return expression
  
>     def parse_or_expression(self):
>         expression = self.parse_and_expression()
>         while self.tokens.peek() in ["||"]:
>             self.tokens.expect("||")
>             expression = OR(expression, self.parse_and_expression())
>         return expression
  
>     def parse_and_expression(self):
>         expression = self.parse_binary_expression(["|"])
>         while self.tokens.peek() in ["&&"]:
>             self.tokens.expect("&&")
>             expression = AND(expression, self.parse_binary_expression(["|"]))
>         return expression
  
>     def parse_binary_expression(self, operators):
>         operator_precedence = {
>                 "|": ["^"],
>                 "^": ["&"],
>                 "&": ["==", "!="],
>                 "==": ["<", ">", "<=", ">="],
>                 "<": ["<<", ">>"],
>                 "<<": ["+", "-"],
>                 "+": ["*", "/", "%"],
>         }
>         if operators[0] not in operator_precedence:
>             expression = self.parse_unary_expression()
>             while self.tokens.peek() in operators:
>                 expression = Binary(
>                     self.tokens.get(), 
>                     expression, 
>                     self.parse_unary_expression(), 
>                     self.allocator
>                 )
>             return expression
>         else:
>             next_operators = operator_precedence[operators[0]]
>             expression = self.parse_binary_expression(next_operators)
>             while self.tokens.peek() in operators:
>                 expression = Binary(
>                     self.tokens.get(), 
>                     expression, 
>                     self.parse_binary_expression(next_operators), 
>                     self.allocator
>                 )
>             return expression
  
>     def parse_unary_expression(self):
>         if self.tokens.peek() == "!":
>             operator = self.tokens.get()
>             expression = self.parse_paren_expression()
>             return Binary("==", expression, Constant(0), self.allocator)
>         elif self.tokens.peek() == "-":
>             operator = self.tokens.get()
>             expression = self.parse_paren_expression()
>             return Binary("-", Constant(0), expression, self.allocator)
>         elif self.tokens.peek() == "~":
>             operator = self.tokens.get()
>             expression = self.parse_paren_expression()
>             return Unary("~", expression)
>         else:
>             return self.parse_paren_expression()
  
>     def parse_paren_expression(self):
>         if self.tokens.peek() == "(":
>             self.tokens.expect("(")
>             expression = self.parse_expression()
>             self.tokens.expect(")")
>         else:
>             expression = self.parse_number_or_variable()
>         return expression
  
>     def parse_number_or_variable(self):
>         if self.tokens.peek()[0].isalpha():
>             name = self.tokens.get()
>             if self.tokens.peek() == "(":
>                 return self.parse_function_call(name)
>             else:
>                 return self.parse_variable(name)
>         else:
>             return self.parse_number()
  
>     def parse_input(self, name):
>         input_name = name.replace("input_", "")
>         self.tokens.expect("(")
>         self.tokens.expect(")")
>         return Input(input_name)
  
>     def parse_ready(self, name):
>         input_name = name.replace("ready_", "")
>         self.tokens.expect("(")
>         self.tokens.expect(")")
>         return Ready(input_name)
  
>     def parse_output(self, name):
>         output_name = name.replace("output_", "")
>         self.tokens.expect("(")
>         expression = self.parse_expression()
>         self.tokens.expect(")")
>         return Output(output_name, expression)
  
>     def parse_function_call(self, name):
>         if name.startswith("input_"):
>             return self.parse_input(name)
>         if name.startswith("ready_"):
>             return self.parse_ready(name)
>         if name.startswith("output_"):
>             return self.parse_output(name)
>         function_call = FunctionCall()
>         function_call.arguments = []
>         self.tokens.expect("(")
>         while self.tokens.peek() != ")":
>             function_call.arguments.append(self.parse_expression())
>             if self.tokens.peek() == ",":
>                 self.tokens.expect(",")
>             else:
>                 break
>         self.tokens.expect(")")
  
>         if name not in self.scope:
>             self.tokens.error("Unknown function: %s"%name)
  
>         function_call.function = self.scope[name]
>         function_call.type_ = function_call.function.type_
>         required_arguments = len(function_call.function.arguments)
>         actual_arguments = len(function_call.arguments)
>         if required_arguments != actual_arguments:
>             self.tokens.error("Function %s takes %s arguments %s given."%(
>                 name,
>                 len(function_call.function.arguments),
>                 len(function_call.arguments)
>             ))
>         required_arguments = function_call.function.arguments
>         actual_arguments = function_call.arguments
>         for required, actual in zip(required_arguments, actual_arguments):
>             if required.type_ != actual.type_:
>                 self.tokens.error("Type mismatch expected type : %s got: %s."%(
>                     required.type_,
>                     actual.type_
>                 ))
  
  
>         return function_call
  
>     def parse_number(self):
>         token = self.tokens.get()
>         if token.startswith("'"):
>             try:
>                 token = eval(token)
>                 value = ord(token)
!             except SyntaxError:
!                 self.tokens.error("%s is not a character literal"%token)
>         else:
>             try:
>                 value = int(eval(token))
>             except SyntaxError:
>                 self.tokens.error("%s is not an integer literal"%token)
>         return Constant(value)
  
>     def parse_variable(self, name):
>         if name not in self.scope:
>             self.tokens.error("Unknown variable: %s"%name)
>         instance = self.scope[name]
>         return self.parse_variable_array_struct(instance)
   
>     def parse_variable_array_struct(self, instance):
>         if instance.type_ in ["int", "short", "long", "char"]:
>             return Variable(instance, self.allocator)
>         elif instance.type_.endswith("[]"):
>             if self.tokens.peek() == "[":
>                 self.tokens.expect("[")
>                 index_expression = self.parse_expression()
>                 self.tokens.expect("]")
>                 if index_expression.type_ not in ["int", "short", "long", "char"]:
>                     self.tokens.error(
>                         "array indices must be an integer like expression"
>                     )
>                 return ArrayIndex(instance, index_expression, self.allocator)
>             else:
>                 return Array(instance, self.allocator)
>         elif instance.type_ == "struct":
>             self.tokens.expect(".")
>             member = self.tokens.get()
>             instance = instance.members[member]
>             return self.parse_variable_array_struct(instance)

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.