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 4

Compare with Previous | Blame | View Log

> __author__ = "Jon Dawson"
> __copyright__ = "Copyright (C) 2012, Jonathan P Dawson"
> __version__ = "0.1"
  
> import struct
> from copy import copy
  
> from parse_tree import *
> from tokens import Tokens
> from allocator import Allocator
  
> types = ["float", "signed", "unsigned", "short", "long", "char", "int", "void"]
> numeric_types = ["float", "signed", "unsigned", "short", "long", "char", "int"]
> storage_specifiers = ["const"]
  
> class Parser:
  
>     """Turn the C input file into a tree of expressions and statements."""
  
>     def __init__(self, input_file, reuse, initialize_memory):
>         self.scope = {}
>         self.function = None
>         self.loop = None
>         self.tokens = Tokens(input_file)
>         self.allocator = Allocator(reuse)
>         self.structs = []
>         self.initialize_memory = initialize_memory
  
>     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_type_specifier(self):
>         type_specifiers = []
  
>         while self.tokens.peek() in types + self.structs + storage_specifiers:
>             type_specifiers.append(self.tokens.get())
  
>         signed = True
>         if "unsigned" in type_specifiers:
>             signed = False
>             if "signed" in type_specifiers:
!                 self.tokens.error("Cannot be signed and unsigned")
  
>         size = 2
>         if "long" in type_specifiers:
>             if "short" in type_specifiers:
!                 self.tokens.error("Cannot be long and short")
>             size = 4
  
>         type_ = "int"
>         for i in type_specifiers:
>             if i in self.structs:
>                 type_ = i
>                 size = 2
>                 signed = False
  
>         if "float" in type_specifiers:
>             if "short" in type_specifiers:
!                 self.tokens.error("Float cannot be short")
>             if "long" in type_specifiers:
!                 self.tokens.error("Float cannot be long (but double can)")
>             if "unsigned" in type_specifiers:
!                 self.tokens.error("Float cannot be unsigned")
>             type_ = "float"
>             size = 4
>             signed = True
  
>         const = False 
>         if "const" in type_specifiers:
>             const = True
  
>         if "void" in type_specifiers:
>             type_ = "void"
>             size = 2
>             signed = False
  
  
>         return type_, size, signed, const
  
>     def parse_argument(self):
>         type_, size, signed, const = self.parse_type_specifier()
  
>         if type_ in ["void"]:
!             self.tokens.error("argument cannot be void")
>         else:
>             argument = self.tokens.get()
>             if type_ in self.structs:
>                 declaration = self.scope[type_]
>             else:
>                 if self.tokens.peek() == "[":
>                     self.tokens.expect("[")
>                     self.tokens.expect("]")
>                     declaration = ArrayDeclaration(
>                         self.allocator,
>                         2,
>                         type_+"[]",
>                         type_,
>                         size,
>                         signed, 
>                         None,
>                         self.initialize_memory)
>                 else:
>                     declaration = VariableDeclaration(
>                         self.allocator,
>                         None,
>                         argument,
>                         type_,
>                         size,
>                         signed,
>                         const)
>         instance = declaration.instance()
>         self.scope[argument] = instance
>         return instance.reference()
  
>     def parse_function(self):
>         function = Function()
>         function.allocator = self.allocator
>         stored_scope = copy(self.scope)
>         type_, size, signed, const = self.parse_type_specifier()
>         name = self.tokens.get()
  
          #check if it is a global declaration
>         if self.tokens.peek() != "(":
>             return self.parse_global_declaration(type_, size, signed, const, name)
  
          #otherwise continue parsing a function
>         self.tokens.expect("(")
>         function.name = name
>         function.type_ = type_
>         function.size = size
>         function.signed = signed
  
>         function.return_address = self.allocator.new(2, 
>             function.name+" return address")
  
>         if type_ != "void":
  
>             if type_ in self.structs:
!                 declaration = self.scope[type_]
>             else:
>                 if self.tokens.peek() == "[":
!                     self.tokens.error(
!                         "Functions cannot return arrays")
>                 else:
>                     declaration = VariableDeclaration(
>                         self.allocator,
>                         None,
>                         function.name+" return value",
>                         type_,
>                         size,
>                         signed,
>                         const)
  
>             function.return_value = declaration.instance().reference()
  
>         function.arguments = []
>         while self.tokens.peek() != ")":
>             function.arguments.append(self.parse_argument())
>             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
>         return_.allocator = self.allocator
>         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 numeric_types + self.structs + storage_specifiers:
>             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 lvalue.const():
  
>                 self.tokens.error(
>                     "left hand operand of assignment is not modifiable")
  
>             operator = self.tokens.get()
>             if operator == "=":
>                 expression = self.parse_ternary_expression()
>             else:
  
>                 expression = self.parse_ternary_expression()
>                 left = lvalue
>                 left, expression = self.coerce_types(left, expression)
>                 expression = Binary(operator[:-1], left, expression)
  
>             if expression.type_() != lvalue.type_():
>                 if expression.type_() == "int" and lvalue.type_() == "float":
!                     expression = IntToFloat(expression)
>                 elif expression.type_() == "float" and lvalue.type_() == "int":
>                     expression = FloatToInt(expression)
>                 else:
>                     self.tokens.error(
>                         "type mismatch in assignment expected: %s actual: %s"%(
>                             lvalue.type_(),
>                             expression.type_()))
  
>             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 ["unsigned", "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 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 ["unsigned", "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"]:
>             self.tokens.error(
>                 "case expression must be an integer like expression")
>         self.tokens.expect(":")
>         try:
>             expression = expression.value()
>             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()
>         loop.statement = if_
>         break_ = Break()
>         break_.loop = loop
>         if_.allocator = self.allocator
>         if expression.type_() not in ["int"]:
>             self.tokens.error(
>                 "while statement conditional must be an integer like expression")
>         if_.expression = expression
>         if_.false_statement = break_
>         if_.true_statement = statement
  
>         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 [
>                 "unsigned", 
>                 "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 = copy(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_, size, signed, const = self.parse_type_specifier()
>             name = self.tokens.get()
  
>             members[name] = self.parse_declaration(
>                 type_, 
>                 size, 
>                 signed, 
>                 const,
>                 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_, size, signed, const, name):
>         instances = []
>         while True:
  
>             instance = self.parse_declaration(
>                 type_, 
>                 size, 
>                 signed, 
>                 const,
>                 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_, size, signed, const = self.parse_type_specifier()
>         instances = []
>         while True:
>             name = self.tokens.get()
  
>             instance = self.parse_declaration(
>                 type_, 
>                 size, 
>                 signed, 
>                 const,
>                 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_, size, signed, const, name):
          #struct declaration
>         if type_ in self.structs:
>             declaration = self.scope[type_]
>         elif type_ in ["int", "float"]:
              #array declaration
>             if self.tokens.peek() == "[":
>                 array_size = None
>                 self.tokens.expect("[")
>                 if self.tokens.peek() != "]":
>                     size_expression = self.parse_ternary_expression()
>                     if size_expression.type_() != "int":
!                         self.tokens.error("Array size must be an integer like expression")
>                     try:
>                         array_size = size_expression.value()
>                     except NotConstant:
>                         self.tokens.error("Array size must be constant")
  
>                 self.tokens.expect("]")
>                 initializer = None
>                 if self.tokens.peek() == "=":
>                     self.tokens.expect("=")
>                     initializer = self.tokens.get()
>                     initializer = [ord(i) for i in initializer.strip('"').decode("string_escape")] + [0]
>                     array_size = len(initializer)
>                 if array_size is None:
  
>                     self.tokens.error(
>                         "array size must be specified if not initialized")
  
>                 array_type=type_+"[]"
>                 initialize_memory = self.initialize_memory
>                 declaration = ArrayDeclaration(
>                     self.allocator,
>                     array_size,
>                     array_type,
>                     type_,
>                     size,
>                     signed,
>                     initializer,
>                     self.initialize_memory)
  
              #simple variable declaration
>             else:
>                 if self.tokens.peek() == "=":
>                     self.tokens.expect("=")
>                     initializer = self.parse_ternary_expression()
>                 else:
>                     initializer = Constant(0, type_, size, signed)
  
>                 if type_ != initializer.type_():
  
>                     if type_ == "int" and initializer.type_() == "float":
>                         initializer = FloatToInt(initializer)
>                     elif type_ == "float" and initializer.type_() == "int":
>                         initializer = IntToFloat(initializer)
>                     else:
>                         self.tokens.error(
>                             "type mismatch in intializer expected: %s actual: %s"%(
>                                 type_,
>                                 intitializer.type_()))
>                 declaration = VariableDeclaration(
>                     self.allocator,
>                     initializer,
>                     name,
>                     type_,
>                     size,
>                     signed,
>                     const
>                 )
  
>         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 substitute_function(self, binary_expression):
  
>         """
>         For some operations are more easily implemented in sofftware.
>         This function substitutes a call to the builtin library function.
>         """
  
>         functions = {
>            "False,int,int,4,/" : "long_unsigned_divide_xxxx",
>            "True,int,int,4,/" : "long_divide_xxxx",
>            "False,int,int,2,/" : "unsigned_divide_xxxx",
>            "True,int,int,2,/" : "divide_xxxx",
>            "False,int,int,4,%" : "long_unsigned_modulo_xxxx",
>            "True,int,int,4,%" : "long_modulo_xxxx",
>            "False,int,int,2,%" : "unsigned_modulo_xxxx",
>            "True,int,int,2,%" : "modulo_xxxx",
>            "True,float,float,4,==" : "float_equal_xxxx",
>            "True,float,float,4,!=" : "float_ne_xxxx",
>            "True,float,float,4,<" : "float_lt_xxxx",
>            "True,float,float,4,>" : "float_gt_xxxx",
>            "True,float,float,4,<=" : "float_le_xxxx",
>            "True,float,float,4,>=" : "float_ge_xxxx",
>         }
  
          #select a function that matches the template.
>         signature = ",".join([
>             str(binary_expression.signed()), 
>             binary_expression.left.type_(), 
>             binary_expression.right.type_(), 
>             str(binary_expression.size()), 
>             binary_expression.operator])
  
          #Some things can't be implemented in verilog, substitute them with a function
>         if signature in functions:
>             function = self.scope[functions[signature]]
>             function_call = FunctionCall(function)
>             function_call.arguments = [binary_expression.left, binary_expression.right]
>             return function_call
>         else:
>             return binary_expression
  
>     def coerce_types(self, left, right):
  
>         """
>         Convert numeric types in expressions.
>         """
  
>         if left.type_() != right.type_():
>             if left.type_() == "float" and right.type_() == "int":
>                 return left, IntToFloat(right)
>             elif left.type_() == "int" and right.type_() == "float":
>                 return IntToFloat(left), right
>             else:
>                 self.tokens.error("Incompatible types : %s %s"%(
>                     left.type_(),
>                     right.type_()))
  
>         return left, right
  
>     def parse_binary_expression(self, operators):
>         operator_precedence = {
>                 "|": ["^"],
>                 "^": ["&"],
>                 "&": ["==", "!="],
>                 "==": ["<", ">", "<=", ">="],
>                 "<": ["<<", ">>"],
>                 "<<": ["+", "-"],
>                 "+": ["*", "/", "%"],
>         }
>         if operators[0] not in operator_precedence:
>             left = self.parse_unary_expression()
>             while self.tokens.peek() in operators:
>                 operator = self.tokens.get()
>                 right = self.parse_unary_expression()
>                 left, right = self.coerce_types(left, right)
>                 left = Binary(operator, left, right)
>                 left = self.substitute_function(left)
>             return left
>         else:
>             next_operators = operator_precedence[operators[0]]
>             left = self.parse_binary_expression(next_operators)
>             while self.tokens.peek() in operators:
>                 operator = self.tokens.get()
>                 right = self.parse_binary_expression(next_operators)
>                 left, right = self.coerce_types(left, right)
>                 left = Binary(operator, left, right)
>                 left = self.substitute_function(left)
>             return left
  
>     def parse_unary_expression(self):
>         if self.tokens.peek() == "!":
>             operator = self.tokens.get()
>             expression = self.parse_postfix_expression()
>             return Binary("==", expression, Constant(0))
>         elif self.tokens.peek() == "-":
>             operator = self.tokens.get()
>             expression = self.parse_postfix_expression()
>             return Binary("-", Constant(0, 
>                 expression.type_(), 
>                 expression.size(), 
>                 expression.signed()), 
>                 expression)
>         elif self.tokens.peek() == "~":
>             operator = self.tokens.get()
>             expression = self.parse_postfix_expression()
>             return Unary("~", expression)
>         elif self.tokens.peek() == "sizeof":
>             operator = self.tokens.get()
>             expression = self.parse_unary_expression()
>             return SizeOf(expression)
>         else:
>             return self.parse_postfix_expression()
  
>     def parse_postfix_expression(self):
>         expression = self.parse_paren_expression()
>         while self.tokens.peek() in ["++", "--"]:
>             operator = self.tokens.get()
>             expression = PostIncrement(
>                 operator[:-1],
>                 expression,
>                 self.allocator
>             )
>         return 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_file_read(self):
!         self.tokens.expect("(")
!         file_name = self.tokens.get()
>         file_name = file_name.strip('"').decode("string_escape")
>         self.tokens.expect(")")
!         return FileRead(file_name)
  
>     def parse_file_write(self):
>         self.tokens.expect("(")
>         expression = self.parse_expression()
>         self.tokens.expect(",")
>         file_name = self.tokens.get()
>         file_name = file_name.strip('"').decode("string_escape")
>         self.tokens.expect(")")
>         return FileWrite(file_name, expression)
  
>     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)
>         if name == "file_read":
>             return self.parse_file_read()
>         if name == "file_write":
>             return self.parse_file_write()
>         if name not in self.scope:
>             self.tokens.error("Unknown function: %s"%name)
>         function = self.scope[name]
>         function_call = FunctionCall(function)
>         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(")")
  
  
>         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
>         corrected_arguments = []
>         for required, actual in zip(required_arguments, actual_arguments):
>             if not compatible(required, actual):
>                 if actual.type_() == "int" and required.type_() == "float":
>                     actual = IntToFloat(actual)
>                 elif actual.type_() == "float" and required.type_() == "int":
!                     actual = FloatToInt(actual)
>                 else:
>                     self.tokens.error(
>                         "type mismatch in assignment expected: %s actual: %s"%(
>                             required.type_(),
>                             actual.type_()))
>             corrected_arguments.append(actual)
>         function_call.arguments = corrected_arguments
  
>         return function_call
  
>     def parse_number(self):
>         token = self.tokens.get()
>         type_ = "int"
>         size = 2
>         signed = True
>         if token.startswith("'"):
>             try:
>                 token = eval(token)
>                 value = ord(token)
!             except SyntaxError:
!                 self.tokens.error("%s is not a character literal"%token)
>         elif token.startswith('"'):
>             try:
>                 initializer = [ord(i) for i in token.strip('"').decode("string_escape")] + [0]
>                 size = len(initializer)
>                 initialize_memory = self.initialize_memory
>                 declaration = ArrayDeclaration(
>                     self.allocator,
>                     size,
>                     "int[]",
>                     "int",
>                     2,
>                     False,
>                     initializer,
>                     self.initialize_memory)
>                 return ConstArray(declaration.instance())
!             except SyntaxError:
!                 self.tokens.error("%s is not a character literal"%token)
>         elif "." in token:
              #float literal
>             try:
>                 type_ = "float"
>                 signed = True
>                 size = 4
>                 token = token.upper().replace("F", "")
>                 token = token.upper().replace("L", "")
>                 value = float(eval(token))
  
>                 try:
>                     byte_value = struct.pack(">f", value)
>                 except OverflowError:
>                     self.tokens.error("value too large")
  
>             except SyntaxError:
>                 self.tokens.error("%s is not a floating point literal"%token)
>         else:
              #integer literal
>             try:
>                 if "U" in token.upper():
>                     signed = False
>                 if "L" in token.upper():
>                     size = 4
>                 token = token.upper().replace("U", "")
>                 value = int(eval(token))
  
>                 if signed:
>                     if value > 2**((size * 8)-1) - 1:
>                         self.tokens.error("value too large")
>                     if value < -(2**((size * 8)-1)):
>                         self.tokens.error("value too small")
>                 else:
>                     if value > 2**(size * 8) - 1:
!                         self.tokens.error("value too large")
>                     if value < 0:
>                         self.tokens.error("value too small")
  
>             except SyntaxError:
>                 self.tokens.error("%s is not an integer literal"%token)
  
>         return Constant(value, type_, size, signed)
  
>     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 numeric_types:
  
>             if not hasattr(instance, "reference"):
  
>                 self.tokens.error(
>                     "Not an expression")
  
>             return Variable(instance)
>         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"]:
  
>                     self.tokens.error(
>                         "Array indices must be an integer like expression")
  
>                 return ArrayIndex(instance, index_expression)
>             else:
>                 return Array(instance)
>         elif instance.type_().startswith("struct"):
>             if self.tokens.peek() == ".":
>                 self.tokens.expect(".")
>                 member = self.tokens.get()
>                 instance = instance.members[member]
>                 return self.parse_variable_array_struct(instance)
>             else:
>                 return Struct(instance)
  
> def compatible(left, right):
>     return left.type_() == right.type_()

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.