ANTLR Verilog @ ( * ) совпадение двух лексем
Я пытаюсь использовать ANTLR4 для разбора кода Verilog. Я использую грамматику Verilog, найденную здесь https://github.com/antlr/grammars-v4/blob/master/verilog/Verilog2001.g4
Пример кода
module blinker(
input clk,
input rst,
output blink
);
reg [24:0] counter_d, counter_q;
assign blink = counter_q[24];
always @(*) begin
counter_d = counter_q + 1'b1;
end
always @(posedge clk) begin
if (rst) begin
counter_q <= 25'b0;
end else begin
counter_q <= counter_d;
end
end
endmodule
Проблема заключается в линии
always @(*) begin
( * ) разбивается на лексемы ' (*' и ')'.
В строке 723 файла грамматики есть
event_control :
'@' event_identifier
| '@' '(' event_expression ')'
| '@' '*'
| '@' '(' '*' ')'
;
Который должен соответствовать строке @ ( * ), если бы не строка 1329
attribute_instance : '(*' attr_spec ( ',' attr_spec )* '*)' ;
Я новичок во всем этом. это, но я предполагаю, что маркер '(*' из этой строки соответствует (* в коде и все портит.
Прочитав немного из окончательной ссылки ANTLR 4, я подумал, что правило, впервые определенное, будет иметь приоритет. Однако, я думаю, что это делает жадный матч?
Есть идеи, как исправить грамматику?
2 ответа:
Я новичок во всем этом, но я предполагаю, что маркер'(*'
из этой строки соответствует(*
в коде и все портит.Вы правы.
Прочитав немного из окончательной ссылки ANTLR 4, я подумал, что правило, впервые определенное, будет иметь приоритет. Однако, я думаю, что это делает жадный матч?
Несмотря на то, что они определены в правилах синтаксического анализа, литеральные токены на самом деле являются правилами лексера, которые имеют приоритет в том порядке, в котором они определены , только, если они совпадают с одинаковым количеством символов. Если правило лексера может соответствовать большему числу, оно так и делает (как вы заметили).
Я не знаю никакого Verilog, но быстрое решение для этого было бы позволить
attribute_instance
выглядеть так:Однако, если лексер отбрасывает символы, такие как пробелы, то входattribute_instance : '(' '*' attr_spec ( ',' attr_spec )* '*' ')' ;
"( *"
(скобка, пробел, звезда) также будет соответствовать началуattribute_instance
. Если это нежелательно, вы можете позволить своемуevent_control
выглядеть так это:event_control : '@' event_identifier | '@' '(' event_expression ')' | '@' '*' | '@' ( '(' '*' | '(*' ) ')' ;
Обратите внимание на
( '(' '*' | '(*' )
в последней альтернативе, которая соответствует двум одиночным токенам,'('
и'*'
(с возможными пробелами между ними!), или единственный маркер'(*'
.