Line 1... |
Line 1... |
> __author__ = "Jon Dawson"
|
> __author__ = "Jon Dawson"
|
> __copyright__ = "Copyright (C) 2012, Jonathan P Dawson"
|
> __copyright__ = "Copyright (C) 2012, Jonathan P Dawson"
|
> __version__ = "0.1"
|
> __version__ = "0.1"
|
|
|
|
> import struct
|
|
> from copy import copy
|
|
|
> from parse_tree import *
|
> from parse_tree import *
|
> from tokens import Tokens
|
> from tokens import Tokens
|
> from allocator import Allocator
|
> from allocator import Allocator
|
|
|
> def optimise_if(if_statement):
|
> types = ["float", "signed", "unsigned", "short", "long", "char", "int", "void"]
|
> try:
|
> numeric_types = ["float", "signed", "unsigned", "short", "long", "char", "int"]
|
> if value(if_statement.expression):
|
> storage_specifiers = ["const"]
|
> 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:
|
> class Parser:
|
|
|
> """Turn the C input file into a tree of expressions and statements."""
|
> """Turn the C input file into a tree of expressions and statements."""
|
|
|
> def __init__(self, input_file, reuse):
|
> def __init__(self, input_file, reuse, initialize_memory):
|
> self.scope = {}
|
> self.scope = {}
|
> self.function = None
|
> self.function = None
|
> self.loop = None
|
> self.loop = None
|
> self.tokens = Tokens(input_file)
|
> self.tokens = Tokens(input_file)
|
> self.allocator = Allocator(reuse)
|
> self.allocator = Allocator(reuse)
|
> self.structs = []
|
> self.structs = []
|
|
> self.initialize_memory = initialize_memory
|
|
|
> def parse_process(self):
|
> def parse_process(self):
|
> process = Process()
|
> process = Process()
|
> process.allocator = self.allocator
|
> process.allocator = self.allocator
|
> process.inputs = []
|
> process.inputs = []
|
Line 45... |
Line 40... |
> else:
|
> else:
|
> process.functions.append(self.parse_function())
|
> process.functions.append(self.parse_function())
|
> process.main = self.main
|
> process.main = self.main
|
> return process
|
> 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):
|
> def parse_function(self):
|
> function = Function()
|
> function = Function()
|
> function.allocator = self.allocator
|
> function.allocator = self.allocator
|
> stored_scope = self.scope
|
> stored_scope = copy(self.scope)
|
> type_ = self.tokens.get()
|
> type_, size, signed, const = self.parse_type_specifier()
|
> name = self.tokens.get()
|
> name = self.tokens.get()
|
|
|
#check if it is a global declaration
|
#check if it is a global declaration
|
> if self.tokens.peek() != "(":
|
> if self.tokens.peek() != "(":
|
> if type_ not in ["int", "short", "long", "char"] + self.structs:
|
> return self.parse_global_declaration(type_, size, signed, const, name)
|
! self.tokens.error("unknown type")
|
|
> return self.parse_global_declaration(type_, name)
|
|
|
|
#otherwise continue parsing a function
|
#otherwise continue parsing a function
|
> self.tokens.expect("(")
|
> self.tokens.expect("(")
|
> function.name = name
|
> function.name = name
|
> function.type_ = type_
|
> function.type_ = type_
|
> function.return_address = self.allocator.new(function.name+" return address")
|
> function.size = size
|
> if type_ not in ["int", "short", "long", "char", "void"]:
|
> function.signed = signed
|
! self.tokens.error("unknown type")
|
|
|
> function.return_address = self.allocator.new(2,
|
|
> function.name+" return address")
|
|
|
> if type_ != "void":
|
> if type_ != "void":
|
> function.return_value = self.allocator.new(function.name+" return value")
|
|
|
> 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 = []
|
> function.arguments = []
|
> while self.tokens.peek() != ")":
|
> while self.tokens.peek() != ")":
|
> type_ = self.tokens.get()
|
> function.arguments.append(self.parse_argument())
|
> 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() == ",":
|
> if self.tokens.peek() == ",":
|
> self.tokens.expect(",")
|
> self.tokens.expect(",")
|
> else:
|
> else:
|
> break
|
> break
|
|
|
> self.tokens.expect(")")
|
> self.tokens.expect(")")
|
> self.function = function
|
> self.function = function
|
> function.statement = self.parse_statement()
|
> function.statement = self.parse_statement()
|
> if type_ != "void" and not hasattr(function, "return_statement"):
|
> if type_ != "void" and not hasattr(function, "return_statement"):
|
> self.tokens.error("Function must have a return statement")
|
> self.tokens.error("Function must have a return statement")
|
Line 111... |
Line 201... |
> return continue_
|
> return continue_
|
|
|
> def parse_return(self):
|
> def parse_return(self):
|
> return_ = Return()
|
> return_ = Return()
|
> return_.function = self.function
|
> return_.function = self.function
|
|
> return_.allocator = self.allocator
|
> self.function.return_statement = return_
|
> self.function.return_statement = return_
|
> self.tokens.expect("return")
|
> self.tokens.expect("return")
|
> if hasattr(self.function, "return_value"):
|
> if hasattr(self.function, "return_value"):
|
> return_.expression = self.parse_expression()
|
> return_.expression = self.parse_expression()
|
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
Line 154... |
Line 245... |
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
> wait_clocks.line = self.tokens.lineno
|
> wait_clocks.line = self.tokens.lineno
|
> return wait_clocks
|
> return wait_clocks
|
|
|
> def parse_statement(self):
|
> def parse_statement(self):
|
> if self.tokens.peek() in ["int", "short", "long", "char"] + self.structs:
|
> if self.tokens.peek() in numeric_types + self.structs + storage_specifiers:
|
> return self.parse_compound_declaration()
|
> return self.parse_compound_declaration()
|
> elif self.tokens.peek() == "struct":
|
> elif self.tokens.peek() == "struct":
|
> return self.parse_struct_declaration()
|
> return self.parse_struct_declaration()
|
> elif self.tokens.peek() == "if":
|
> elif self.tokens.peek() == "if":
|
> return self.parse_if()
|
> return self.parse_if()
|
Line 194... |
Line 285... |
> def parse_discard(self):
|
> def parse_discard(self):
|
> return DiscardExpression(self.parse_expression(), self.allocator)
|
> return DiscardExpression(self.parse_expression(), self.allocator)
|
|
|
> def parse_assignment(self):
|
> def parse_assignment(self):
|
> assignment_operators = [
|
> assignment_operators = [
|
> "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=",
|
> "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>="
|
> "++", "--"
|
|
> ]
|
> ]
|
> lvalue = self.parse_ternary_expression()
|
> lvalue = self.parse_ternary_expression()
|
> if self.tokens.peek() in assignment_operators:
|
> if self.tokens.peek() in assignment_operators:
|
> if not hasattr(lvalue, "declaration"):
|
> if lvalue.const():
|
|
|
> self.tokens.error(
|
> self.tokens.error(
|
> "left hand operand of assignment is not modifiable"
|
> "left hand operand of assignment is not modifiable")
|
> )
|
|
> operator = self.tokens.get()
|
> operator = self.tokens.get()
|
> if operator == "=":
|
> if operator == "=":
|
> expression = self.parse_ternary_expression()
|
> expression = self.parse_ternary_expression()
|
> elif operator in ["++", "--"]:
|
|
> expression = Binary(
|
|
> operator[:-1],
|
|
> lvalue,
|
|
> Constant(1),
|
|
> self.allocator
|
|
> )
|
|
> else:
|
> else:
|
> expression = Binary(
|
|
> operator[:-1],
|
> expression = self.parse_ternary_expression()
|
> lvalue,
|
> left = lvalue
|
> self.parse_ternary_expression(),
|
> left, expression = self.coerce_types(left, expression)
|
> self.allocator
|
> expression = Binary(operator[:-1], left, expression)
|
> )
|
|
> if lvalue.type_ != expression.type_:
|
> 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(
|
> self.tokens.error(
|
> "type mismatch in assignment"
|
> "type mismatch in assignment expected: %s actual: %s"%(
|
> )
|
> lvalue.type_(),
|
|
> expression.type_()))
|
|
|
> return Assignment(lvalue, expression, self.allocator)
|
> return Assignment(lvalue, expression, self.allocator)
|
> else:
|
> else:
|
> return lvalue
|
> return lvalue
|
|
|
|
|
> def parse_if(self):
|
> def parse_if(self):
|
> if_ = If()
|
> if_ = If()
|
> if_.allocator = self.allocator
|
> if_.allocator = self.allocator
|
> self.tokens.expect("if")
|
> self.tokens.expect("if")
|
> self.tokens.expect("(")
|
> self.tokens.expect("(")
|
> if_.expression = self.parse_expression()
|
> if_.expression = self.parse_expression()
|
> if if_.expression.type_ not in ["int", "short", "long", "char"]:
|
> if if_.expression.type_() not in ["unsigned", "int", "short", "long", "char"]:
|
> self.tokens.error(
|
> self.tokens.error(
|
> "if statement conditional must be an integer like expression"
|
> "if statement conditional must be an integer like expression")
|
> )
|
|
> self.tokens.expect(")")
|
> self.tokens.expect(")")
|
> if_.true_statement = self.parse_statement()
|
> if_.true_statement = self.parse_statement()
|
> if self.tokens.peek() == "else":
|
> if self.tokens.peek() == "else":
|
> self.tokens.expect("else")
|
> self.tokens.expect("else")
|
> if_.false_statement = self.parse_statement()
|
> if_.false_statement = self.parse_statement()
|
> else:
|
> else:
|
> if_.false_statement = None
|
> if_.false_statement = None
|
> return optimise_if(if_)
|
> return if_
|
|
|
> def parse_switch(self):
|
> def parse_switch(self):
|
> switch = Switch()
|
> switch = Switch()
|
> switch.cases = {}
|
> switch.cases = {}
|
> self.tokens.expect("switch")
|
> self.tokens.expect("switch")
|
> self.tokens.expect("(")
|
> self.tokens.expect("(")
|
> expression = self.parse_expression()
|
> expression = self.parse_expression()
|
> if expression.type_ not in ["int", "short", "long", "char"]:
|
> if expression.type_() not in ["unsigned", "int", "short", "long", "char"]:
|
> self.tokens.error(
|
> self.tokens.error(
|
> "switch statement expression must be an integer like expression"
|
> "switch statement expression must be an integer like expression")
|
> )
|
|
> self.tokens.expect(")")
|
> self.tokens.expect(")")
|
> stored_loop = self.loop
|
> stored_loop = self.loop
|
> self.loop = switch
|
> self.loop = switch
|
> statement = self.parse_statement()
|
> statement = self.parse_statement()
|
> self.loop = stored_loop
|
> self.loop = stored_loop
|
Line 271... |
Line 359... |
> return switch
|
> return switch
|
|
|
> def parse_case(self):
|
> def parse_case(self):
|
> self.tokens.expect("case")
|
> self.tokens.expect("case")
|
> expression = self.parse_expression()
|
> expression = self.parse_expression()
|
> if expression.type_ not in ["int", "short", "long", "char"]:
|
> if expression.type_() not in ["int"]:
|
> self.tokens.error(
|
> self.tokens.error(
|
> "case expression must be an integer like expression"
|
> "case expression must be an integer like expression")
|
> )
|
|
> self.tokens.expect(":")
|
> self.tokens.expect(":")
|
> try:
|
> try:
|
> expression = value(expression)
|
> expression = expression.value()
|
> case = Case()
|
> case = Case()
|
> self.loop.cases[expression] = case
|
> self.loop.cases[expression] = case
|
> except NotConstant:
|
> except NotConstant:
|
> self.tokens.error("case expression must be constant")
|
> self.tokens.error("case expression must be constant")
|
> except AttributeError:
|
> except AttributeError:
|
> self.tokens.error(
|
> self.tokens.error(
|
> "case statements may only be use inside a switch statment"
|
> "case statements may only be use inside a switch statment")
|
> )
|
|
> return case
|
> return case
|
|
|
> def parse_default(self):
|
> def parse_default(self):
|
> self.tokens.expect("default")
|
> self.tokens.expect("default")
|
> self.tokens.expect(":")
|
> self.tokens.expect(":")
|
> default = Default()
|
> default = Default()
|
> if not hasattr(self.loop, "cases"):
|
> if not hasattr(self.loop, "cases"):
|
> self.tokens.error(
|
> self.tokens.error(
|
> "default statements may only be used inside a switch statment"
|
> "default statements may only be used inside a switch statment")
|
> )
|
|
> if hasattr(self.loop, "default"):
|
> if hasattr(self.loop, "default"):
|
> self.tokens.error(
|
> self.tokens.error(
|
> "A switch statement may only have one default statement"
|
> "A switch statement may only have one default statement")
|
> )
|
|
> self.loop.default=default
|
> self.loop.default=default
|
> return default
|
> return default
|
|
|
> def parse_while(self):
|
> def parse_while(self):
|
> loop = Loop()
|
> loop = Loop()
|
Line 315... |
Line 399... |
> self.loop = loop
|
> self.loop = loop
|
> statement = self.parse_statement()
|
> statement = self.parse_statement()
|
> self.loop = stored_loop
|
> self.loop = stored_loop
|
|
|
> if_ = If()
|
> if_ = If()
|
|
> loop.statement = if_
|
> break_ = Break()
|
> break_ = Break()
|
> break_.loop = loop
|
> break_.loop = loop
|
> if_.allocator = self.allocator
|
> if_.allocator = self.allocator
|
> if expression.type_ not in ["int", "short", "long", "char"]:
|
> if expression.type_() not in ["int"]:
|
> self.tokens.error(
|
> self.tokens.error(
|
> "if statement conditional must be an integer like expression"
|
> "while statement conditional must be an integer like expression")
|
> )
|
|
> if_.expression = expression
|
> if_.expression = expression
|
> if_.false_statement = break_
|
> if_.false_statement = break_
|
> if_.true_statement = statement
|
> if_.true_statement = statement
|
|
|
> loop.statement = optimise_if(if_)
|
|
> return loop
|
> return loop
|
|
|
> def parse_for(self):
|
> def parse_for(self):
|
> for_ = For()
|
> for_ = For()
|
> for_.allocator = self.allocator
|
> for_.allocator = self.allocator
|
Line 339... |
Line 422... |
> if self.tokens.peek() != ";":
|
> if self.tokens.peek() != ";":
|
> for_.statement1 = self.parse_discard()
|
> for_.statement1 = self.parse_discard()
|
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
> if self.tokens.peek() != ";":
|
> if self.tokens.peek() != ";":
|
> for_.expression = self.parse_expression()
|
> for_.expression = self.parse_expression()
|
> if for_.expression.type_ not in ["int", "short", "long", "char"]:
|
> if for_.expression.type_() not in [
|
|
> "unsigned",
|
|
> "int",
|
|
> "short",
|
|
> "long",
|
|
> "char"]:
|
|
|
> self.tokens.error(
|
> self.tokens.error(
|
> "for statement conditional must be an integer like expression"
|
> "For statement conditional must be an integer like expression")
|
> )
|
|
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
> if self.tokens.peek() != ")":
|
> if self.tokens.peek() != ")":
|
> for_.statement2 = self.parse_discard()
|
> for_.statement2 = self.parse_discard()
|
> self.tokens.expect(")")
|
> self.tokens.expect(")")
|
> stored_loop = self.loop
|
> stored_loop = self.loop
|
Line 355... |
Line 444... |
> self.loop = stored_loop
|
> self.loop = stored_loop
|
> return for_
|
> return for_
|
|
|
> def parse_block(self):
|
> def parse_block(self):
|
> block = Block()
|
> block = Block()
|
> stored_scope = self.scope
|
> stored_scope = copy(self.scope)
|
> self.tokens.expect("{")
|
> self.tokens.expect("{")
|
> block.statements = []
|
> block.statements = []
|
> while self.tokens.peek() != "}":
|
> while self.tokens.peek() != "}":
|
> block.statements.append(self.parse_statement())
|
> block.statements.append(self.parse_statement())
|
> self.tokens.expect("}")
|
> self.tokens.expect("}")
|
Line 368... |
Line 457... |
|
|
> def parse_struct_body(self):
|
> def parse_struct_body(self):
|
> self.tokens.expect("{")
|
> self.tokens.expect("{")
|
> members = {}
|
> members = {}
|
> while self.tokens.peek() != "}":
|
> while self.tokens.peek() != "}":
|
> type_ = self.tokens.get()
|
> type_, size, signed, const = self.parse_type_specifier()
|
> name = self.tokens.get()
|
> name = self.tokens.get()
|
> members[name] = self.parse_declaration(type_, name)
|
|
|
> members[name] = self.parse_declaration(
|
|
> type_,
|
|
> size,
|
|
> signed,
|
|
> const,
|
|
> name)
|
|
|
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
> self.tokens.expect("}")
|
> self.tokens.expect("}")
|
> return members
|
> return members
|
|
|
> def parse_typedef_struct(self):
|
> def parse_typedef_struct(self):
|
Line 400... |
Line 496... |
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
> instance = self.scope[struct_name].instance()
|
> instance = self.scope[struct_name].instance()
|
> self.scope[name] = instance
|
> self.scope[name] = instance
|
> return instance
|
> return instance
|
|
|
> def parse_global_declaration(self, type_, name):
|
> def parse_global_declaration(self, type_, size, signed, const, name):
|
> instances = []
|
> instances = []
|
> while True:
|
> while True:
|
> instance = self.parse_declaration(type_, name).instance()
|
|
|
> instance = self.parse_declaration(
|
|
> type_,
|
|
> size,
|
|
> signed,
|
|
> const,
|
|
> name).instance()
|
|
|
> self.scope[name] = instance
|
> self.scope[name] = instance
|
> instances.append(instance)
|
> instances.append(instance)
|
> if self.tokens.peek() == ",":
|
> if self.tokens.peek() == ",":
|
> self.tokens.expect(",")
|
> self.tokens.expect(",")
|
> else:
|
> else:
|
Line 415... |
Line 518... |
> name = self.tokens.get()
|
> name = self.tokens.get()
|
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
> return CompoundDeclaration(instances)
|
> return CompoundDeclaration(instances)
|
|
|
> def parse_compound_declaration(self):
|
> def parse_compound_declaration(self):
|
> type_ = self.tokens.get()
|
> type_, size, signed, const = self.parse_type_specifier()
|
> instances = []
|
> instances = []
|
> while True:
|
> while True:
|
> name = self.tokens.get()
|
> name = self.tokens.get()
|
> instance = self.parse_declaration(type_, name).instance()
|
|
|
> instance = self.parse_declaration(
|
|
> type_,
|
|
> size,
|
|
> signed,
|
|
> const,
|
|
> name).instance()
|
|
|
> self.scope[name] = instance
|
> self.scope[name] = instance
|
> instances.append(instance)
|
> instances.append(instance)
|
> if self.tokens.peek() == ",":
|
> if self.tokens.peek() == ",":
|
> self.tokens.expect(",")
|
> self.tokens.expect(",")
|
> else:
|
> else:
|
> break
|
> break
|
> name = None
|
> name = None
|
> self.tokens.expect(";")
|
> self.tokens.expect(";")
|
> return CompoundDeclaration(instances)
|
> return CompoundDeclaration(instances)
|
|
|
> def parse_declaration(self, type_, name):
|
> def parse_declaration(self, type_, size, signed, const, name):
|
#struct declaration
|
#struct declaration
|
> if type_ in self.structs:
|
> if type_ in self.structs:
|
> declaration = self.scope[type_]
|
> declaration = self.scope[type_]
|
> elif type_ in ["int", "short", "long", "char"]:
|
> elif type_ in ["int", "float"]:
|
#array declaration
|
#array declaration
|
> if self.tokens.peek() == "[":
|
> if self.tokens.peek() == "[":
|
> size = None
|
> array_size = None
|
> self.tokens.expect("[")
|
> self.tokens.expect("[")
|
> if self.tokens.peek() != "]":
|
> if self.tokens.peek() != "]":
|
> size = self.tokens.get()
|
> 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("]")
|
> self.tokens.expect("]")
|
> initializer = None
|
> initializer = None
|
> if self.tokens.peek() == "=":
|
> if self.tokens.peek() == "=":
|
> self.tokens.expect("=")
|
> self.tokens.expect("=")
|
> initializer = self.tokens.get()
|
> initializer = self.tokens.get()
|
> initializer = [ord(i) for i in initializer.strip('"')] + [0]
|
> initializer = [ord(i) for i in initializer.strip('"').decode("string_escape")] + [0]
|
> size = len(initializer)
|
> array_size = len(initializer)
|
> if size is None:
|
> if array_size is None:
|
> self.tokens.error("array size must be specified if not initialized")
|
|
> type_+="[]"
|
> self.tokens.error(
|
> declaration = ArrayDeclaration(self.allocator, size, type_, initializer)
|
> "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
|
#simple variable declaration
|
> else:
|
> else:
|
> if self.tokens.peek() == "=":
|
> if self.tokens.peek() == "=":
|
> self.tokens.expect("=")
|
> self.tokens.expect("=")
|
> initializer = self.parse_ternary_expression()
|
> initializer = self.parse_ternary_expression()
|
> else:
|
> else:
|
> initializer = Constant(0)
|
> 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(
|
> declaration = VariableDeclaration(
|
> self.allocator,
|
> self.allocator,
|
> initializer,
|
> initializer,
|
> name,
|
> name,
|
> type_
|
> type_,
|
|
> size,
|
|
> signed,
|
|
> const
|
> )
|
> )
|
|
|
> return declaration
|
> return declaration
|
|
|
> def parse_expression(self):
|
> def parse_expression(self):
|
Line 497... |
Line 641... |
> while self.tokens.peek() in ["&&"]:
|
> while self.tokens.peek() in ["&&"]:
|
> self.tokens.expect("&&")
|
> self.tokens.expect("&&")
|
> expression = AND(expression, self.parse_binary_expression(["|"]))
|
> expression = AND(expression, self.parse_binary_expression(["|"]))
|
> return 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):
|
> def parse_binary_expression(self, operators):
|
> operator_precedence = {
|
> operator_precedence = {
|
> "|": ["^"],
|
> "|": ["^"],
|
> "^": ["&"],
|
> "^": ["&"],
|
> "&": ["==", "!="],
|
> "&": ["==", "!="],
|
Line 508... |
Line 711... |
> "<": ["<<", ">>"],
|
> "<": ["<<", ">>"],
|
> "<<": ["+", "-"],
|
> "<<": ["+", "-"],
|
> "+": ["*", "/", "%"],
|
> "+": ["*", "/", "%"],
|
> }
|
> }
|
> if operators[0] not in operator_precedence:
|
> if operators[0] not in operator_precedence:
|
> expression = self.parse_unary_expression()
|
> left = self.parse_unary_expression()
|
> while self.tokens.peek() in operators:
|
> while self.tokens.peek() in operators:
|
> expression = Binary(
|
> operator = self.tokens.get()
|
> self.tokens.get(),
|
> right = self.parse_unary_expression()
|
> expression,
|
> left, right = self.coerce_types(left, right)
|
> self.parse_unary_expression(),
|
> left = Binary(operator, left, right)
|
> self.allocator
|
> left = self.substitute_function(left)
|
> )
|
> return left
|
> return expression
|
|
> else:
|
> else:
|
> next_operators = operator_precedence[operators[0]]
|
> next_operators = operator_precedence[operators[0]]
|
> expression = self.parse_binary_expression(next_operators)
|
> left = self.parse_binary_expression(next_operators)
|
> while self.tokens.peek() in operators:
|
> while self.tokens.peek() in operators:
|
> expression = Binary(
|
> operator = self.tokens.get()
|
> self.tokens.get(),
|
> right = self.parse_binary_expression(next_operators)
|
> expression,
|
> left, right = self.coerce_types(left, right)
|
> self.parse_binary_expression(next_operators),
|
> left = Binary(operator, left, right)
|
> self.allocator
|
> left = self.substitute_function(left)
|
> )
|
> return left
|
> return expression
|
|
|
|
> def parse_unary_expression(self):
|
> def parse_unary_expression(self):
|
> if self.tokens.peek() == "!":
|
> if self.tokens.peek() == "!":
|
> operator = self.tokens.get()
|
> operator = self.tokens.get()
|
> expression = self.parse_paren_expression()
|
> expression = self.parse_postfix_expression()
|
> return Binary("==", expression, Constant(0), self.allocator)
|
> return Binary("==", expression, Constant(0))
|
> elif self.tokens.peek() == "-":
|
> elif self.tokens.peek() == "-":
|
> operator = self.tokens.get()
|
> operator = self.tokens.get()
|
> expression = self.parse_paren_expression()
|
> expression = self.parse_postfix_expression()
|
> return Binary("-", Constant(0), expression, self.allocator)
|
> return Binary("-", Constant(0,
|
|
> expression.type_(),
|
|
> expression.size(),
|
|
> expression.signed()),
|
|
> expression)
|
> elif self.tokens.peek() == "~":
|
> elif self.tokens.peek() == "~":
|
> operator = self.tokens.get()
|
> operator = self.tokens.get()
|
> expression = self.parse_paren_expression()
|
> expression = self.parse_postfix_expression()
|
> return Unary("~", expression)
|
> return Unary("~", expression)
|
|
> elif self.tokens.peek() == "sizeof":
|
|
> operator = self.tokens.get()
|
|
> expression = self.parse_unary_expression()
|
|
> return SizeOf(expression)
|
> else:
|
> else:
|
> return self.parse_paren_expression()
|
> 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):
|
> def parse_paren_expression(self):
|
> if self.tokens.peek() == "(":
|
> if self.tokens.peek() == "(":
|
> self.tokens.expect("(")
|
> self.tokens.expect("(")
|
> expression = self.parse_expression()
|
> expression = self.parse_expression()
|
Line 564... |
Line 784... |
> else:
|
> else:
|
> return self.parse_variable(name)
|
> return self.parse_variable(name)
|
> else:
|
> else:
|
> return self.parse_number()
|
> 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):
|
> def parse_input(self, name):
|
> input_name = name.replace("input_", "")
|
> input_name = name.replace("input_", "")
|
> self.tokens.expect("(")
|
> self.tokens.expect("(")
|
> self.tokens.expect(")")
|
> self.tokens.expect(")")
|
> return Input(input_name)
|
> return Input(input_name)
|
Line 590... |
Line 826... |
> return self.parse_input(name)
|
> return self.parse_input(name)
|
> if name.startswith("ready_"):
|
> if name.startswith("ready_"):
|
> return self.parse_ready(name)
|
> return self.parse_ready(name)
|
> if name.startswith("output_"):
|
> if name.startswith("output_"):
|
> return self.parse_output(name)
|
> return self.parse_output(name)
|
> function_call = FunctionCall()
|
> 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 = []
|
> function_call.arguments = []
|
> self.tokens.expect("(")
|
> self.tokens.expect("(")
|
> while self.tokens.peek() != ")":
|
> while self.tokens.peek() != ")":
|
> function_call.arguments.append(self.parse_expression())
|
> function_call.arguments.append(self.parse_expression())
|
> if self.tokens.peek() == ",":
|
> if self.tokens.peek() == ",":
|
> self.tokens.expect(",")
|
> self.tokens.expect(",")
|
> else:
|
> else:
|
> break
|
> break
|
> self.tokens.expect(")")
|
> 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)
|
> required_arguments = len(function_call.function.arguments)
|
> actual_arguments = len(function_call.arguments)
|
> actual_arguments = len(function_call.arguments)
|
> if required_arguments != actual_arguments:
|
> if required_arguments != actual_arguments:
|
> self.tokens.error("Function %s takes %s arguments %s given."%(
|
> self.tokens.error("Function %s takes %s arguments %s given."%(
|
> name,
|
> name,
|
> len(function_call.function.arguments),
|
> len(function_call.function.arguments),
|
> len(function_call.arguments)
|
> len(function_call.arguments)))
|
> ))
|
|
> required_arguments = function_call.function.arguments
|
> required_arguments = function_call.function.arguments
|
> actual_arguments = function_call.arguments
|
> actual_arguments = function_call.arguments
|
|
> corrected_arguments = []
|
> for required, actual in zip(required_arguments, actual_arguments):
|
> for required, actual in zip(required_arguments, actual_arguments):
|
> if required.type_ != actual.type_:
|
> if not compatible(required, actual):
|
> self.tokens.error("Type mismatch expected type : %s got: %s."%(
|
> if actual.type_() == "int" and required.type_() == "float":
|
> required.type_,
|
> actual = IntToFloat(actual)
|
> actual.type_
|
> 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
|
> return function_call
|
|
|
> def parse_number(self):
|
> def parse_number(self):
|
> token = self.tokens.get()
|
> token = self.tokens.get()
|
|
> type_ = "int"
|
|
> size = 2
|
|
> signed = True
|
> if token.startswith("'"):
|
> if token.startswith("'"):
|
> try:
|
> try:
|
> token = eval(token)
|
> token = eval(token)
|
> value = ord(token)
|
> value = ord(token)
|
! except SyntaxError:
|
! except SyntaxError:
|
! self.tokens.error("%s is not a character literal"%token)
|
! 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:
|
> else:
|
|
#integer literal
|
> try:
|
> try:
|
|
> if "U" in token.upper():
|
|
> signed = False
|
|
> if "L" in token.upper():
|
|
> size = 4
|
|
> token = token.upper().replace("U", "")
|
> value = int(eval(token))
|
> 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:
|
> except SyntaxError:
|
> self.tokens.error("%s is not an integer literal"%token)
|
> self.tokens.error("%s is not an integer literal"%token)
|
> return Constant(value)
|
|
|
> return Constant(value, type_, size, signed)
|
|
|
> def parse_variable(self, name):
|
> def parse_variable(self, name):
|
> if name not in self.scope:
|
> if name not in self.scope:
|
> self.tokens.error("Unknown variable: %s"%name)
|
> self.tokens.error("Unknown variable: %s"%name)
|
> instance = self.scope[name]
|
> instance = self.scope[name]
|
> return self.parse_variable_array_struct(instance)
|
> return self.parse_variable_array_struct(instance)
|
|
|
> def parse_variable_array_struct(self, instance):
|
> def parse_variable_array_struct(self, instance):
|
> if instance.type_ in ["int", "short", "long", "char"]:
|
> if instance.type_() in numeric_types:
|
> return Variable(instance, self.allocator)
|
|
> elif instance.type_.endswith("[]"):
|
> if not hasattr(instance, "reference"):
|
|
|
|
> self.tokens.error(
|
|
> "Not an expression")
|
|
|
|
> return Variable(instance)
|
|
> elif instance.type_().endswith("[]"):
|
> if self.tokens.peek() == "[":
|
> if self.tokens.peek() == "[":
|
> self.tokens.expect("[")
|
> self.tokens.expect("[")
|
> index_expression = self.parse_expression()
|
> index_expression = self.parse_expression()
|
> self.tokens.expect("]")
|
> self.tokens.expect("]")
|
> if index_expression.type_ not in ["int", "short", "long", "char"]:
|
> if index_expression.type_() not in ["int"]:
|
|
|
> self.tokens.error(
|
> self.tokens.error(
|
> "array indices must be an integer like expression"
|
> "Array indices must be an integer like expression")
|
> )
|
|
> return ArrayIndex(instance, index_expression, self.allocator)
|
> return ArrayIndex(instance, index_expression)
|
> else:
|
> else:
|
> return Array(instance, self.allocator)
|
> return Array(instance)
|
> elif instance.type_ == "struct":
|
> elif instance.type_().startswith("struct"):
|
|
> if self.tokens.peek() == ".":
|
> self.tokens.expect(".")
|
> self.tokens.expect(".")
|
> member = self.tokens.get()
|
> member = self.tokens.get()
|
> instance = instance.members[member]
|
> instance = instance.members[member]
|
> return self.parse_variable_array_struct(instance)
|
> return self.parse_variable_array_struct(instance)
|
|
> else:
|
|
> return Struct(instance)
|
|
|
|
> def compatible(left, right):
|
|
> return left.type_() == right.type_()
|