From d6eef91276daa4acdbed3f924a99cf087cb98fe3 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sat, 25 Jan 2020 19:36:03 +0100 Subject: [PATCH] as: parse: handle :modifier(symbol+offset) exprs, improve docs --- erlang/apps/as/src/parse.erl | 104 ++++++++++++++++++++++++++--------- erlang/apps/as/src/tunit.hrl | 1 + 2 files changed, 78 insertions(+), 27 deletions(-) diff --git a/erlang/apps/as/src/parse.erl b/erlang/apps/as/src/parse.erl index 7306f54..6d69758 100644 --- a/erlang/apps/as/src/parse.erl +++ b/erlang/apps/as/src/parse.erl @@ -73,7 +73,7 @@ stmt(ScanState) -> %% %%
::= "@"? ? ? %% -%% ::= | | [bf] +%% ::= %% %% ::= "(" ")" %% @@ -85,9 +85,6 @@ stmt(ScanState) -> %% movei 1,@fum(2) %% jump bar %% -%% TODO: should be and permit parentheses and -%% various operators. -%% %% Ambiguous example: %% %% () @@ -137,7 +134,7 @@ insn_uint(ScanState, Location, Name, Location2, UInt) -> %% Seen " " where is not "@", or followed by ",". %% is the start of the . insn_disp(ScanState, Location, Name, First) -> - case do_expr(ScanState, {ok, First}) of + case do_expr(ScanState, {ok, First}, ifiw) of {ok, Displacement} -> insn_ea_disp(ScanState, Location, Name, _AccOrDev = false, _At = false, Displacement); {error, _Reason} = Error -> Error @@ -150,7 +147,7 @@ insn_ea(ScanState, Location, 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, {_Location, _Token}} = ScanRes -> - case do_expr(ScanState, ScanRes) of + case do_expr(ScanState, ScanRes, ifiw) of {ok, Displacement} -> insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = false, Displacement); {error, _Reason} = Error -> Error @@ -160,7 +157,7 @@ insn_ea(ScanState, Location, Name, AccOrDev) -> %% [ ","] "@" . ["(" ")"] insn_ea_at(ScanState, Location, Name, AccOrDev) -> - case expr(ScanState) of + case expr(ScanState, ifiw) of {ok, Displacement} -> insn_ea_disp(ScanState, Location, Name, AccOrDev, _At = true, Displacement); {error, _Reason} = Error -> Error @@ -208,7 +205,7 @@ make_insn(Location, Name, AccOrDev, At, Displacement, Index) -> Stmt = #s_insn{ high13 = FinalHigh13 , at = At , address = case Displacement of - false -> mk_integer_expr(0); + false -> mk_integer_expr(0, ifiw); _ -> Displacement end , index = if Index =:= false -> 0; true -> Index end @@ -602,13 +599,26 @@ section_name(ScanState) -> end. %% Expressions ----------------------------------------------------------------- +%% +%% ::= ":" "(" ")" +%% | +%% +%% ::= "(" ")" +%% | "-"? +%% | ( | ) (("+" | "-") )? +%% +%% ::= "ifiw" | "w" | "b" | "h" +%% +%% Note: defaults to "ifiw" in and "w" in data directives. +%% It describes how the value should be represented, which also determines +%% which relocation to use for it. %% ::= ( ("," )*)? \n expr_list(ScanState) -> case scan:token(ScanState) of {ok, {_Location, ?T_NEWLINE}} -> {ok, []}; First -> - case do_expr(ScanState, First) of + case do_expr(ScanState, First, _DefaultModifier = w) of {ok, Expr} -> expr_list(ScanState, [Expr]); {error, _Reason} = Error -> Error end @@ -617,7 +627,7 @@ expr_list(ScanState) -> expr_list(ScanState, Exprs) -> case scan:token(ScanState) of {ok, {_Location, ?T_COMMA}} -> - case expr(ScanState) of + case expr(ScanState, _DefaultModifier = w) of {ok, Expr} -> expr_list(ScanState, [Expr | Exprs]); {error, _Reason} = Error -> Error end; @@ -625,13 +635,44 @@ expr_list(ScanState, Exprs) -> ScanRes -> badtok("expected comma or newline", ScanRes) end. -expr(ScanState) -> - do_expr(ScanState, scan:token(ScanState)). +expr(ScanState, DefaultModifier) -> + do_expr(ScanState, scan:token(ScanState), DefaultModifier). -do_expr(ScanState, First) -> +do_expr(ScanState, First, DefaultModifier) -> + case First of + {ok, {_Location, ?T_COLON}} -> modifier_expr(ScanState); + _ -> do_plain_expr(ScanState, First, DefaultModifier) + end. + +modifier_expr(ScanState) -> + case scan:token(ScanState) of + {ok, {_Location1, {?T_SYMBOL, Symbol}}} = ScanRes1 -> + case symbol_modifier(Symbol) of + false -> badtok("invalid modifier", ScanRes1); + Modifier -> + case scan:token(ScanState) of + {ok, {_Location2, ?T_LPAREN}} -> + case plain_expr(ScanState, Modifier) of + {ok, _Expr} = Result -> + case scan:token(ScanState) of + {ok, {_Location3, ?T_RPAREN}} -> Result; + ScanRes3 -> badtok("expected right parenthesis", ScanRes3) + end; + {error, _Reason} = Error -> Error + end; + ScanRes2 -> badtok("expected left parenthesis", ScanRes2) + end + end; + ScanRes1 -> badtok("expected modifier ", ScanRes1) + end. + +plain_expr(ScanState, Modifier) -> + do_plain_expr(ScanState, scan:token(ScanState), Modifier). + +do_plain_expr(ScanState, First, Modifier) -> case First of {ok, {_Location1, ?T_LPAREN}} -> - case expr(ScanState) of + case plain_expr(ScanState, Modifier) of {ok, Expr} -> case scan:token(ScanState) of {ok, {_Location2, ?T_RPAREN}} -> {ok, Expr}; @@ -642,39 +683,48 @@ do_expr(ScanState, First) -> {ok, {_Location1, ?T_MINUS}} -> case scan:token(ScanState) of {ok, {_Location2, {?T_UINTEGER, UInt}}} -> - {ok, mk_integer_expr(-UInt)}; + {ok, mk_integer_expr(-UInt, Modifier)}; ScanRes -> badtok("expected after -", ScanRes) end; {ok, {_Location, {?T_UINTEGER, UInt}}} -> - {ok, mk_integer_expr(UInt)}; + {ok, mk_integer_expr(UInt, Modifier)}; {ok, {_Location, {?T_LOCAL_LABEL, Number, Direction}}} -> - do_expr_maybe_offset(ScanState, _Symbol = {Number, Direction}); + do_expr_maybe_offset(ScanState, _Symbol = {Number, Direction}, Modifier); {ok, {_Location, {?T_SYMBOL, Symbol}}} -> - do_expr_maybe_offset(ScanState, Symbol); + do_expr_maybe_offset(ScanState, Symbol, Modifier); _ -> badtok("invalid start of expr", First) end. -do_expr_maybe_offset(ScanState, Symbol) -> +do_expr_maybe_offset(ScanState, Symbol, Modifier) -> case scan:token(ScanState) of - {ok, {_Location, ?T_MINUS}} -> do_expr_offset(ScanState, Symbol, _IsMinus = true); - {ok, {_Location, ?T_PLUS}} -> do_expr_offset(ScanState, Symbol, _IsMinus = false); + {ok, {_Location, ?T_MINUS}} -> do_expr_offset(ScanState, Symbol, _IsMinus = true, Modifier); + {ok, {_Location, ?T_PLUS}} -> do_expr_offset(ScanState, Symbol, _IsMinus = false, Modifier); {ok, {_Location, _Token} = First} -> scan:pushback(ScanState, First), - {ok, mk_symbol_expr(Symbol)}; + {ok, mk_symbol_expr(Symbol, Modifier)}; {error, _Reason} = Error -> Error end. -do_expr_offset(ScanState, Symbol, IsMinus) -> +do_expr_offset(ScanState, Symbol, IsMinus, Modifier) -> case scan:token(ScanState) of {ok, {_Location, {?T_UINTEGER, UInt}}} -> - {ok, mk_symbol_expr(Symbol, if IsMinus -> -UInt; true -> UInt end)}; + {ok, mk_symbol_expr(Symbol, if IsMinus -> -UInt; true -> UInt end, Modifier)}; ScanRes -> badtok("expected after ", ScanRes) end. -mk_integer_expr(Value) -> #expr{symbol = false, offset = Value}. -mk_symbol_expr(Symbol) -> #expr{symbol = Symbol, offset = 0}. -mk_symbol_expr(Symbol, Offset) -> #expr{symbol = Symbol, offset = Offset}. +symbol_modifier(Symbol) -> + case Symbol of + "ifiw" -> ifiw; + "w" -> w; + "b" -> b; + "h" -> h; + _ -> false + end. + +mk_integer_expr(Value, Modifier) -> #expr{symbol = false, offset = Value, modifier = Modifier}. +mk_symbol_expr(Symbol, Modifier) -> #expr{symbol = Symbol, offset = 0, modifier = Modifier}. +mk_symbol_expr(Symbol, Offset, Modifier) -> #expr{symbol = Symbol, offset = Offset, modifier = Modifier}. %% String Lists ---------------------------------------------------------------- diff --git a/erlang/apps/as/src/tunit.hrl b/erlang/apps/as/src/tunit.hrl index 502c6d9..c577d73 100644 --- a/erlang/apps/as/src/tunit.hrl +++ b/erlang/apps/as/src/tunit.hrl @@ -26,6 +26,7 @@ -record(expr, { symbol :: false | string() | {non_neg_integer(), $b | $f} , offset :: integer() + , modifier :: ifiw | w | b | h }). -type expr() :: #expr{}.