diff --git a/erlang/apps/as/src/parse.erl b/erlang/apps/as/src/parse.erl index f950a2b..9f7fd81 100644 --- a/erlang/apps/as/src/parse.erl +++ b/erlang/apps/as/src/parse.erl @@ -43,11 +43,11 @@ stmt(ScanState) -> {ok, {_Location, ?T_DOT_SUBSECTION}} -> dot_subsection(ScanState); {ok, {_Location, ?T_DOT_TEXT}} -> dot_text(ScanState); {ok, {_Location, ?T_DOT_TYPE}} -> dot_type(ScanState); - {ok, {_Location, {?T_SYMBOL, Name}}} -> stmt_after_symbol(ScanState, Name); + {ok, {Location, {?T_SYMBOL, Name}}} -> stmt_after_symbol(ScanState, Location, Name); {ok, {_Location, {?T_UINTEGER, UInt}}} -> stmt_after_uinteger(ScanState, UInt); {ok, {_Location, ?T_NEWLINE}} -> stmt(ScanState); {ok, {_Location, ?T_EOF}} -> eof; - ScanRes -> badtok(ScanState, "expected directive, label, or instruction", ScanRes) + ScanRes -> badtok("expected directive, label, or instruction", ScanRes) end. %% Instructions and labels ----------------------------------------------------- @@ -94,120 +94,120 @@ stmt(ScanState) -> %% This means that "opcode (...)" is interpreted as having a displacement but no %% index. Use "opcode 0(index)" if an index with zero displacement is needed. -stmt_after_symbol(ScanState, Name) -> +stmt_after_symbol(ScanState, Location, Name) -> case scan:token(ScanState) of {ok, {_Location, ?T_COLON}} -> {ok, #s_label{name = Name}}; - {ok, {_Location, ?T_NEWLINE}} -> make_insn(ScanState, Name, false, false, false, false); - {ok, {_Location, {?T_UINTEGER, UInt}}} -> insn_uint(ScanState, Name, UInt); - {ok, {_Location, {?T_SYMBOL, Symbol}}} -> insn_symbol(ScanState, Name, Symbol); + {ok, {_Location, ?T_NEWLINE}} -> make_insn(Location, Name, false, false, false, false); + {ok, {_Location, {?T_UINTEGER, UInt}}} -> insn_uint(ScanState, Location, Name, UInt); + {ok, {_Location, {?T_SYMBOL, Symbol}}} -> insn_symbol(ScanState, Location, Name, Symbol); {ok, {_Location, {?T_LOCAL_LABEL, Number, Direction}}} -> - insn_local_label(ScanState, Name, Number, Direction); - ScanRes -> badtok(ScanState, "junk after symbol", ScanRes) + insn_local_label(ScanState, Location, Name, Number, Direction); + ScanRes -> badtok("junk after symbol", ScanRes) end. %% ::= . ":" stmt_after_uinteger(ScanState, UInt) -> case scan:token(ScanState) of {ok, {_Location, ?T_COLON}} -> {ok, #s_local_label{number = UInt}}; - ScanRes -> badtok(ScanState, "junk after symbol", ScanRes) + ScanRes -> badtok("junk after symbol", ScanRes) end. %% Seen " ". The is the if followed %% by ",", otherwise (the start of) the . -insn_uint(ScanState, Name, UInt) -> +insn_uint(ScanState, Location, Name, UInt) -> case scan:token(ScanState) of {ok, {_Location, ?T_COMMA}} -> % the Uint is the Accumulator, parse EA next - insn_ea(ScanState, Name, _AccOrDev = UInt); + insn_ea(ScanState, Location, Name, _AccOrDev = UInt); {ok, {_Location, ?T_LPAREN}} -> % the Uint is the Displacement, parse Index next Displacement = #e_integer{value = UInt}, - insn_ea_index(ScanState, Name, _AccOrDev = false, _At = false, Displacement); + insn_ea_index(ScanState, Location, Name, _AccOrDev = false, _At = false, Displacement); {ok, {_Location, ?T_NEWLINE}} -> % the Uint is the Displacement Displacement = #e_integer{value = UInt}, - make_insn(ScanState, Name, _AccOrDev = false, _At = false, Displacement, _Index = false); - ScanRes -> badtok(ScanState, "junk after ", ScanRes) + make_insn(Location, Name, _AccOrDev = false, _At = false, Displacement, _Index = false); + ScanRes -> badtok("junk after ", ScanRes) end. %% Seen " ". The is (the start of) the . %% TODO: permit to be the (named register or device). -insn_symbol(ScanState, Name, Symbol2) -> +insn_symbol(ScanState, Location, Name, Symbol2) -> Displacement = #e_symbol{name = Symbol2}, - insn_ea_disp(ScanState, Name, _AccOrDev = false, _At = false, Displacement). + insn_ea_disp(ScanState, Location, Name, _AccOrDev = false, _At = false, Displacement). %% Seen " ". The is (the start of) the . -insn_local_label(ScanState, Name, Number, Direction) -> +insn_local_label(ScanState, Location, Name, Number, Direction) -> Displacement = #e_local_label{number = Number, direction = Direction}, - insn_ea_disp(ScanState, Name, _AccOrDev = false, _At = false, Displacement). + insn_ea_disp(ScanState, Location, Name, _AccOrDev = false, _At = false, Displacement). %% "," . [ ["@"] ["(" ")"] ] -insn_ea(ScanState, Name, AccOrDev) -> +insn_ea(ScanState, Location, Name, AccOrDev) -> case scan:token(ScanState) of {ok, {_Location, ?T_NEWLINE}} -> - make_insn(ScanState, Name, AccOrDev, _At = false, _Displacement = false, _Index = false); - {ok, {_Location, ?T_AT}} -> insn_ea_at(ScanState, Name, AccOrDev); + make_insn(Location, Name, AccOrDev, _At = false, _Displacement = false, _Index = false); + {ok, {_Location, ?T_AT}} -> insn_ea_at(ScanState, Location, Name, AccOrDev); {ok, {_Lcation, {?T_UINTEGER, UInt}}} -> Displacement = #e_integer{value = UInt}, - insn_ea_disp(ScanState, Name, AccOrDev, _At = false, Displacement); + insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = false, Displacement); {ok, {_Location, {?T_SYMBOL, Symbol}}} -> Displacement = #e_symbol{name = Symbol}, - insn_ea_disp(ScanState, Name, AccOrDev, _At = false, Displacement); + insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = false, Displacement); {ok, {_Location, {?T_LOCAL_LABEL, Number, Direction}}} -> Displacement = #e_local_label{number = Number, direction = Direction}, - insn_ea_disp(ScanState, Name, AccOrDev, _At = false, Displacement); - ScanRes -> badtok(ScanState, "junk after comma", ScanRes) + insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = false, Displacement); + ScanRes -> badtok("junk after comma", ScanRes) end. %% [ ","] "@" . ["(" ")"] -insn_ea_at(ScanState, Name, AccOrDev) -> +insn_ea_at(ScanState, Location, Name, AccOrDev) -> case scan:token(ScanState) of {ok, {_Location, {?T_UINTEGER, UInt}}} -> Displacement = #e_integer{value = UInt}, - insn_ea_disp(ScanState, Name, AccOrDev, _At = true, Displacement); + insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = true, Displacement); {ok, {_Location, {?T_SYMBOL, Symbol}}} -> Displacement = #e_symbol{name = Symbol}, - insn_ea_disp(ScanState, Name, AccOrDev, _At = true, Displacement); + insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = true, Displacement); {ok, {_Location, {?T_LOCAL_LABEL, Number, Direction}}} -> Displacement = #e_local_label{number = Number, direction = Direction}, - insn_ea_disp(ScanState, Name, AccOrDev, _At = true, Displacement); - ScanRes -> badtok(ScanState, "junk after @", ScanRes) + insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = true, Displacement); + ScanRes -> badtok("junk after @", ScanRes) end. %% [ ","] ["@"] . ["(" ")"] -insn_ea_disp(ScanState, Name, AccOrDev, At, Displacement) -> +insn_ea_disp(ScanState, Location, Name, AccOrDev, At, Displacement) -> case scan:token(ScanState) of - {ok, {_Location, ?T_LPAREN}} -> insn_ea_index(ScanState, Name, AccOrDev, At, Displacement); - {ok, {_Location, ?T_NEWLINE}} -> make_insn(ScanState, Name, AccOrDev, At, Displacement, _Index = false); - ScanRes -> badtok(ScanState, "junk after ", ScanRes) + {ok, {_Location, ?T_LPAREN}} -> insn_ea_index(ScanState, Location, Name, AccOrDev, At, Displacement); + {ok, {_Location, ?T_NEWLINE}} -> make_insn(Location, Name, AccOrDev, At, Displacement, _Index = false); + ScanRes -> badtok("junk after ", ScanRes) end. %% [ ","] ["@"] "(" . ")" -insn_ea_index(ScanState, Name, AccOrDev, At, Displacement) -> +insn_ea_index(ScanState, Location, Name, AccOrDev, At, Displacement) -> case scan:token(ScanState) of {ok, {_Location1, {?T_UINTEGER, Index}}} when Index =< 8#17 -> case scan:token(ScanState) of {ok, {_Location2, ?T_RPAREN}} -> case scan:token(ScanState) of {ok, {_Location3, ?T_NEWLINE}} -> - make_insn(ScanState, Name, AccOrDev, At, Displacement, Index); - ScanRes -> badtok(ScanState, "junk after ", ScanRes) + make_insn(Location, Name, AccOrDev, At, Displacement, Index); + ScanRes -> badtok("junk after ", ScanRes) end; - ScanRes -> badtok(ScanState, "junk in ", ScanRes) + ScanRes -> badtok("junk in ", ScanRes) end; - ScanRes -> badtok(ScanState, "junk in ", ScanRes) + ScanRes -> badtok("junk in ", ScanRes) end. -make_insn(ScanState, Name, AccOrDev, At, Displacement, Index) -> +make_insn(Location, Name, AccOrDev, At, Displacement, Index) -> Models = ?PDP10_KL10_271, % FIXME: make dynamic case pdp10_opcodes:insn_from_name(Models, Name, AccOrDev =/= false) of - false -> badinsn(ScanState, "invalid mnemonic ~s", Name); + false -> badinsn(Location, "invalid mnemonic ~s", Name); #pdp10_insn_desc{ high13 = High13 , format = Format , e_unused = EUnused , extended = false % TODO: handle extended opcodes } -> - case make_high13(ScanState, Name, AccOrDev, High13, Format) of + case make_high13(Location, Name, AccOrDev, High13, Format) of {error, _Reason} = Error -> Error; {ok, FinalHigh13} -> - case check_e(ScanState, Name, At, Displacement, Index, EUnused) of + case check_e(Location, Name, At, Displacement, Index, EUnused) of {error, _Reason} = Error -> Error; ok -> {ok, #s_insn{ high13 = FinalHigh13 , at = At @@ -221,14 +221,14 @@ make_insn(ScanState, Name, AccOrDev, At, Displacement, Index) -> end end. -make_high13(ScanState, Name, AccOrDev, High13, Format) -> +make_high13(Location, Name, AccOrDev, High13, Format) -> case {Format, AccOrDev} of {?PDP10_INSN_A_OPCODE, false} -> {ok, High13}; {?PDP10_INSN_A_OPCODE, _} -> - badinsn(ScanState, "~s: extraneous accumulator operand", Name); + badinsn(Location, "~s: extraneous accumulator operand", Name); {?PDP10_INSN_IO, false} -> - badinsn(ScanState, "~s: missing device operand", Name); + badinsn(Location, "~s: missing device operand", Name); {?PDP10_INSN_IO, _} -> make_high13_io(High13, AccOrDev); {?PDP10_INSN_BASIC, false} -> @@ -236,9 +236,9 @@ make_high13(ScanState, Name, AccOrDev, High13, Format) -> {?PDP10_INSN_BASIC, _} -> make_high13_basic(High13, AccOrDev); {?PDP10_INSN_A_NONZERO, false} -> - badinsn(ScanState, "~s: missing accumulator operand", Name); + badinsn(Location, "~s: missing accumulator operand", Name); {?PDP10_INSN_A_NONZERO, 0} -> - badinsn(ScanState, "~s: accumulator must not be zero", Name); + badinsn(Location, "~s: accumulator must not be zero", Name); {?PDP10_INSN_A_NONZERO, _} -> make_high13_basic(High13, AccOrDev) end. @@ -251,17 +251,17 @@ make_high13_io(High13, Device) -> Mask = ((1 bsl 7) - 1), {ok, (High13 band bnot (Mask bsl 3)) bor ((Device band Mask) bsl 3)}. -check_e(ScanState, Name, At, Displacement, Index, EUnused) -> +check_e(Location, Name, At, Displacement, Index, EUnused) -> HaveE = At orelse Displacement =/= false orelse Index =/= false, case {EUnused, HaveE} of {true, false} -> ok; - {true, true} -> badinsn(ScanState, "~s: extraneous address operand", Name); - {false, false} -> badinsn(ScanState, "~s: missing address operand", Name); + {true, true} -> badinsn(Location, "~s: extraneous address operand", Name); + {false, false} -> badinsn(Location, "~s: missing address operand", Name); {false, true} -> ok end. -badinsn(ScanState, Fmt, Mnemonic) -> - fmterr(ScanState, Fmt, [Mnemonic]). +badinsn(Location, Fmt, Mnemonic) -> + fmterr(Location, Fmt, [Mnemonic]). %% Directives ------------------------------------------------------------------ @@ -271,9 +271,9 @@ dot_data(ScanState) -> {ok, {_Location1, {?T_UINTEGER, Nr}}} -> case scan:token(ScanState) of {ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_data{nr = Nr}}; - ScanRes -> badtok(ScanState, "junk after .data ", ScanRes) + ScanRes -> badtok("junk after .data ", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .data", ScanRes) + ScanRes -> badtok("junk after .data", ScanRes) end. dot_file(ScanState) -> @@ -289,9 +289,9 @@ dot_file_or_ident(ScanState, MkStmt, ErrMsg) -> {ok, {_Location1, {?T_STRING, String}}} -> case scan:token(ScanState) of {ok, {_Location2, ?T_NEWLINE}} -> {ok, MkStmt(String)}; - ScanRes -> badtok(ScanState, ErrMsg, ScanRes) + ScanRes -> badtok(ErrMsg, ScanRes) end; - ScanRes -> badtok(ScanState, ErrMsg, ScanRes) + ScanRes -> badtok(ErrMsg, ScanRes) end. dot_globl(ScanState) -> @@ -299,21 +299,21 @@ dot_globl(ScanState) -> {ok, {_Location1, {?T_SYMBOL, Name}}} -> case scan:token(ScanState) of {ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_globl{name = Name}}; - ScanRes -> badtok(ScanState, "junk after .globl", ScanRes) + ScanRes -> badtok("junk after .globl", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .globl", ScanRes) + ScanRes -> badtok("junk after .globl", ScanRes) end. dot_popsection(ScanState) -> case scan:token(ScanState) of {ok, {_Location, ?T_NEWLINE}} -> {ok, #s_dot_popsection{}}; - ScanRes -> badtok(ScanState, "junk after .popsection", ScanRes) + ScanRes -> badtok("junk after .popsection", ScanRes) end. dot_previous(ScanState) -> case scan:token(ScanState) of {ok, {_Location, ?T_NEWLINE}} -> {ok, #s_dot_previous{}}; - ScanRes -> badtok(ScanState, "junk after .previous", ScanRes) + ScanRes -> badtok("junk after .previous", ScanRes) end. %% For now only accepts ".pushsection [, ]". TODO: extend @@ -324,7 +324,7 @@ dot_pushsection(ScanState) -> %% TODO: do we need a general mapping from reserved to plain symbols? {ok, {_Location, ?T_DOT_DATA}} -> dot_pushsection(ScanState, _Name = ".data"); {ok, {_Location, ?T_DOT_TEXT}} -> dot_pushsection(ScanState, _Name = ".text"); - ScanRes -> badtok(ScanState, "junk after .pushsection", ScanRes) + ScanRes -> badtok("junk after .pushsection", ScanRes) end. %% Seen ".pushsection ", expects "[, ]". @@ -336,11 +336,11 @@ dot_pushsection(ScanState, Name) -> {ok, {_Location2, {?T_UINTEGER, Nr}}} -> case scan:token(ScanState) of {ok, {_Location3, ?T_NEWLINE}} -> {ok, #s_dot_pushsection{name = Name, nr = Nr}}; - ScanRes -> badtok(ScanState, "junk after .pushsection , ", ScanRes) + ScanRes -> badtok("junk after .pushsection , ", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .pushsection ,", ScanRes) + ScanRes -> badtok("junk after .pushsection ,", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .pushsection ", ScanRes) + ScanRes -> badtok("junk after .pushsection ", ScanRes) end. %% For now only accepts ".size ,.-". TODO: extend @@ -357,17 +357,17 @@ dot_size(ScanState) -> {ok, {_Location5, {?T_SYMBOL, Name}}} -> % same Name as above case scan:token(ScanState) of {ok, {_Location6, ?T_NEWLINE}} -> {ok, #s_dot_size{name = Name}}; - ScanRes -> badtok(ScanState, "junk after .size", ScanRes) + ScanRes -> badtok("junk after .size", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .size", ScanRes) + ScanRes -> badtok("junk after .size", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .size", ScanRes) + ScanRes -> badtok("junk after .size", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .size", ScanRes) + ScanRes -> badtok("junk after .size", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .size", ScanRes) + ScanRes -> badtok("junk after .size", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .size", ScanRes) + ScanRes -> badtok("junk after .size", ScanRes) end. dot_subsection(ScanState) -> @@ -375,9 +375,9 @@ dot_subsection(ScanState) -> {ok, {_Location1, {?T_UINTEGER, Nr}}} -> case scan:token(ScanState) of {ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_subsection{nr = Nr}}; - ScanRes -> badtok(ScanState, "junk after .subsection ", ScanRes) + ScanRes -> badtok("junk after .subsection ", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .subsection", ScanRes) + ScanRes -> badtok("junk after .subsection", ScanRes) end. dot_text(ScanState) -> @@ -386,9 +386,9 @@ dot_text(ScanState) -> {ok, {_Location1, {?T_UINTEGER, Nr}}} -> case scan:token(ScanState) of {ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_text{nr = Nr}}; - ScanRes -> badtok(ScanState, "junk after .text ", ScanRes) + ScanRes -> badtok("junk after .text ", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .text", ScanRes) + ScanRes -> badtok("junk after .text", ScanRes) end. %% For now only accepts ".type ,@function". TODO: extend @@ -403,25 +403,24 @@ dot_type(ScanState) -> {ok, {_Location4, {?T_SYMBOL, "function"}}} -> case scan:token(ScanState) of {ok, {_Location5, ?T_NEWLINE}} -> {ok, #s_dot_type{name = Name}}; - ScanRes -> badtok(ScanState, "junk after .type", ScanRes) + ScanRes -> badtok("junk after .type", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .type", ScanRes) + ScanRes -> badtok("junk after .type", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .type", ScanRes) + ScanRes -> badtok("junk after .type", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .type", ScanRes) + ScanRes -> badtok("junk after .type", ScanRes) end; - ScanRes -> badtok(ScanState, "junk after .type", ScanRes) + ScanRes -> badtok("junk after .type", ScanRes) end. %% Error reporting ------------------------------------------------------------- -badtok(_ScanState, _ErrMsg, {error, _Reason} = Error) -> Error; -badtok(ScanState, ErrMsg, {ok, {_Location, Token}}) -> - fmterr(ScanState, ErrMsg ++ "; current token is ~s", [token:format(Token)]). +badtok(_ErrMsg, {error, _Reason} = Error) -> Error; +badtok(ErrMsg, {ok, {Location, Token}}) -> + fmterr(Location, ErrMsg ++ "; current token is ~s", [token:format(Token)]). -fmterr(ScanState, Fmt, Args) -> - {ok, {FileName, LineNr}} = scan_state:location(ScanState), +fmterr({FileName, LineNr}, Fmt, Args) -> {error, {?MODULE, {FileName, LineNr, Fmt, Args}}}. -spec format_error(term()) -> io_lib:chars().