as: parse: tag returned statements with start locations; input: use it

This commit is contained in:
Mikael Pettersson 2019-12-26 20:38:12 +01:00
parent 589e2c40bb
commit 084b3b4e8f
2 changed files with 64 additions and 62 deletions

View File

@ -79,8 +79,8 @@ pass1_file(File, Ctx) ->
pass1_process(ScanState, Ctx) ->
case parse:stmt(ScanState) of
eof -> {ok, Ctx};
{ok, Stmt} ->
case pass1_stmt(scan_state_location(ScanState), Ctx, Stmt) of
{ok, {Location, Stmt}} ->
case pass1_stmt(Location, Ctx, Stmt) of
{ok, NewCtx} -> pass1_process(ScanState, NewCtx);
{error, _Reason} = Error -> Error
end;
@ -270,10 +270,6 @@ scan_state_open(File) ->
_ -> scan_state:fopen(File)
end.
scan_state_location(ScanState) ->
{ok, Location = {_FileName, _LineNr}} = scan_state:location(ScanState),
Location.
%% Pass 2 ----------------------------------------------------------------------
%%
%% - process subsections in order

View File

@ -28,23 +28,25 @@
-include("tunit.hrl").
-include_lib("lib/include/pdp10_opcodes.hrl").
-type location() :: scan_state:location().
-spec stmt(scan_state:scan_state())
-> {ok, stmt()} | eof | {error, {module(), term()}}.
-> {ok, {location(), stmt()}} | eof | {error, {module(), term()}}.
stmt(ScanState) ->
case scan:token(ScanState) of
{ok, {_Location, ?T_DOT_DATA}} -> dot_data(ScanState);
{ok, {_Location, ?T_DOT_FILE}} -> dot_file(ScanState);
{ok, {_Location, ?T_DOT_GLOBL}} -> dot_globl(ScanState);
{ok, {_Location, ?T_DOT_IDENT}} -> dot_ident(ScanState);
{ok, {_Location, ?T_DOT_POPSECTION}} -> dot_popsection(ScanState);
{ok, {_Location, ?T_DOT_PREVIOUS}} -> dot_previous(ScanState);
{ok, {_Location, ?T_DOT_PUSHSECTION}} -> dot_pushsection(ScanState);
{ok, {_Location, ?T_DOT_SIZE}} -> dot_size(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_DOT_DATA}} -> dot_data(ScanState, Location);
{ok, {Location, ?T_DOT_FILE}} -> dot_file(ScanState, Location);
{ok, {Location, ?T_DOT_GLOBL}} -> dot_globl(ScanState, Location);
{ok, {Location, ?T_DOT_IDENT}} -> dot_ident(ScanState, Location);
{ok, {Location, ?T_DOT_POPSECTION}} -> dot_popsection(ScanState, Location);
{ok, {Location, ?T_DOT_PREVIOUS}} -> dot_previous(ScanState, Location);
{ok, {Location, ?T_DOT_PUSHSECTION}} -> dot_pushsection(ScanState, Location);
{ok, {Location, ?T_DOT_SIZE}} -> dot_size(ScanState, Location);
{ok, {Location, ?T_DOT_SUBSECTION}} -> dot_subsection(ScanState, Location);
{ok, {Location, ?T_DOT_TEXT}} -> dot_text(ScanState, Location);
{ok, {Location, ?T_DOT_TYPE}} -> dot_type(ScanState, Location);
{ok, {Location, {?T_SYMBOL, Name}}} -> stmt_after_symbol(ScanState, Location, Name);
{ok, {_Location, {?T_UINTEGER, UInt}}} -> stmt_after_uinteger(ScanState, UInt);
{ok, {Location, {?T_UINTEGER, UInt}}} -> stmt_after_uinteger(ScanState, Location, UInt);
{ok, {_Location, ?T_NEWLINE}} -> stmt(ScanState);
{ok, {_Location, ?T_EOF}} -> eof;
ScanRes -> badtok("expected directive, label, or instruction", ScanRes)
@ -96,7 +98,7 @@ stmt(ScanState) ->
stmt_after_symbol(ScanState, Location, Name) ->
case scan:token(ScanState) of
{ok, {_Location, ?T_COLON}} -> {ok, #s_label{name = Name}};
{ok, {_Location, ?T_COLON}} -> {ok, {Location, #s_label{name = Name}}};
{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);
@ -106,9 +108,9 @@ stmt_after_symbol(ScanState, Location, Name) ->
end.
%% <stmt> ::= <uinteger> . ":"
stmt_after_uinteger(ScanState, UInt) ->
stmt_after_uinteger(ScanState, Location, UInt) ->
case scan:token(ScanState) of
{ok, {_Location, ?T_COLON}} -> {ok, #s_local_label{number = UInt}};
{ok, {_Location, ?T_COLON}} -> {ok, {Location, #s_local_label{number = UInt}}};
ScanRes -> badtok("junk after symbol", ScanRes)
end.
@ -209,14 +211,16 @@ make_insn(Location, Name, AccOrDev, At, Displacement, Index) ->
{ok, FinalHigh13} ->
case check_e(Location, Name, At, Displacement, Index, EUnused) of
{error, _Reason} = Error -> Error;
ok -> {ok, #s_insn{ high13 = FinalHigh13
, at = At
, address = case Displacement of
false -> #e_integer{value = 0};
_ -> Displacement
end
, index = if Index =:= false -> 0; true -> Index end
}}
ok ->
Stmt = #s_insn{ high13 = FinalHigh13
, at = At
, address = case Displacement of
false -> #e_integer{value = 0};
_ -> Displacement
end
, index = if Index =:= false -> 0; true -> Index end
},
{ok, {Location, Stmt}}
end
end
end.
@ -265,77 +269,79 @@ badinsn(Location, Fmt, Mnemonic) ->
%% Directives ------------------------------------------------------------------
dot_data(ScanState) ->
dot_data(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location1, ?T_NEWLINE}} -> {ok, #s_dot_data{nr = 0}};
{ok, {_Location1, ?T_NEWLINE}} -> {ok, {Location, #s_dot_data{nr = 0}}};
{ok, {_Location1, {?T_UINTEGER, Nr}}} ->
case scan:token(ScanState) of
{ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_data{nr = Nr}};
{ok, {_Location2, ?T_NEWLINE}} -> {ok, {Location, #s_dot_data{nr = Nr}}};
ScanRes -> badtok("junk after .data <nr>", ScanRes)
end;
ScanRes -> badtok("junk after .data", ScanRes)
end.
dot_file(ScanState) ->
dot_file_or_ident(ScanState, fun(String) -> #s_dot_file{string = String} end,
dot_file(ScanState, Location) ->
dot_file_or_ident(ScanState, Location,
fun(String) -> #s_dot_file{string = String} end,
"junk after .file").
dot_ident(ScanState) ->
dot_file_or_ident(ScanState, fun(String) -> #s_dot_ident{string = String} end,
dot_ident(ScanState, Location) ->
dot_file_or_ident(ScanState, Location,
fun(String) -> #s_dot_ident{string = String} end,
"junk after .ident").
dot_file_or_ident(ScanState, MkStmt, ErrMsg) ->
dot_file_or_ident(ScanState, Location, MkStmt, ErrMsg) ->
case scan:token(ScanState) of
{ok, {_Location1, {?T_STRING, String}}} ->
case scan:token(ScanState) of
{ok, {_Location2, ?T_NEWLINE}} -> {ok, MkStmt(String)};
{ok, {_Location2, ?T_NEWLINE}} -> {ok, {Location, MkStmt(String)}};
ScanRes -> badtok(ErrMsg, ScanRes)
end;
ScanRes -> badtok(ErrMsg, ScanRes)
end.
dot_globl(ScanState) ->
dot_globl(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location1, {?T_SYMBOL, Name}}} ->
case scan:token(ScanState) of
{ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_globl{name = Name}};
{ok, {_Location2, ?T_NEWLINE}} -> {ok, {Location, #s_dot_globl{name = Name}}};
ScanRes -> badtok("junk after .globl", ScanRes)
end;
ScanRes -> badtok("junk after .globl", ScanRes)
end.
dot_popsection(ScanState) ->
dot_popsection(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location, ?T_NEWLINE}} -> {ok, #s_dot_popsection{}};
{ok, {_Location, ?T_NEWLINE}} -> {ok, {Location, #s_dot_popsection{}}};
ScanRes -> badtok("junk after .popsection", ScanRes)
end.
dot_previous(ScanState) ->
dot_previous(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location, ?T_NEWLINE}} -> {ok, #s_dot_previous{}};
{ok, {_Location, ?T_NEWLINE}} -> {ok, {Location, #s_dot_previous{}}};
ScanRes -> badtok("junk after .previous", ScanRes)
end.
%% For now only accepts ".pushsection <name> [, <nr>]". TODO: extend
dot_pushsection(ScanState) ->
dot_pushsection(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location, {?T_STRING, Name}}} -> dot_pushsection(ScanState, Name);
{ok, {_Location, {?T_SYMBOL, Name}}} -> dot_pushsection(ScanState, Name);
{ok, {_Location, {?T_STRING, Name}}} -> dot_pushsection(ScanState, Location, Name);
{ok, {_Location, {?T_SYMBOL, Name}}} -> dot_pushsection(ScanState, Location, Name);
%% 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");
{ok, {_Location, ?T_DOT_DATA}} -> dot_pushsection(ScanState, Location, _Name = ".data");
{ok, {_Location, ?T_DOT_TEXT}} -> dot_pushsection(ScanState, Location, _Name = ".text");
ScanRes -> badtok("junk after .pushsection", ScanRes)
end.
%% Seen ".pushsection <name>", expects "[, <nr>]".
dot_pushsection(ScanState, Name) ->
dot_pushsection(ScanState, Location, Name) ->
case scan:token(ScanState) of
{ok, {_Location1, ?T_NEWLINE}} -> {ok, #s_dot_pushsection{name = Name, nr = 0}};
{ok, {_Location1, ?T_NEWLINE}} -> {ok, {Location, #s_dot_pushsection{name = Name, nr = 0}}};
{ok, {_Location1, ?T_COMMA}} ->
case scan:token(ScanState) of
{ok, {_Location2, {?T_UINTEGER, Nr}}} ->
case scan:token(ScanState) of
{ok, {_Location3, ?T_NEWLINE}} -> {ok, #s_dot_pushsection{name = Name, nr = Nr}};
{ok, {_Location3, ?T_NEWLINE}} -> {ok, {Location, #s_dot_pushsection{name = Name, nr = Nr}}};
ScanRes -> badtok("junk after .pushsection <name>, <nr>", ScanRes)
end;
ScanRes -> badtok("junk after .pushsection <name>,", ScanRes)
@ -344,7 +350,7 @@ dot_pushsection(ScanState, Name) ->
end.
%% For now only accepts ".size <sym>,.-<sym>". TODO: extend
dot_size(ScanState) ->
dot_size(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location1, {?T_SYMBOL, Name}}} ->
case scan:token(ScanState) of
@ -356,7 +362,7 @@ dot_size(ScanState) ->
case scan:token(ScanState) of
{ok, {_Location5, {?T_SYMBOL, Name}}} -> % same Name as above
case scan:token(ScanState) of
{ok, {_Location6, ?T_NEWLINE}} -> {ok, #s_dot_size{name = Name}};
{ok, {_Location6, ?T_NEWLINE}} -> {ok, {Location, #s_dot_size{name = Name}}};
ScanRes -> badtok("junk after .size", ScanRes)
end;
ScanRes -> badtok("junk after .size", ScanRes)
@ -370,29 +376,29 @@ dot_size(ScanState) ->
ScanRes -> badtok("junk after .size", ScanRes)
end.
dot_subsection(ScanState) ->
dot_subsection(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location1, {?T_UINTEGER, Nr}}} ->
case scan:token(ScanState) of
{ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_subsection{nr = Nr}};
{ok, {_Location2, ?T_NEWLINE}} -> {ok, {Location, #s_dot_subsection{nr = Nr}}};
ScanRes -> badtok("junk after .subsection <nr>", ScanRes)
end;
ScanRes -> badtok("junk after .subsection", ScanRes)
end.
dot_text(ScanState) ->
dot_text(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location1, ?T_NEWLINE}} -> {ok, #s_dot_text{nr = 0}};
{ok, {_Location1, ?T_NEWLINE}} -> {ok, {Location, #s_dot_text{nr = 0}}};
{ok, {_Location1, {?T_UINTEGER, Nr}}} ->
case scan:token(ScanState) of
{ok, {_Location2, ?T_NEWLINE}} -> {ok, #s_dot_text{nr = Nr}};
{ok, {_Location2, ?T_NEWLINE}} -> {ok, {Location, #s_dot_text{nr = Nr}}};
ScanRes -> badtok("junk after .text <nr>", ScanRes)
end;
ScanRes -> badtok("junk after .text", ScanRes)
end.
%% For now only accepts ".type <sym>,@function". TODO: extend
dot_type(ScanState) ->
dot_type(ScanState, Location) ->
case scan:token(ScanState) of
{ok, {_Location1, {?T_SYMBOL, Name}}} ->
case scan:token(ScanState) of
@ -402,7 +408,7 @@ dot_type(ScanState) ->
case scan:token(ScanState) of
{ok, {_Location4, {?T_SYMBOL, "function"}}} ->
case scan:token(ScanState) of
{ok, {_Location5, ?T_NEWLINE}} -> {ok, #s_dot_type{name = Name}};
{ok, {_Location5, ?T_NEWLINE}} -> {ok, {Location, #s_dot_type{name = Name}}};
ScanRes -> badtok("junk after .type", ScanRes)
end;
ScanRes -> badtok("junk after .type", ScanRes)