获取yecc中的行号
Get line number in yecc
我正在使用 yecc 来解析我的标记化类 asm 代码。在提供像 "MOV [1], [2]\nJMP hello"
这样的代码并进行词法分析之后,这就是我得到的回应。
[{:opcode, 1, :MOV}, {:register, 1, 1}, {:",", 1}, {:register, 1, 2},
{:opcode, 2, :JMP}, {:identifer, 2, :hello}]
当我解析这个时,我得到
[%{operation: [:MOV, [:REGISTER, 1], [:REGISTER, 2]]},
%{operation: [:JMP, [:CONST, :hello]]}]
但我希望每个操作都有行号,以便在代码中进一步得到有意义的错误。
所以我将解析器更改为:
Nonterminals
code statement operation value.
Terminals
label identifer integer ',' opcode register address address_in_register line_number.
Rootsymbol code.
code -> line_number statement : [{get_line(''), ''}].
code -> line_number statement code : [{get_line(''), ''} | ''].
%code -> statement : [''].
%code -> statement code : ['' | ''].
statement -> label : #{'label' => label('')}.
statement -> operation : #{'operation' => ''}.
operation -> opcode value ',' value : [operation(''), '', ''].
operation -> opcode value : [operation(''), ''].
operation -> opcode identifer : [operation(''), value('')].
operation -> opcode : [operation('')].
value -> integer : value('').
value -> register : value('').
value -> address : value('').
value -> address_in_register : value('').
Erlang code.
get_line({_, Line, _}) -> Line.
operation({opcode, _, OpcodeName}) -> OpcodeName.
label({label, _, Value}) -> Value.
value({identifer, _, Value}) -> ['CONST', Value];
value({integer, _, Value}) -> ['CONST', Value];
value({register, _, Value}) -> ['REGISTER', Value];
value({address, _, Value}) -> ['ADDRESS', Value];
value({address_in_register, _, Value}) -> ['ADDRESS_IN_REGISTER', Value].
(评论code
是旧的,工作规则)
现在我得到
{:error, {1, :assembler_parser, ['syntax error before: ', ['\'MOV\'']]}}
提供相同的输入后。如何解决这个问题?
我的建议是将行号保留在令牌中而不是作为单独的令牌,然后更改构建操作的方式。
所以我建议:
operation -> opcode value ',' value : [operation(''), line(''), '', ''].
operation -> opcode value : [operation(''), line(''), ''].
operation -> opcode identifer : [operation(''), line(''), value('')].
operation -> opcode : [operation(''), line('')].
line({_, Line, _}) -> Line.
如果你想镜像 Elixir AST,甚至可以这样:
operation -> opcode value ',' value : {operation(''), meta(''), ['', '']}.
operation -> opcode value : {operation(''), meta(''), ['']}.
operation -> opcode identifer : {operation(''), meta(''), [value('')]}.
operation -> opcode : {operation(''), meta(''), []}.
meta({_, Line, _}) -> [{line, Line}].
我正在使用 yecc 来解析我的标记化类 asm 代码。在提供像 "MOV [1], [2]\nJMP hello"
这样的代码并进行词法分析之后,这就是我得到的回应。
[{:opcode, 1, :MOV}, {:register, 1, 1}, {:",", 1}, {:register, 1, 2},
{:opcode, 2, :JMP}, {:identifer, 2, :hello}]
当我解析这个时,我得到
[%{operation: [:MOV, [:REGISTER, 1], [:REGISTER, 2]]},
%{operation: [:JMP, [:CONST, :hello]]}]
但我希望每个操作都有行号,以便在代码中进一步得到有意义的错误。
所以我将解析器更改为:
Nonterminals
code statement operation value.
Terminals
label identifer integer ',' opcode register address address_in_register line_number.
Rootsymbol code.
code -> line_number statement : [{get_line(''), ''}].
code -> line_number statement code : [{get_line(''), ''} | ''].
%code -> statement : [''].
%code -> statement code : ['' | ''].
statement -> label : #{'label' => label('')}.
statement -> operation : #{'operation' => ''}.
operation -> opcode value ',' value : [operation(''), '', ''].
operation -> opcode value : [operation(''), ''].
operation -> opcode identifer : [operation(''), value('')].
operation -> opcode : [operation('')].
value -> integer : value('').
value -> register : value('').
value -> address : value('').
value -> address_in_register : value('').
Erlang code.
get_line({_, Line, _}) -> Line.
operation({opcode, _, OpcodeName}) -> OpcodeName.
label({label, _, Value}) -> Value.
value({identifer, _, Value}) -> ['CONST', Value];
value({integer, _, Value}) -> ['CONST', Value];
value({register, _, Value}) -> ['REGISTER', Value];
value({address, _, Value}) -> ['ADDRESS', Value];
value({address_in_register, _, Value}) -> ['ADDRESS_IN_REGISTER', Value].
(评论code
是旧的,工作规则)
现在我得到
{:error, {1, :assembler_parser, ['syntax error before: ', ['\'MOV\'']]}}
提供相同的输入后。如何解决这个问题?
我的建议是将行号保留在令牌中而不是作为单独的令牌,然后更改构建操作的方式。
所以我建议:
operation -> opcode value ',' value : [operation(''), line(''), '', ''].
operation -> opcode value : [operation(''), line(''), ''].
operation -> opcode identifer : [operation(''), line(''), value('')].
operation -> opcode : [operation(''), line('')].
line({_, Line, _}) -> Line.
如果你想镜像 Elixir AST,甚至可以这样:
operation -> opcode value ',' value : {operation(''), meta(''), ['', '']}.
operation -> opcode value : {operation(''), meta(''), ['']}.
operation -> opcode identifer : {operation(''), meta(''), [value('')]}.
operation -> opcode : {operation(''), meta(''), []}.
meta({_, Line, _}) -> [{line, Line}].