class StatementVTab: Statement;
class StatementGet: Statement;
class StatementInput: Statement;
+class StatementDim: Statement;
class RValue: Node;
class RValueOr: RValue;
class RValueAnd: RValue;
class RValueVal: RValue;
class LValue: RValue;
class LValueVariable: LValue;
+class LValueArray: LValue;
%%
self,
program = None,
variables = None,
+ arrays = None,
i = 0,
j = 1,
k = 0,
):
self.program = program if program is not None else Program()
self.variables = variables if variables is not None else {}
+ self.arrays = arrays if arrays is not None else {}
# execute pointer (line index, statement index)
self.i = i
# variable is created and initialized to 0 if not existent
variable = self.variables.get(name)
if variable is None:
- variable = Variable(
- '' if name[-1] == '$' else 0 if name[-1] == '%' else 0.
- )
+ null_value = '' if name[-1] == '$' else 0 if name[-1] == '%' else 0.
+ variable = Variable(null_value)
self.variables[name] = variable
return variable
+ def find_array(self, name):
+ # array is created and initialized to 11 0s if not existent
+ array = self.arrays.get(name)
+ if array is None:
+ null_value = '' if name[-1] == '$' else 0 if name[-1] == '%' else 0.
+ array = [Variable(null_value) for i in range(11)]
+ self.arrays[name] = array
+ return array
+
def factory(tag, *args, **kwargs):
return tag_to_class[tag](*args, **kwargs)
)
value = apple_io.input()
self.children[-1].set_val(context, value)
+@method(StatementDim)
+def execute(self, context):
+ dim = [
+ data_types.cint(i.get_float(context)) + 1
+ for i in self.children[1:]
+ ]
+
+ # we don't check for an existing array until here, as it could be
+ # created with the default 11 elements while evaluating dimensions
+ name = self.children[0].str_value
+ if name in context.arrays:
+ raise Exception(
+ f'?REDIM\'D ARRAY ERROR IN {context.line_number():d}'
+ )
+
+ null_value = '' if name[-1] == '$' else 0 if name[-1] == '%' else 0.
+ def create_array(i):
+ return (
+ Variable(null_value)
+ if i >= len(dim) else
+ [create_array(i + 1) for j in range(dim[i])]
+ )
+ context.arrays[name] = create_array(0)
del execute
@method(RValue)
def find_variable(self, context):
name = self.children[0].str_value
return context.find_variable(name)
+@method(LValueArray)
+def find_variable(self, context):
+ name = self.children[0].str_value
+ variable = context.find_array(name)
+ for i in self.children[1:]:
+ if not isinstance(variable, list):
+ # too many subscripts
+ raise Exception(
+ f'?BAD SUBSCRIPT ERROR IN {context.line_number():d}'
+ )
+ index = data_types.cint(i.get_float(context))
+ if index < 0 or index >= len(variable):
+ raise Exception(
+ f'?BAD SUBSCRIPT ERROR IN {context.line_number():d}'
+ )
+ variable = variable[index]
+ if not isinstance(variable, Variable):
+ # not enough subscripts
+ raise Exception(
+ f'?BAD SUBSCRIPT ERROR IN {context.line_number():d}'
+ )
+ return variable
del find_variable
@method(LValue)
statement_opt
:
- | %space (?E{t_def.StatementLet}(?E{t_def.LValueVariable}VARIABLE_NAME) '=' expression)
- | %space (?E{t_def.StatementLet}KEYWORD_LET %space (?E{t_def.LValueVariable}VARIABLE_NAME) '=' expression)
- | %space (?E{t_def.StatementPrint, semicolon = False}KEYWORD_PRINT print_expression_list0)
- | %space (?E{t_def.StatementPrint, semicolon = True}KEYWORD_PRINT print_expression_list1)
+ | %space (?E{t_def.StatementLet}lvalue '=' rvalue)
+ | %space (?E{t_def.StatementLet}KEYWORD_LET lvalue '=' rvalue)
+ | %space (?E{t_def.StatementPrint, semicolon = False}KEYWORD_PRINT print_rvalue_list0)
+ | %space (?E{t_def.StatementPrint, semicolon = True}KEYWORD_PRINT print_rvalue_list1)
| %space (?E{t_def.StatementGoto}KEYWORD_GOTO INT_LITERAL)
- | %space (?E{t_def.StatementIf}KEYWORD_IF expression KEYWORD_THEN) statement_opt
- | %space (?E{t_def.StatementIf}KEYWORD_IF expression KEYWORD_THEN) %space (?E{t_def.StatementGoto}INT_LITERAL)
+ | %space (?E{t_def.StatementIf}KEYWORD_IF rvalue KEYWORD_THEN) statement_opt
+ | %space (?E{t_def.StatementIf}KEYWORD_IF rvalue KEYWORD_THEN) %space (?E{t_def.StatementGoto}INT_LITERAL)
| %space (?E{t_def.StatementEnd}KEYWORD_END)
| %space (?E{t_def.StatementGosub}KEYWORD_GOSUB INT_LITERAL)
| %space (?E{t_def.StatementReturn}KEYWORD_RETURN)
- | %space (?E{t_def.StatementFor}KEYWORD_FOR VARIABLE_NAME '=' expression KEYWORD_TO expression)
- | %space (?E{t_def.StatementFor}KEYWORD_FOR VARIABLE_NAME '=' expression KEYWORD_TO expression KEYWORD_STEP expression)
+ | %space (?E{t_def.StatementFor}KEYWORD_FOR VARIABLE_NAME '=' rvalue KEYWORD_TO rvalue)
+ | %space (?E{t_def.StatementFor}KEYWORD_FOR VARIABLE_NAME '=' rvalue KEYWORD_TO rvalue KEYWORD_STEP rvalue)
| %space (?E{t_def.StatementNext}KEYWORD_NEXT)
| %space (?E{t_def.StatementNext}KEYWORD_NEXT VARIABLE_NAME)
- | %space (?E{t_def.StatementRead}KEYWORD_READ %space (?E{t_def.LValueVariable}VARIABLE_NAME) )
+ | %space (?E{t_def.StatementRead}KEYWORD_READ lvalue)
| %space (?E{t_def.StatementRestore}KEYWORD_RESTORE INT_LITERAL)
| %space (?E{t_def.StatementData}KEYWORD_DATA data_item_list)
| %space (?E{t_def.StatementHome}KEYWORD_HOME)
| %space (?E{t_def.StatementNormal}KEYWORD_NORMAL)
| %space (?E{t_def.StatementInverse}KEYWORD_INVERSE)
| %space (?E{t_def.StatementFlash}KEYWORD_FLASH)
- | %space (?E{t_def.StatementHTab}KEYWORD_HTAB expression)
- | %space (?E{t_def.StatementVTab}KEYWORD_VTAB expression)
- | %space (?E{t_def.StatementGet}KEYWORD_GET %space (?E{t_def.LValueVariable}VARIABLE_NAME) )
- | %space (?E{t_def.StatementInput}KEYWORD_INPUT %space (?E{t_def.LValueVariable}VARIABLE_NAME) )
- | %space (?E{t_def.StatementInput}KEYWORD_INPUT STR_LITERAL ';' %space (?E{t_def.LValueVariable}VARIABLE_NAME) )
+ | %space (?E{t_def.StatementHTab}KEYWORD_HTAB rvalue)
+ | %space (?E{t_def.StatementVTab}KEYWORD_VTAB rvalue)
+ | %space (?E{t_def.StatementGet}KEYWORD_GET lvalue)
+ | %space (?E{t_def.StatementInput}KEYWORD_INPUT lvalue)
+ | %space (?E{t_def.StatementInput}KEYWORD_INPUT STR_LITERAL ';' lvalue)
+ | %space (?E{t_def.StatementDim}KEYWORD_DIM VARIABLE_NAME '(' rvalue_list ')')
;
-print_expression_list0
+print_rvalue_list0
:
- | print_expression_list0 expression
- | print_expression_list1 expression
+ | print_rvalue_list0 rvalue
+ | print_rvalue_list1 rvalue
;
-print_expression_list1
- : print_expression_list0 ';'
- | print_expression_list1 ';'
+print_rvalue_list1
+ : print_rvalue_list0 ';'
+ | print_rvalue_list1 ';'
;
data_item_list
| STR_LITERAL
;
-expression
- : %space (?E{t_def.RValueOr}expression KEYWORD_OR expression)
- | %space (?E{t_def.RValueAnd}expression KEYWORD_AND expression)
- | %space (?E{t_def.RValueLT}expression '<' expression)
- | %space (?E{t_def.RValueEqual}expression '=' expression)
- | %space (?E{t_def.RValueGT}expression '>' expression)
- | %space (?E{t_def.RValueGE}expression OPERATOR_GE expression)
- | %space (?E{t_def.RValueLE}expression OPERATOR_LE expression)
- | %space (?E{t_def.RValueNE}expression OPERATOR_NE expression)
- | %space (?E{t_def.RValueAdd}expression '+' expression)
- | %space (?E{t_def.RValueSubtract}expression '-' expression)
- | %space (?E{t_def.RValueMultiply}expression '*' expression)
- | %space (?E{t_def.RValueDivide}expression '/' expression)
- | %space (?E{t_def.RValuePower}expression '^' expression)
- | %space (?E{t_def.RValueSign, sign = -1}'-' expression) %prec UNARY
- | %space (?E{t_def.RValueSign, sign = 1}'+' expression) %prec UNARY
- | %space (?E{t_def.RValueNot}KEYWORD_NOT expression)
- | '(' expression ')'
- | %space (?E{t_def.RValueIntLiteral}INT_LITERAL)
- | %space (?E{t_def.RValueFloatLiteral}FLOAT_LITERAL)
+rvalue_list
+ : rvalue
+ | rvalue_list ',' rvalue
+ ;
+
+rvalue
+ : lvalue
+ | '(' rvalue ')'
| %space (?E{t_def.RValueStrLiteral}STR_LITERAL)
- | %space (?E{t_def.LValueVariable}VARIABLE_NAME)
- | %space (?E{t_def.RValueStrDollar}KEYWORD_STR_DOLLAR '(' expression ')')
- | %space (?E{t_def.RValueVal}KEYWORD_VAL '(' expression ')')
+ | %space (?E{t_def.RValueFloatLiteral}FLOAT_LITERAL)
+ | %space (?E{t_def.RValueIntLiteral}INT_LITERAL)
+ | %space (?E{t_def.RValueNot}KEYWORD_NOT rvalue)
+ | %space (?E{t_def.RValueSign, sign = 1}'+' rvalue) %prec UNARY
+ | %space (?E{t_def.RValueSign, sign = -1}'-' rvalue) %prec UNARY
+ | %space (?E{t_def.RValuePower}rvalue '^' rvalue)
+ | %space (?E{t_def.RValueDivide}rvalue '/' rvalue)
+ | %space (?E{t_def.RValueMultiply}rvalue '*' rvalue)
+ | %space (?E{t_def.RValueSubtract}rvalue '-' rvalue)
+ | %space (?E{t_def.RValueAdd}rvalue '+' rvalue)
+ | %space (?E{t_def.RValueNE}rvalue OPERATOR_NE rvalue)
+ | %space (?E{t_def.RValueLE}rvalue OPERATOR_LE rvalue)
+ | %space (?E{t_def.RValueGE}rvalue OPERATOR_GE rvalue)
+ | %space (?E{t_def.RValueGT}rvalue '>' rvalue)
+ | %space (?E{t_def.RValueEqual}rvalue '=' rvalue)
+ | %space (?E{t_def.RValueLT}rvalue '<' rvalue)
+ | %space (?E{t_def.RValueAnd}rvalue KEYWORD_AND rvalue)
+ | %space (?E{t_def.RValueOr}rvalue KEYWORD_OR rvalue)
+ | %space (?E{t_def.RValueStrDollar}KEYWORD_STR_DOLLAR '(' rvalue ')')
+ | %space (?E{t_def.RValueVal}KEYWORD_VAL '(' rvalue ')')
;
+
+lvalue
+ : %space (?E{t_def.LValueVariable}VARIABLE_NAME)
+ | %space (?E{t_def.LValueArray}VARIABLE_NAME '(' rvalue_list ')')
+ ;
%%
def yyerror(s):