Я пытаюсь разобрать некоторые фрагменты Verilog - меня в первую очередь интересует извлечение определений и экземпляров модулей.
В Verilog модуль определяется так:
module foo ( ... ) endmodule;
И модуль создается одним из двух возможных способов:
foo fooinst ( ... );
foo #( ...list of params... ) fooinst ( .... );
На данный момент меня интересует только имя определенного или созданного модуля; 'foo' в обоих случаях выше.
Учитывая эту грамматику менгира (verParser.mly):
%{
type expr = Module of expr
| ModInst of expr
| Ident of string
| Int of int
| Lparen
| Rparen
| Junk
| ExprList of expr list
%}
%token <string> INT
%token <string> IDENT
%token LPAREN RPAREN MODULE TICK OTHER HASH EOF
%start expr2
%type <expr> mod_expr
%type <expr> expr1
%type <expr list> expr2
%%
mod_expr:
| MODULE IDENT LPAREN { Module ( Ident $2) }
| IDENT IDENT LPAREN { ModInst ( Ident $1) }
| IDENT HASH LPAREN { ModInst ( Ident $1) };
junk:
| LPAREN { }
| RPAREN { }
| HASH { }
| INT { };
expr1:
| junk* mod_expr junk* { $2 } ;
expr2:
| expr1* EOF { $1 };
Когда я пробую это в интерпретаторе менгира, он отлично работает, извлекая экземпляр модуля:
MODULE IDENT LPAREN
ACCEPT
[expr2:
[list(expr1):
[expr1:
[list(junk):]
[mod_expr: MODULE IDENT LPAREN]
[list(junk):]
]
[list(expr1):]
]
EOF
]
Он отлично работает для создания экземпляра одного модуля:
IDENT IDENT LPAREN
ACCEPT
[expr2:
[list(expr1):
[expr1:
[list(junk):]
[mod_expr: IDENT IDENT LPAREN]
[list(junk):]
]
[list(expr1):]
]
EOF
]
Но, конечно, если есть IDENT, который появляется перед любым из них, он будет ОТКЛОНЯТЬ:
IDENT MODULE IDENT LPAREN IDENT IDENT LPAREN
REJECT
... и, конечно же, в реальном файле verilog будут идентификаторы до этих определений.
Я пытаюсь не полностью указывать грамматику Verilog, вместо этого я хочу создавать грамматику медленно и постепенно, чтобы в конечном итоге анализировать все больше и больше языка.
Если я добавлю IDENT в правило нежелательной почты, это решит описанную выше проблему, но тогда правило создания экземпляра модуля не будет работать, потому что теперь правило нежелательной почты захватывает IDENT.
Можно ли создать очень разрешающее правило, которое будет обходить вещи, которые я не хочу сопоставлять, или обычно требуется, чтобы вы создали полную грамматику, чтобы действительно сделать что-то подобное?
Можно ли создать правило, которое позволит мне сопоставить:
MODULE IDENT LPAREN stuff* RPAREN ENDMODULE
где "stuff*" изначально соответствует всему, кроме RPAREN?
Что-то типа :
stuff:
| !RPAREN { } ;
В прошлом я использовал парсеры PEG, которые допускали такие конструкции.