我正在尝试解析 Verilog 的一些点点滴滴——我主要对提取模块定义和实例感兴趣。
在verilog中,模块定义如下:
module foo ( ... ) endmodule;
并且模块以两种不同的可能方式之一实例化:
foo fooinst ( ... );
foo #( ...list of params... ) fooinst ( .... );
此时我只对查找已定义或实例化模块的名称感兴趣;'foo' 在上述两种情况下。
鉴于此 menhir 语法 (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 };
当我在 menhir 解释器中尝试这个时,它可以很好地提取模块实例:
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 出现在其中任何一个之前,它将 REJECT:
IDENT MODULE IDENT LPAREN IDENT IDENT LPAREN
REJECT
...当然,在这些defs之前的实际verilog文件中会有标识符。
我试图不必完全指定 Verilog 语法,而是希望慢慢地、增量地构建语法,以最终解析越来越多的语言。
如果我将 IDENT 添加到垃圾规则中,则可以解决上述问题,但是模块实例化规则不起作用,因为现在垃圾规则正在捕获 IDENT。
是否可以创建一个非常宽松的规则来绕过我不想匹配的内容,或者通常要求您必须创建一个完整的语法才能实际执行此类操作?
是否可以创建一个让我匹配的规则:
MODULE IDENT LPAREN stuff* RPAREN ENDMODULE
其中“stuff*”最初匹配除 RPAREN 之外的所有内容?
就像是 :
stuff:
| !RPAREN { } ;
我过去使用过允许这样的构造的 PEG 解析器。