def ml_parse_value(gmls, default=None): """ Parse a value in a macro-language string. """ c = util.skip(gmls, ml_whitepace) sgn = -1 if c == '-' else 1 if c in ('+', '-'): gmls.read(1) c = util.peek(gmls) # don't allow default if sign is given default = None if c == '=': gmls.read(1) c = util.peek(gmls) if len(c) == 0: raise error.RunError(error.IFC) elif ord(c) > 8: name = util.get_var_name(gmls) indices = ml_parse_indices(gmls) step = var.get_var_or_array(name, indices) util.require_read(gmls, (';',), err=error.IFC) else: # varptr$ step = get_value_for_varptrstr(gmls.read(3)) elif c and c in string.digits: step = ml_parse_const(gmls) elif default is not None: step = default else: raise error.RunError(error.IFC) if sgn == -1: step = vartypes.number_neg(step) return step
def ml_parse_value(gmls, default=None): """ Parse a value in a macro-language string. """ c = util.skip(gmls, ml_whitepace) sgn = -1 if c == '-' else 1 if not c: raise error.RunError(error.IFC) if c in ('+', '-'): gmls.read(1) c = util.peek(gmls) # don't allow default if sign is given default = None if c == '=': gmls.read(1) c = util.peek(gmls) if len(c) == 0: raise error.RunError(error.IFC) elif ord(c) > 8: name = util.get_var_name(gmls) indices = ml_parse_indices(gmls) step = var.get_var_or_array(name, indices) util.require_read(gmls, (';',), err=error.IFC) else: # varptr$ step = get_value_for_varptrstr(gmls.read(3)) elif c in representation.ascii_digits: step = ml_parse_const(gmls) elif default is not None: step = default else: raise error.RunError(error.IFC) if sgn == -1: step = vartypes.number_neg(step) return step
def ml_parse_string(gmls): """ Parse a string value in a macro-language string. """ c = util.skip(gmls, ml_whitepace) if len(c) == 0: raise error.RunError(error.IFC) elif ord(c) > 8: name = util.get_var_name(gmls, err=error.IFC) indices = ml_parse_indices(gmls) sub = var.get_var_or_array(name, indices) util.require_read(gmls, (';',), err=error.IFC) return vartypes.pass_string_unpack(sub, err=error.IFC) else: # varptr$ return vartypes.pass_string_unpack(get_value_for_varptrstr(gmls.read(3)))
def ml_parse_string(gmls): """ Parse a string value in a macro-language string. """ c = util.skip(gmls, ml_whitepace) if len(c) == 0: raise error.RunError(error.IFC) elif ord(c) > 8: name = util.get_var_name(gmls) indices = ml_parse_indices(gmls) sub = var.get_var_or_array(name, indices) util.require_read(gmls, (';',), err=error.IFC) return vartypes.pass_string_unpack(sub, err=error.IFC) else: # varptr$ return vartypes.pass_string_unpack(get_value_for_varptrstr(gmls.read(3)))
def parse_expr_unit(ins): """ Compute the value of the expression unit at the current code pointer. """ d = util.skip_white(ins) # string literal if d == '"': ins.read(1) output = bytearray() # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such: # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a # line number afterwards, etc. We follow this. d = ins.read(1) while d not in tk.end_line + ('"',): output += d d = ins.read(1) if d == '\0': ins.seek(-1, 1) return vartypes.pack_string(output) # variable name elif d in string.ascii_uppercase: name, indices = get_var_or_array_name(ins) return var.get_var_or_array(name, indices) # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .) # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers. elif d in string.digits: outs = StringIO() representation.tokenise_number(ins, outs) outs.seek(0) return representation.parse_value(outs) # number literals elif d in tk.number: return representation.parse_value(ins) # gw-basic allows adding line numbers to numbers elif d == tk.T_UINT: return vartypes.pack_int(util.parse_jumpnum(ins)) # brackets elif d == '(': return parse_bracket(ins) # single-byte tokens else: ins.read(1) if d == tk.INPUT: return value_input(ins) elif d == tk.SCREEN: return value_screen(ins) elif d == tk.USR: return value_usr(ins) elif d == tk.FN: return value_fn(ins) elif d == tk.NOT: return value_not(ins) elif d == tk.ERL: return value_erl(ins) elif d == tk.ERR: return value_err(ins) elif d == tk.STRING: return value_string(ins) elif d == tk.INSTR: return value_instr(ins) elif d == tk.VARPTR: return value_varptr(ins) elif d == tk.CSRLIN: return value_csrlin(ins) elif d == tk.POINT: return value_point(ins) elif d == tk.INKEY: return value_inkey(ins) elif d == tk.O_PLUS: return parse_expr_unit(ins) elif d == tk.O_MINUS: return value_neg(ins) # two-byte tokens elif d == '\xFD': d += ins.read(1) if d == tk.CVI: return value_cvi(ins) elif d == tk.CVS: return value_cvs(ins) elif d == tk.CVD: return value_cvd(ins) elif d == tk.MKI: return value_mki(ins) elif d == tk.MKS: return value_mks(ins) elif d == tk.MKD: return value_mkd(ins) elif d == tk.EXTERR: return value_exterr(ins) # two-byte tokens elif d == '\xFE': d += ins.read(1) if d == tk.DATE: return value_date(ins) elif d == tk.TIME: return value_time(ins) elif d == tk.PLAY: return value_play(ins) elif d == tk.TIMER: return value_timer(ins) elif d == tk.ERDEV: return value_erdev(ins) elif d == tk.IOCTL: return value_ioctl(ins) elif d == tk.ENVIRON: return value_environ(ins) elif d == tk.PMAP: return value_pmap(ins) # two-byte tokens elif d == '\xFF': d += ins.read(1) if d == tk.LEFT: return value_left(ins) elif d == tk.RIGHT: return value_right(ins) elif d == tk.MID: return value_mid(ins) elif d == tk.SGN: return value_sgn(ins) elif d == tk.INT: return value_int(ins) elif d == tk.ABS: return value_abs(ins) elif d == tk.SQR: return value_sqr(ins) elif d == tk.RND: return value_rnd(ins) elif d == tk.SIN: return value_sin(ins) elif d == tk.LOG: return value_log(ins) elif d == tk.EXP: return value_exp(ins) elif d == tk.COS: return value_cos(ins) elif d == tk.TAN: return value_tan(ins) elif d == tk.ATN: return value_atn(ins) elif d == tk.FRE: return value_fre(ins) elif d == tk.INP: return value_inp(ins) elif d == tk.POS: return value_pos(ins) elif d == tk.LEN: return value_len(ins) elif d == tk.STR: return value_str(ins) elif d == tk.VAL: return value_val(ins) elif d == tk.ASC: return value_asc(ins) elif d == tk.CHR: return value_chr(ins) elif d == tk.PEEK: return value_peek(ins) elif d == tk.SPACE: return value_space(ins) elif d == tk.OCT: return value_oct(ins) elif d == tk.HEX: return value_hex(ins) elif d == tk.LPOS: return value_lpos(ins) elif d == tk.CINT: return value_cint(ins) elif d == tk.CSNG: return value_csng(ins) elif d == tk.CDBL: return value_cdbl(ins) elif d == tk.FIX: return value_fix(ins) elif d == tk.PEN: return value_pen(ins) elif d == tk.STICK: return value_stick(ins) elif d == tk.STRIG: return value_strig(ins) elif d == tk.EOF: return value_eof(ins) elif d == tk.LOC: return value_loc(ins) elif d == tk.LOF: return value_lof(ins) else: return None
def parse_expr_unit(ins): """ Compute the value of the expression unit at the current code pointer. """ d = util.skip_white(ins) # string literal if d == '"': ins.read(1) output = bytearray() # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such: # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a # line number afterwards, etc. We follow this. d = ins.read(1) while d not in util.end_line + ('"',): output += d d = ins.read(1) if d == '\0': ins.seek(-1, 1) return vartypes.pack_string(output) # variable name elif d >= 'A' and d <= 'Z': name, indices = get_var_or_array_name(ins) return var.get_var_or_array(name, indices) # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .) # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers. elif d >= '0' and d <= '9': outs = StringIO() representation.tokenise_number(ins, outs) outs.seek(0) return util.parse_value(outs) # number literals elif d in token.number: return util.parse_value(ins) # gw-basic allows adding line numbers to numbers elif d == token.T_UINT: return vartypes.pack_int(util.parse_jumpnum(ins)) # brackets elif d == '(': return parse_bracket(ins) # single-byte tokens else: ins.read(1) if d == '\x85': return value_input(ins) elif d == '\xC8': return value_screen(ins) elif d == '\xD0': return value_usr(ins) elif d == '\xD1': return value_fn(ins) elif d == '\xD3': return value_not(ins) elif d == '\xD4': return value_erl(ins) elif d == '\xD5': return value_err(ins) elif d == '\xD6': return value_string(ins) elif d == '\xD8': return value_instr(ins) elif d == '\xDA': return value_varptr(ins) elif d == '\xDB': return value_csrlin(ins) elif d == '\xDC': return value_point(ins) elif d == '\xDE': return value_inkey(ins) elif d == '\xE9': return parse_expr_unit(ins) elif d == '\xEA': return value_neg(ins) # two-byte tokens elif d == '\xFD': d = ins.read(1) if d == '\x81': return value_cvi(ins) elif d =='\x82': return value_cvs(ins) elif d =='\x83': return value_cvd(ins) elif d =='\x84': return value_mki(ins) elif d =='\x85': return value_mks(ins) elif d =='\x86': return value_mkd(ins) elif d == '\x8b': return value_exterr(ins) # two-byte tokens elif d == '\xFE': d = ins.read(1) if d == '\x8D': return value_date(ins) elif d == '\x8E': return value_time(ins) elif d == '\x93': return value_play(ins) elif d == '\x94': return value_timer(ins) elif d == '\x95': return value_erdev(ins) elif d == '\x96': return value_ioctl(ins) elif d == '\x9B': return value_environ(ins) elif d == '\x9E': return value_pmap(ins) # two-byte tokens elif d == '\xFF': d = ins.read(1) if d == '\x81': return value_left(ins) elif d == '\x82': return value_right(ins) elif d == '\x83': return value_mid(ins) elif d == '\x84': return value_sgn(ins) elif d == '\x85': return value_int(ins) elif d == '\x86': return value_abs(ins) elif d == '\x87': return value_sqrt(ins) elif d == '\x88': return value_rnd(ins) elif d == '\x89': return value_sin(ins) elif d == '\x8a': return value_log(ins) elif d == '\x8b': return value_exp(ins) elif d == '\x8c': return value_cos(ins) elif d == '\x8D': return value_tan(ins) elif d == '\x8E': return value_atn(ins) elif d == '\x8F': return value_fre(ins) elif d == '\x90': return value_inp(ins) elif d == '\x91': return value_pos(ins) elif d == '\x92': return value_len(ins) elif d == '\x93': return value_str(ins) elif d == '\x94': return value_val(ins) elif d == '\x95': return value_asc(ins) elif d == '\x96': return value_chr(ins) elif d == '\x97': return value_peek(ins) elif d == '\x98': return value_space(ins) elif d == '\x99': return value_oct(ins) elif d == '\x9A': return value_hex(ins) elif d == '\x9B': return value_lpos(ins) elif d == '\x9C': return value_cint(ins) elif d == '\x9D': return value_csng(ins) elif d == '\x9E': return value_cdbl(ins) elif d == '\x9F': return value_fix(ins) elif d == '\xA0': return value_pen(ins) elif d == '\xA1': return value_stick(ins) elif d == '\xA2': return value_strig(ins) elif d == '\xA3': return value_eof(ins) elif d == '\xA4': return value_loc(ins) elif d == '\xA5': return value_lof(ins) else: return None
def parse_expr_unit(ins): """ Compute the value of the expression unit at the current code pointer. """ d = util.skip_white(ins) # string literal if d == '"': ins.read(1) output = bytearray() # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such: # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a # line number afterwards, etc. We follow this. d = ins.read(1) while d not in tk.end_line + ('"', ): output += d d = ins.read(1) if d == '\0': ins.seek(-1, 1) return vartypes.pack_string(output) # variable name elif d in string.ascii_uppercase: name, indices = get_var_or_array_name(ins) return var.get_var_or_array(name, indices) # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .) # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers. elif d in string.digits: outs = StringIO() representation.tokenise_number(ins, outs) outs.seek(0) return representation.parse_value(outs) # number literals elif d in tk.number: return representation.parse_value(ins) # gw-basic allows adding line numbers to numbers elif d == tk.T_UINT: return vartypes.pack_int(util.parse_jumpnum(ins)) # brackets elif d == '(': return parse_bracket(ins) # single-byte tokens else: ins.read(1) if d == tk.INPUT: return value_input(ins) elif d == tk.SCREEN: return value_screen(ins) elif d == tk.USR: return value_usr(ins) elif d == tk.FN: return value_fn(ins) elif d == tk.NOT: return value_not(ins) elif d == tk.ERL: return value_erl(ins) elif d == tk.ERR: return value_err(ins) elif d == tk.STRING: return value_string(ins) elif d == tk.INSTR: return value_instr(ins) elif d == tk.VARPTR: return value_varptr(ins) elif d == tk.CSRLIN: return value_csrlin(ins) elif d == tk.POINT: return value_point(ins) elif d == tk.INKEY: return value_inkey(ins) elif d == tk.O_PLUS: return parse_expr_unit(ins) elif d == tk.O_MINUS: return value_neg(ins) # two-byte tokens elif d == '\xFD': d += ins.read(1) if d == tk.CVI: return value_cvi(ins) elif d == tk.CVS: return value_cvs(ins) elif d == tk.CVD: return value_cvd(ins) elif d == tk.MKI: return value_mki(ins) elif d == tk.MKS: return value_mks(ins) elif d == tk.MKD: return value_mkd(ins) elif d == tk.EXTERR: return value_exterr(ins) # two-byte tokens elif d == '\xFE': d += ins.read(1) if d == tk.DATE: return value_date(ins) elif d == tk.TIME: return value_time(ins) elif d == tk.PLAY: return value_play(ins) elif d == tk.TIMER: return value_timer(ins) elif d == tk.ERDEV: return value_erdev(ins) elif d == tk.IOCTL: return value_ioctl(ins) elif d == tk.ENVIRON: return value_environ(ins) elif d == tk.PMAP: return value_pmap(ins) # two-byte tokens elif d == '\xFF': d += ins.read(1) if d == tk.LEFT: return value_left(ins) elif d == tk.RIGHT: return value_right(ins) elif d == tk.MID: return value_mid(ins) elif d == tk.SGN: return value_sgn(ins) elif d == tk.INT: return value_int(ins) elif d == tk.ABS: return value_abs(ins) elif d == tk.SQR: return value_sqr(ins) elif d == tk.RND: return value_rnd(ins) elif d == tk.SIN: return value_sin(ins) elif d == tk.LOG: return value_log(ins) elif d == tk.EXP: return value_exp(ins) elif d == tk.COS: return value_cos(ins) elif d == tk.TAN: return value_tan(ins) elif d == tk.ATN: return value_atn(ins) elif d == tk.FRE: return value_fre(ins) elif d == tk.INP: return value_inp(ins) elif d == tk.POS: return value_pos(ins) elif d == tk.LEN: return value_len(ins) elif d == tk.STR: return value_str(ins) elif d == tk.VAL: return value_val(ins) elif d == tk.ASC: return value_asc(ins) elif d == tk.CHR: return value_chr(ins) elif d == tk.PEEK: return value_peek(ins) elif d == tk.SPACE: return value_space(ins) elif d == tk.OCT: return value_oct(ins) elif d == tk.HEX: return value_hex(ins) elif d == tk.LPOS: return value_lpos(ins) elif d == tk.CINT: return value_cint(ins) elif d == tk.CSNG: return value_csng(ins) elif d == tk.CDBL: return value_cdbl(ins) elif d == tk.FIX: return value_fix(ins) elif d == tk.PEN: return value_pen(ins) elif d == tk.STICK: return value_stick(ins) elif d == tk.STRIG: return value_strig(ins) elif d == tk.EOF: return value_eof(ins) elif d == tk.LOC: return value_loc(ins) elif d == tk.LOF: return value_lof(ins) else: return None