当扫描仪在JAVACC中遇到SPECIAL_TOKEN时,有没有办法调用函数?

时间:2013-06-26 14:36:24

标签: javacc

我正在使用JAVACC为Eclipse插件编写一个简单的Verilog HDL解析器。

在此插件中,所有参数和连线都在“大纲”视图中注册。 如果包含的文件中存在大量的分解,则此功能很难在“大纲”视图中找到所需的信号。 为了缩短轮廓列表,我想从包含的文件中将参数(和其他信号)收集到子文件夹中。

Parser实际上是两次通过,这意味着首先解析所有编译器派生词,并将结果字符串传递给Verilog解析器(JAVACC)。

因此,JAVACC解析器无法知道所包含文件的开始和结束位置。

为解决这个问题,我添加了SPECIAL_TOKEN,其中包含一些与包含相关的信息。

Lexer正确检测到SPECIAL_TOKEN,但是我找不到从SPECIAL_TOKEN的预处理体调用解析器函数的方法。 (实际上,这是合理的,因为它们位于不同的类别中)

我想我可以使用页面最后一部分描述的解决方案(https://javacc.java.net/doc/tokenmanager.html)。 但是,我必须将这些代码添加到所有常规令牌中,不是吗? 如你所知,Verilog的语法是如此复杂,我无法接受上述解决方案。

有没有一个很好的解决方案来解决这个问题?

1 个答案:

答案 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
}