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
|
|
|
|
types = ["float", "signed", "unsigned", "short", "long", "char", "int", "void"]
|
|
numeric_types = ["float", "signed", "unsigned", "short", "long", "char", "int"]
|
|
storage_specifiers = ["const"]
|
|
|
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, initialize_memory):
|
def __init__(self, input_file, reuse, initialize_memory):
|
Line 36... |
Line 43... |
return process
|
return process
|
|
|
def parse_type_specifier(self):
|
def parse_type_specifier(self):
|
type_specifiers = []
|
type_specifiers = []
|
|
|
while self.tokens.peek() in ["signed", "unsigned", "short", "long", "char", "int", "void"] + self.structs:
|
while self.tokens.peek() in types + self.structs + storage_specifiers:
|
type_specifiers.append(self.tokens.get())
|
type_specifiers.append(self.tokens.get())
|
|
|
signed = True
|
signed = True
|
if "unsigned" in type_specifiers:
|
if "unsigned" in type_specifiers:
|
signed = False
|
signed = False
|
Line 58... |
Line 65... |
if i in self.structs:
|
if i in self.structs:
|
type_ = i
|
type_ = i
|
size = 2
|
size = 2
|
signed = False
|
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:
|
if "void" in type_specifiers:
|
type_ = "void"
|
type_ = "void"
|
size = 2
|
size = 2
|
signed = False
|
signed = False
|
|
|
|
|
return type_, size, signed
|
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_, size, signed = self.parse_type_specifier()
|
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() != "(":
|
return self.parse_global_declaration(type_, size, signed, name)
|
return self.parse_global_declaration(type_, size, signed, const, 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.size = size
|
function.size = size
|
function.signed = signed
|
function.signed = signed
|
function.return_address = self.allocator.new(2, function.name+" return address")
|
|
|
function.return_address = self.allocator.new(2,
|
|
function.name+" return address")
|
|
|
if type_ != "void":
|
if type_ != "void":
|
function.return_value = self.allocator.new(function.size, function.name+" return value")
|
|
function.arguments = []
|
if type_ in self.structs:
|
while self.tokens.peek() != ")":
|
declaration = self.scope[type_]
|
argument_type, argument_size, argument_signed = self.parse_type_specifier()
|
else:
|
if argument_type in ["void"]:
|
|
self.tokens.error("argument cannot be void")
|
|
argument = self.tokens.get()
|
|
element_type = None
|
|
element_size = None
|
|
element_signed = None
|
|
if self.tokens.peek() == "[":
|
if self.tokens.peek() == "[":
|
self.tokens.expect("[")
|
self.tokens.error(
|
self.tokens.expect("]")
|
"Functions cannot return arrays")
|
element_type = argument_type
|
else:
|
element_size = argument_size
|
declaration = VariableDeclaration(
|
element_signed = argument_signed
|
self.allocator,
|
argument_type+="[]"
|
None,
|
argument_size = 2
|
function.name+" return value",
|
argument_signed = False
|
type_,
|
|
size,
|
|
signed,
|
|
const)
|
|
|
function.arguments.append(Argument(
|
function.return_value = declaration.instance().reference()
|
argument,
|
|
argument_type,
|
function.arguments = []
|
argument_size,
|
while self.tokens.peek() != ")":
|
argument_signed,
|
function.arguments.append(self.parse_argument())
|
self,
|
|
element_type,
|
|
element_size,
|
|
element_signed))
|
|
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 147... |
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 190... |
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 ["unsigned", "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 230... |
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()
|
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 not compatible(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 ["unsigned", "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()
|
Line 281... |
Line 343... |
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 ["unsigned", "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 298... |
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"]:
|
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 346... |
Line 403... |
if_ = If()
|
if_ = If()
|
loop.statement = 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"]:
|
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
|
|
|
return loop
|
return loop
|
Line 366... |
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 ["unsigned", "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 382... |
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 395... |
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_, size, signed = self.parse_type_specifier()
|
type_, size, signed, const = self.parse_type_specifier()
|
name = self.tokens.get()
|
name = self.tokens.get()
|
members[name] = self.parse_declaration(type_, size, signed, 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 427... |
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_, size, signed, name):
|
def parse_global_declaration(self, type_, size, signed, const, name):
|
instances = []
|
instances = []
|
while True:
|
while True:
|
instance = self.parse_declaration(type_, size, signed, 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 442... |
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_, size, signed = self.parse_type_specifier()
|
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_, size, signed, 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_, size, signed, 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"]:
|
elif type_ in ["int", "float"]:
|
#array declaration
|
#array declaration
|
if self.tokens.peek() == "[":
|
if self.tokens.peek() == "[":
|
array_size = None
|
array_size = None
|
self.tokens.expect("[")
|
self.tokens.expect("[")
|
if self.tokens.peek() != "]":
|
if self.tokens.peek() != "]":
|
array_size = int(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('"').decode("string_escape")] + [0]
|
initializer = [ord(i) for i in initializer.strip('"').decode("string_escape")] + [0]
|
array_size = len(initializer)
|
array_size = len(initializer)
|
if array_size is None:
|
if array_size is None:
|
self.tokens.error("array size must be specified if not initialized")
|
|
|
self.tokens.error(
|
|
"array size must be specified if not initialized")
|
|
|
array_type=type_+"[]"
|
array_type=type_+"[]"
|
initialize_memory = self.initialize_memory
|
initialize_memory = self.initialize_memory
|
declaration = ArrayDeclaration(self.allocator,
|
declaration = ArrayDeclaration(
|
|
self.allocator,
|
array_size,
|
array_size,
|
array_type,
|
array_type,
|
type_,
|
type_,
|
size,
|
size,
|
signed,
|
signed,
|
Line 494... |
Line 588... |
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,
|
size,
|
signed
|
signed,
|
|
const
|
)
|
)
|
|
|
return declaration
|
return declaration
|
|
|
def parse_expression(self):
|
def parse_expression(self):
|
Line 534... |
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, operator, left, right):
|
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
|
#Some things can't be implemented in verilog, substitute them with a function
|
if operator in ["/", "%"]:
|
if signature in functions:
|
function_call = FunctionCall()
|
function = self.scope[functions[signature]]
|
function_call.arguments = [left, right]
|
function_call = FunctionCall(function)
|
if operator == "/":
|
function_call.arguments = [binary_expression.left, binary_expression.right]
|
if left.signed and right.signed:
|
|
if max(left.size, right.size) == 4:
|
|
function_call.function = self.scope["long_divide_xxxx"]
|
|
else:
|
|
function_call.function = self.scope["divide_xxxx"]
|
|
else:
|
|
if max(left.size, right.size) == 4:
|
|
function_call.function = self.scope["long_unsigned_divide_xxxx"]
|
|
else:
|
|
function_call.function = self.scope["unsigned_divide_xxxx"]
|
|
elif operator == "%":
|
|
if left.signed and right.signed:
|
|
if max(left.size, right.size) == 4:
|
|
function_call.function = self.scope["long_modulo_xxxx"]
|
|
else:
|
|
function_call.function = self.scope["modulo_xxxx"]
|
|
else:
|
|
if max(left.size, right.size) == 4:
|
|
function_call.function = self.scope["long_unsigned_modulo_xxxx"]
|
|
else:
|
|
function_call.function = self.scope["unsigned_modulo_xxxx"]
|
|
function_call.type_ = function_call.function.type_
|
|
function_call.size = function_call.function.size
|
|
function_call.signed = function_call.function.signed
|
|
return function_call
|
return function_call
|
else:
|
else:
|
return Binary(
|
return binary_expression
|
operator,
|
|
left,
|
def coerce_types(self, left, right):
|
right,
|
|
self.allocator
|
"""
|
)
|
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 584... |
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:
|
operator = self.tokens.get()
|
operator = self.tokens.get()
|
right = self.parse_unary_expression()
|
right = self.parse_unary_expression()
|
expression = self.substitute_function(operator, expression, right)
|
left, right = self.coerce_types(left, right)
|
return expression
|
left = Binary(operator, left, right)
|
|
left = self.substitute_function(left)
|
|
return left
|
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_postfix_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_postfix_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_postfix_expression()
|
expression = self.parse_postfix_expression()
|
return Unary("~", expression, self.allocator)
|
return Unary("~", expression)
|
elif self.tokens.peek() == "sizeof":
|
elif self.tokens.peek() == "sizeof":
|
operator = self.tokens.get()
|
operator = self.tokens.get()
|
expression = self.parse_unary_expression()
|
expression = self.parse_unary_expression()
|
return SizeOf(expression)
|
return SizeOf(expression)
|
else:
|
else:
|
Line 698... |
Line 830... |
return self.parse_output(name)
|
return self.parse_output(name)
|
if name == "file_read":
|
if name == "file_read":
|
return self.parse_file_read()
|
return self.parse_file_read()
|
if name == "file_write":
|
if name == "file_write":
|
return self.parse_file_write()
|
return self.parse_file_write()
|
function_call = FunctionCall()
|
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_
|
|
function_call.size = function_call.function.size
|
|
function_call.signed = function_call.function.signed
|
|
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 not compatible(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
|
size = 2
|
signed = True
|
signed = True
|
if token.startswith("'"):
|
if token.startswith("'"):
|
try:
|
try:
|
token = eval(token)
|
token = eval(token)
|
Line 760... |
Line 896... |
"int",
|
"int",
|
2,
|
2,
|
False,
|
False,
|
initializer,
|
initializer,
|
self.initialize_memory)
|
self.initialize_memory)
|
return declaration.instance()
|
return ConstArray(declaration.instance())
|
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 "." 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():
|
if "U" in token.upper():
|
signed = False
|
signed = False
|
if "L" in token.upper():
|
if "L" in token.upper():
|
size = 4
|
size = 4
|
Line 785... |
Line 939... |
if value < 0:
|
if value < 0:
|
self.tokens.error("value too small")
|
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, size, signed)
|
|
|
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 ["unsigned", "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 ["unsigned", "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):
|
def compatible(left, right):
|
return left == right
|
return left.type_() == right.type_()
|
|
|
No newline at end of file
|
No newline at end of file
|