Refactored ASTGenerator #3
|
@ -241,113 +241,116 @@ class AstGenerator:
|
||||||
# Generate the statements
|
# Generate the statements
|
||||||
self._generate_from_options(cutoffs, number_line, options)
|
self._generate_from_options(cutoffs, number_line, options)
|
||||||
|
|
||||||
def generate_int_expr(self):
|
|
||||||
self._generate_expression([GAZ_INT_KEY],
|
|
||||||
self.int_op_numline,
|
|
||||||
self.int_op_cutoffs,
|
|
||||||
self.int_op_options,
|
|
||||||
self.int_unary)
|
|
||||||
|
|
||||||
def generate_float_expr(self):
|
|
||||||
self._generate_expression([GAZ_FLOAT_KEY, GAZ_INT_KEY],
|
|
||||||
self.float_op_numline,
|
|
||||||
self.float_op_cutoffs,
|
|
||||||
self.float_op_options,
|
|
||||||
self.float_unary)
|
|
||||||
|
|
||||||
def generate_bool_expr(self):
|
|
||||||
self._generate_expression([GAZ_BOOL_KEY],
|
|
||||||
self.bool_op_numline,
|
|
||||||
self.bool_op_cutoffs,
|
|
||||||
self.bool_op_options,
|
|
||||||
self.bool_unary)
|
|
||||||
|
|
||||||
def generate_char_expr(self):
|
|
||||||
self._generate_expression([GAZ_CHAR_KEY],
|
|
||||||
self.char_op_numline,
|
|
||||||
self.char_op_cutoffs,
|
|
||||||
self.char_op_options)
|
|
||||||
|
|
||||||
def generate_comp_expr(self):
|
|
||||||
self._generate_expression([GAZ_BOOL_KEY],
|
|
||||||
self.comp_op_numline,
|
|
||||||
self.comp_op_cutoffs,
|
|
||||||
self.comp_op_options,
|
|
||||||
comparison=True)
|
|
||||||
|
|
||||||
def _generate_expression(self, expr_type: list[str], number_line,
|
def _generate_expression(self, expr_type: list[str], number_line,
|
||||||
cutoffs, options, unary=None, comparison: bool = False):
|
cutoffs, options, unary=None, comparison: bool = False):
|
||||||
|
"""
|
||||||
|
@brief Generate an expression
|
||||||
|
|
||||||
|
@param expr_type: a list of types to be used
|
||||||
|
@param number_line: number line for probability computation
|
||||||
|
@param cutoffs: cutoffs to be used
|
||||||
|
@param options: options to be used
|
||||||
|
@param unary: a list of unary operators in options
|
||||||
|
"""
|
||||||
if unary is None:
|
if unary is None:
|
||||||
unary = []
|
unary = []
|
||||||
|
|
||||||
parent = self.current_ast_element
|
parent = self.current_ast_element
|
||||||
self.current_nesting_depth += 1
|
self.current_nesting_depth += 1
|
||||||
|
|
||||||
|
# Check the expression depth against settings
|
||||||
if self.current_nesting_depth > self.settings['generation-options']['max-nesting-depth'] or random.random() < \
|
if self.current_nesting_depth > self.settings['generation-options']['max-nesting-depth'] or random.random() < \
|
||||||
self.settings['block-termination-probability']:
|
self.settings['block-termination-probability']:
|
||||||
self.generate_literal(random.choice(expr_type))
|
self.generate_literal(random.choice(expr_type))
|
||||||
self.current_nesting_depth -= 1
|
self.current_nesting_depth -= 1
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Generate
|
||||||
op = _choose_option(cutoffs, number_line, options)
|
op = _choose_option(cutoffs, number_line, options)
|
||||||
|
|
||||||
self._generate_expr(comparison, expr_type, op, unary)
|
self._generate_expr(comparison, expr_type, op, unary)
|
||||||
|
|
||||||
|
# Return to parent
|
||||||
self.current_nesting_depth -= 1
|
self.current_nesting_depth -= 1
|
||||||
self.current_ast_element = parent
|
self.current_ast_element = parent
|
||||||
|
|
||||||
def generate_declaration(self, mut=None):
|
def generate_declaration(self, mut=None): # TODO change this to a bool
|
||||||
|
"""
|
||||||
|
@brief Generate a declaration
|
||||||
|
|
||||||
|
@param mut: the mutability of the variable ('const' or 'var')
|
||||||
|
"""
|
||||||
|
# Initialize the variable
|
||||||
parent = self.current_ast_element
|
parent = self.current_ast_element
|
||||||
decl_type = self.get_type(GAZ_VAR_TAG)
|
decl_type = self.get_type(GAZ_VAR_TAG)
|
||||||
decl_args = [
|
decl_args = [
|
||||||
("type", decl_type),
|
("type", decl_type),
|
||||||
]
|
]
|
||||||
element = build_xml_element(decl_args, name=GAZ_DECLARATION_TAG)
|
self.make_element(GAZ_DECLARATION_TAG, decl_args)
|
||||||
self.current_ast_element.append(element)
|
|
||||||
self.current_ast_element = element
|
|
||||||
|
|
||||||
|
# Generate the variable
|
||||||
variable = self.generate_variable(decl_type, mut=mut)
|
variable = self.generate_variable(decl_type, mut=mut)
|
||||||
self.current_ast_element.append(variable.xml)
|
self.current_ast_element.append(variable.xml)
|
||||||
self.current_scope.append(variable.name, variable)
|
self.current_scope.append(variable.name, variable) # make sure the variable is in scope
|
||||||
|
|
||||||
self.generate_xhs(GAZ_RHS_TAG, decl_type) # TODO add real type (decl_type)
|
# Generate the initialization of the variable
|
||||||
|
self.generate_xhs(GAZ_RHS_TAG, decl_type)
|
||||||
|
|
||||||
|
# Return to parent
|
||||||
self.current_ast_element = parent
|
self.current_ast_element = parent
|
||||||
|
|
||||||
def generate_binary(self, op, op_type):
|
def generate_binary(self, op, op_type):
|
||||||
|
"""
|
||||||
|
@brief Generate a binary operation
|
||||||
|
|
||||||
|
@param op: the operator
|
||||||
|
@param op_type: the type of the expression
|
||||||
|
"""
|
||||||
parent = self.current_ast_element
|
parent = self.current_ast_element
|
||||||
|
|
||||||
|
# Check if the operator is valid
|
||||||
if op == "":
|
if op == "":
|
||||||
raise ValueError("op is empty!")
|
raise ValueError("op is empty!")
|
||||||
args = [
|
args = [
|
||||||
("op", op),
|
("op", op),
|
||||||
("type", op_type),
|
("type", op_type),
|
||||||
]
|
]
|
||||||
element = build_xml_element(args, name=GAZ_OPERATOR_TAG)
|
self.make_element(GAZ_OPERATOR_TAG, args)
|
||||||
self.current_ast_element.append(element)
|
|
||||||
self.current_ast_element = element
|
|
||||||
|
|
||||||
|
# Gnereate lhs and rhs
|
||||||
self.generate_xhs(GAZ_LHS_TAG, op_type)
|
self.generate_xhs(GAZ_LHS_TAG, op_type)
|
||||||
self.generate_xhs(GAZ_RHS_TAG, op_type)
|
self.generate_xhs(GAZ_RHS_TAG, op_type)
|
||||||
|
|
||||||
|
# Return to parent
|
||||||
self.current_ast_element = parent
|
self.current_ast_element = parent
|
||||||
|
|
||||||
def generate_bracket(self, op_type):
|
def generate_bracket(self, op_type):
|
||||||
parent = self.current_ast_element
|
"""
|
||||||
args = [
|
@brief Generate a bracket operation
|
||||||
("type", op_type),
|
|
||||||
]
|
|
||||||
element = build_xml_element(args, name=GAZ_BRACKET_TAG)
|
|
||||||
self.current_ast_element.append(element)
|
|
||||||
self.current_ast_element = element
|
|
||||||
|
|
||||||
|
@param op_type: the type of the expression
|
||||||
|
"""
|
||||||
|
parent = self.current_ast_element
|
||||||
|
|
||||||
|
args = [("type", op_type)]
|
||||||
|
self.make_element(GAZ_BRACKET_TAG, args)
|
||||||
|
|
||||||
|
# Generate the expression in the brackets
|
||||||
self.generate_xhs(GAZ_RHS_TAG, op_type)
|
self.generate_xhs(GAZ_RHS_TAG, op_type)
|
||||||
|
|
||||||
|
# Return to parent
|
||||||
self.current_ast_element = parent
|
self.current_ast_element = parent
|
||||||
|
|
||||||
def generate_xhs(self, handedness, op_type, is_zero=False):
|
def generate_xhs(self, handedness, op_type, is_zero=False):
|
||||||
element = build_xml_element([], name=handedness)
|
"""
|
||||||
|
@brief generate a lhs or a rhs depending on handedness
|
||||||
|
|
||||||
|
@param handedness: the handedness
|
||||||
|
@param op_type: the type of the expression
|
||||||
|
@param is_zero: if the expression is zero
|
||||||
|
"""
|
||||||
parent = self.current_ast_element
|
parent = self.current_ast_element
|
||||||
self.current_ast_element.append(element)
|
|
||||||
self.current_ast_element = element
|
self.make_element(handedness, [])
|
||||||
|
|
||||||
self.generate_expression(op_type, is_zero=is_zero)
|
self.generate_expression(op_type, is_zero=is_zero)
|
||||||
|
|
||||||
|
@ -541,6 +544,40 @@ class AstGenerator:
|
||||||
def generate_arg(self):
|
def generate_arg(self):
|
||||||
return Argument(self.get_name(GAZ_VAR_TAG), self.get_type(GAZ_VAR_TAG))
|
return Argument(self.get_name(GAZ_VAR_TAG), self.get_type(GAZ_VAR_TAG))
|
||||||
|
|
||||||
|
def generate_int_expr(self):
|
||||||
|
self._generate_expression([GAZ_INT_KEY],
|
||||||
|
self.int_op_numline,
|
||||||
|
self.int_op_cutoffs,
|
||||||
|
self.int_op_options,
|
||||||
|
self.int_unary)
|
||||||
|
|
||||||
|
def generate_float_expr(self):
|
||||||
|
self._generate_expression([GAZ_FLOAT_KEY, GAZ_INT_KEY],
|
||||||
|
self.float_op_numline,
|
||||||
|
self.float_op_cutoffs,
|
||||||
|
self.float_op_options,
|
||||||
|
self.float_unary)
|
||||||
|
|
||||||
|
def generate_bool_expr(self):
|
||||||
|
self._generate_expression([GAZ_BOOL_KEY],
|
||||||
|
self.bool_op_numline,
|
||||||
|
self.bool_op_cutoffs,
|
||||||
|
self.bool_op_options,
|
||||||
|
self.bool_unary)
|
||||||
|
|
||||||
|
def generate_char_expr(self):
|
||||||
|
self._generate_expression([GAZ_CHAR_KEY],
|
||||||
|
self.char_op_numline,
|
||||||
|
self.char_op_cutoffs,
|
||||||
|
self.char_op_options)
|
||||||
|
|
||||||
|
def generate_comp_expr(self):
|
||||||
|
self._generate_expression([GAZ_BOOL_KEY],
|
||||||
|
self.comp_op_numline,
|
||||||
|
self.comp_op_cutoffs,
|
||||||
|
self.comp_op_options,
|
||||||
|
comparison=True)
|
||||||
|
|
||||||
def push_scope(self, xml_element: ET.Element = None):
|
def push_scope(self, xml_element: ET.Element = None):
|
||||||
scope = Scope(self.current_scope)
|
scope = Scope(self.current_scope)
|
||||||
self.symbol_table.append(scope)
|
self.symbol_table.append(scope)
|
||||||
|
|
|
@ -292,14 +292,20 @@ class TestGeneration(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
lhs = operator.find("lhs")
|
lhs = operator.find("lhs")
|
||||||
rhs = operator.find("rhs")
|
rhs = operator.find("rhs")
|
||||||
if lhs.find("operator") is not None:
|
if lhs is None:
|
||||||
res = self.is_no_op(lhs.find("operator"))
|
if rhs.find("operator") is not None:
|
||||||
elif lhs.find("unary") is not None:
|
res = self.is_no_op(rhs.find("operator"))
|
||||||
res = self.is_no_op(lhs.find("unary"))
|
elif rhs.find("unary") is not None:
|
||||||
elif rhs.find("operator") is not None:
|
res = self.is_no_op(rhs.find("unary"))
|
||||||
res = self.is_no_op(rhs.find("operator"))
|
else:
|
||||||
elif rhs.find("unary") is not None:
|
if lhs.find("operator") is not None:
|
||||||
res = self.is_no_op(lhs.find("unary"))
|
res = self.is_no_op(lhs.find("operator"))
|
||||||
|
elif lhs.find("unary") is not None:
|
||||||
|
res = self.is_no_op(lhs.find("unary"))
|
||||||
|
elif rhs.find("operator") is not None:
|
||||||
|
res = self.is_no_op(rhs.find("operator"))
|
||||||
|
elif rhs.find("unary") is not None:
|
||||||
|
res = self.is_no_op(rhs.find("unary"))
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue