我正在使用JAVACC为Eclipse插件编写一个简单的Verilog HDL解析器。
在此插件中,所有参数和连线都在“大纲”视图中注册。 如果包含的文件中存在大量的分解,则此功能很难在“大纲”视图中找到所需的信号。 为了缩短轮廓列表,我想从包含的文件中将参数(和其他信号)收集到子文件夹中。
Parser实际上是两次通过,这意味着首先解析所有编译器派生词,并将结果字符串传递给Verilog解析器(JAVACC)。
因此,JAVACC解析器无法知道所包含文件的开始和结束位置。
为解决这个问题,我添加了SPECIAL_TOKEN,其中包含一些与包含相关的信息。
Lexer正确检测到SPECIAL_TOKEN,但是我找不到从SPECIAL_TOKEN的预处理体调用解析器函数的方法。 (实际上,这是合理的,因为它们位于不同的类别中)
我想我可以使用页面最后一部分描述的解决方案(https://javacc.java.net/doc/tokenmanager.html)。 但是,我必须将这些代码添加到所有常规令牌中,不是吗? 如你所知,Verilog的语法是如此复杂,我无法接受上述解决方案。
有没有一个很好的解决方案来解决这个问题?
答案 0 :(得分:1)
如果您的解析器是静态的,那么只需将解析器函数设置为静态。
如果解析器不是静态的,您可以安排令牌管理器将指针指向其解析器。声明此指针如下
TOKEN_MGR_DECLS : { VerlilogParser myParser ; }
然后确保在解析器开始解析之前设置此字段
VerilogParserTokenManager tokMan = new VerilogParserTokenManager(in) ;
VerlilogParser parser = new VerlilogParser(tokMan) ;
tokMan.myParser = parser ;
parser.start() ;
请记住,先行可以使令牌管理器远远超出解析器。因此,从令牌管理器调用解析器时必须非常小心。我解决了将预处理行号与C ++中的预处理行号和文件名相关联的问题的方法是我构建了一个表,表示从一个到另一个的映射。您可以在https://code.google.com/p/the-teaching-machine-jhigraph-and-webwriter-plus-plus/source/browse/trunk/trunk/tm/src/tm/cpp/parser/cplusplus.jj中看到此信息。以下是一些摘录:
当解析器需要知道下一个标记的原始坐标时,它调用getCoords(0)定义如下:
// Coordinates
SourceCoords getCoords(int offset ) {
return pc.line_map.getCoords(getToken(offset).beginLine) ; }
令牌管理器使用以下代码填充line_map表。
SPECIAL_TOKEN :
{
// Line directives should have the form
// #line linenum filename
// or
// #line linenum
// In the latter case the previous file name is kept.
"#line" : LINE_DIRECTIVE
}
<LINE_DIRECTIVE> SPECIAL_TOKEN :
{
<LINE_NO : (["0"-"9"])+>
{ tokenLine = matchedToken.beginLine+1 ;
sourceLine = Integer.parseInt (matchedToken.image.trim()); }
|
<FILE_NM : "\"" (["0"-"9"])+ "\"">
{ file = fileMap.get( new Integer(matchedToken.image.substring(1, matchedToken.image.length()-1) ) );}
|
" "
|
"\n" { pc.line_map.add (tokenLine, sourceLine, file); } : DEFAULT
}