class RValueIntLiteral: RValue;
class RValueFloatLiteral: RValue;
class RValueStrLiteral: RValue;
-class RValueVariable: RValue;
class RValueStrDollar: RValue;
class RValueVal: RValue;
+class LValue: RValue;
+class LValueVariable: LValue;
%%
raise NotImplementedError()
@method(StatementLet)
def execute(self, context):
- name = self.children[0].str_value
- if name[-1] == '$':
- value = self.children[1].get_str(context)
- else:
- value = self.children[1].get_float(context)
- if name[-1] == '$':
- value = data_types.cint(value)
- context.find_variable(name).value = value
+ value = self.children[1].get(context)
+ self.children[0].set(context, value)
@method(StatementPrint)
def execute(self, context):
for i in self.children:
@method(StatementFor)
def execute(self, context):
name = self.children[0].str_value
- if name[-1] == '$':
+ # note: if the loop index is an integer, we will print a type
+ # mismatch error, whereas applesoft would print a syntax error
+ if name[-1] in '$%':
raise Exception(
f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
)
- if name[-1] == '%':
- raise Exception(
- f'?SYNTAX ERROR IN {context.line_number():d}'
- )
variable = context.find_variable(name)
variable.value = self.children[1].get_float(context)
context.m < len(statement.children)
):
item = statement.children[context.m]
+ self.children[0].set_val(context, element.to_text(item))
context.m += 1
- break
+ return
context.l += 1
context.m = 0
- else:
- context.k += 1
- context.l = 1
- assert context.m == 0
- continue
- break
- else:
- raise Exception(
- f'?OUT OF DATA ERROR IN {context.line_number():d}'
- )
+ context.k += 1
+ context.l = 1
+ assert context.m == 0
+ raise Exception(
+ f'?OUT OF DATA ERROR IN {context.line_number():d}'
+ )
- name = self.children[0].str_value
- if name[-1] == '$':
- if not isinstance(item, StrLiteral):
- raise Exception(
- f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
- )
- value = item.text[0]
- else:
- if isinstance(item, IntLiteral):
- value = float(item.int_value)
- elif isinstance(item, FloatLiteral):
- value = item.float_value
- else:
- raise Exception(
- f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
- )
- if name[-1] == '%':
- value = data_types.cint(value)
- context.find_variable(name).value = value
@method(StatementRestore)
def execute(self, context):
context.k = (
apple_io.vtab(data_types.cint(value))
@method(StatementGet)
def execute(self, context):
- name = self.children[0].str_value
value = apple_io.get()
- if name[-1] != '$':
- raise Exception(
- f'?SYNTAX ERROR IN {context.line_number():d}'
- )
- context.find_variable(name).value = value
+ # note: if the lvalue isn't a string then we will print a type
+ # mismatch error, whereas applesoft would print a syntax error
+ self.children[0].set(context, value)
@method(StatementInput)
def execute(self, context):
apple_io._print(
if len(self.children) >= 2 else
'?'
)
- name = self.children[-1].str_value
value = apple_io.input()
- if name[-1] != '$':
- value = data_types.val(value)
- if name[-1] == '%':
- value = data_types.cint(value)
- context.find_variable(name).value = value
+ self.children[-1].set_val(context, value)
del execute
@method(RValue)
@method(RValueStrLiteral)
def get(self, context):
return self.children[0].text[0]
-@method(RValueVariable)
-def get(self, context):
- name = self.children[0].str_value
- return context.find_variable(name).value
@method(RValueStrDollar)
def get(self, context):
value = self.children[0].get_float(context)
def get(self, context):
value = self.children[0].get_str(context)
return data_types.val(value)
+@method(LValue)
+def get(self, context):
+ value = self.find_variable(context).value
+ name = self.children[0].str_value
+ if name[-1] == '%':
+ value = float(value)
+ return value
del get
@method(RValue)
)
return value
del get_str
+
+@method(LValue)
+def find_variable(self, context):
+ raise NotImplementedError()
+@method(LValueVariable)
+def find_variable(self, context):
+ name = self.children[0].str_value
+ return context.find_variable(name)
+del find_variable
+
+@method(LValue)
+def set(self, context, value):
+ name = self.children[0].str_value
+ if name[-1] == '$':
+ if not isinstance(value, str):
+ raise Exception(
+ f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
+ )
+ else:
+ if not isinstance(value, float):
+ raise Exception(
+ f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
+ )
+ if name[-1] == '%':
+ value = data_types.cint(value)
+ self.find_variable(context).value = value
+del set
+
+@method(LValue)
+def set_val(self, context, value):
+ assert isinstance(value, str)
+ name = self.children[0].str_value
+ if name[-1] != '$':
+ value = data_types.val(value)
+ if name[-1] == '%':
+ value = data_types.cint(value)
+ self.find_variable(context).value = value
+del set_val
statement_opt
:
- | %space (?E{t_def.StatementLet}VARIABLE_NAME '=' expression)
- | %space (?E{t_def.StatementLet}KEYWORD_LET VARIABLE_NAME '=' expression)
+ | %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.StatementGoto}KEYWORD_GOTO INT_LITERAL)
| %space (?E{t_def.StatementFor}KEYWORD_FOR VARIABLE_NAME '=' expression KEYWORD_TO expression KEYWORD_STEP expression)
| %space (?E{t_def.StatementNext}KEYWORD_NEXT)
| %space (?E{t_def.StatementNext}KEYWORD_NEXT VARIABLE_NAME)
- | %space (?E{t_def.StatementRead}KEYWORD_READ VARIABLE_NAME)
+ | %space (?E{t_def.StatementRead}KEYWORD_READ %space (?E{t_def.LValueVariable}VARIABLE_NAME) )
| %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.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 VARIABLE_NAME)
- | %space (?E{t_def.StatementInput}KEYWORD_INPUT VARIABLE_NAME)
- | %space (?E{t_def.StatementInput}KEYWORD_INPUT STR_LITERAL ';' VARIABLE_NAME)
+ | %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) )
;
print_expression_list0
| %space (?E{t_def.RValueIntLiteral}INT_LITERAL)
| %space (?E{t_def.RValueFloatLiteral}FLOAT_LITERAL)
| %space (?E{t_def.RValueStrLiteral}STR_LITERAL)
- | %space (?E{t_def.RValueVariable}VARIABLE_NAME)
+ | %space (?E{t_def.LValueVariable}VARIABLE_NAME)
| %space (?E{t_def.RValueStrDollar}KEYWORD_STR_DOLLAR '(' expression ')')
| %space (?E{t_def.RValueVal}KEYWORD_VAL '(' expression ')')
;