当前位置: 首页 > 知识库问答 >
问题:

ANTLR4还支持无扫描解析器语法吗?

司寇飞航
2023-03-14

我有一个利用CharsAsTokens人造lexer的无扫描解析器语法,它为ANTLR4到4.6版本生成了一个可用的Java解析器类。但是,当更新到ANTLR 4.7.2到4.9.3-Snapshot时,该工具会生成代码,从相同的语法文件产生数十个编译错误,如下所述。

我这里的问题很简单:是否不再支持无扫描解析器语法,或者必须在4.7和更高版本中以不同的方式指定基于字符的终端?

更新:

不幸的是,我不能在这里张贴我的完整语法,因为它来自FOO安全标记指南,访问被美国政府收回(我是国防部/集成电路承包商)。

但是,不兼容的升级问题完全可以在最终的ANTLR4参考文献第5.6节中Ter提到的CSQL.g4无扫描解析器语法示例中重现。

'\*'=42
'+'=43

并且解析器语法在其规则中直接引用引用的令牌名称,如:

star: '*' ws? ;
plus: '+' ws? ;

这里的问题是,使用ANTLR4版本4.2和4.6从这样的语法生成了可编译的解析器类,而ANTLR V4.7.2和更高版本生成了带有大量错误的Java代码。

下面是ANTLR V4.6生成的可用CSQL Java类定义的一个片段:

 public static class ArgsContext extends ParserRuleContext {
      public List<ArgContext> arg() {
          return getRuleContexts(ArgContext.class);
      }
      public ArgContext arg(int i) {
          return getRuleContext(ArgContext.class,i);
      }
      public ArgsContext(ParserRuleContext parent, int invokingState) {
          super(parent, invokingState);
      }
      @Override public int getRuleIndex() { return RULE_args; }
      @Override
      public void enterRule(ParseTreeListener listener) {
          if ( listener instanceof CSQLListener ) ((CSQLListener)listener).enterArgs(this);
      }
      @Override
      public void exitRule(ParseTreeListener listener) {
          if ( listener instanceof CSQLListener ) ((CSQLListener)listener).exitArgs(this);
      }
 }
 public static class ArgsContext extends ParserRuleContext {
      public List<ArgContext> arg() {
          return getRuleContexts(ArgContext.class);
      }
      public ArgContext arg(int i) {
          return getRuleContext(ArgContext.class,i);
      }
      public List<TerminalNode> ','() { return getTokens(CSQL.','); }   // line 446
      public TerminalNode ','(int i) {                                  // line 447
          return getToken(CSQL.',', i);                                 // line 448
      }                                                                 // line 449
      public ArgsContext(ParserRuleContext parent, int invokingState) {
          super(parent, invokingState);
      }
      @Override public int getRuleIndex() { return RULE_args; }
      @Override
      public void enterRule(ParseTreeListener listener) {
          if ( listener instanceof CSQLListener ) ((CSQLListener)listener).enterArgs(this);
      }
      @Override
      public void exitRule(ParseTreeListener listener) {
          if ( listener instanceof CSQLListener ) ((CSQLListener)listener).exitArgs(this);
      }
 }
Syntax error on token "','", Identifier expected  CSQL.java     /CSQL/generated-sources  line 446  Java Problem
Syntax error on token "','", delete this token    CSQL.java     /CSQL/generated-sources  line 447  Java Problem
CSQL cannot be resolved to a variable   CSQL.java /CSQL/generated-sources     line 448  Java Problem
Syntax error on token ".", , expected   CSQL.java /CSQL/generated-sources     line 448  Java Problem

那么,为什么在ANTLR V4.7+中会出现向后不兼容的变化,我应该如何最好地解决这个问题呢?

共有1个答案

赵英资
2023-03-14

尝试定义一个grammarlexer.g4文件,而不是grammarlexer.tokens文件。(您仍然可以使用选项:{tokenVocab=grammarlexer;},就像创建grammarlexer.tokens文件一样)

T1 : ' ';
T2 : '\n';
T3 : '\r';
T4 : 'a';
T5 : 'b';

这将为您创建令牌名称。Antlr将允许在解析器语法规则中使用'a''\n'等,但将它们与lexer语法中的lexer规则名称匹配,并使用该名称(例如:当您的规则中有'a'时:T4,当您有'\n'),以便编译干净。只要charsaStokens生成相同的令牌值,就不必使用lexer。(不过,仔细考虑一下,该杠杆可能相当于您正在使用的CharsaStokens标记器,并保证标记数匹配。)

这似乎仍然可以实现令牌只是一个字符流的目标,并处理解析器规则中的所有内容。(并不比生成*.tokens文件更麻烦。两者都需要是所有有效字符的详尽列表。)

 类似资料:
  • 我对ANTLR相对来说是新的,所以请原谅我。 但是当我试图解析下面的表达式时 我最终出现以下错误: 第1:38行:'''处的令牌识别错误 第1:42行:'''处的令牌识别错误 规则r没有方法或者它有参数 规则'r'的意思是什么?我怎么能理解问题的原因呢?任何帮助都将不胜感激!

  • 我正在运行ANTLR4.2,并使用规范的C文法: https://github.com/ANTLR/grammars-v4/tree/master/C 我正在执行以下步骤:(使用ANTLR4书中的批处理文件) ANTLR C.G4 javac c*.java grun C compilationUnit-tokens test.C 其中test.c有以下代码: 传球: 失败:错误是:第3行:9在输

  • antl4是否支持允许用户指定新规则的自适应语法,例如强制函数声明中指定的参数数量? 示例:基本语言包括以下标记定义: 令牌#1定义为[a-z][0-9]* 大写为函数名保留,小写为传递给函数的变量保留。 用户可以“声明”Fxy,下面的每个F实例都必须有两个变量。我希望解析器执行“新规则”。 也许这是编译器中的标准公平,我知道我在C、python等中使用的编译器。当我没有为我在别处声明的函数传递正

  • 问题内容: 我最近不得不使用解析器来做一个项目。我下载ANTLR4并按照书中描述的步骤进行操作The Definitive ANTLR4 Reference。以下是我在命令行中键入的步骤: 一切正常,它生成我需要的java文件。但是,当我进入 它报告 无法将Hello加载为词法分析器或解析器。 我在Google上搜索了一些信息,但仍然无法确定发生了什么。 问题答案: 您通过在语法上运行ANTLR生

  • 我想将QRCode添加到我的android应用程序中。 我使用的是Android Studio 8.1。 我下载zxing核心。maven存储库中的jar文件(http://repo1.maven.org/maven2/com/google/zxing/core/3.1.0/) 我在清单xml文件中添加了以下行: 然后,我将jar文件添加到“lib”文件夹,并在gradle构建文件中添加为库: 编

  • 我必须在项目中使用QR扫描仪: 目前我正在使用QRCodeReaderView: 但是这个库的问题是: 我得到 java.lang.RuntimeException: 無法連接到相機服務 Exception 在Android 6.0中,如本问题所述:Android 6.0 RuntimeException:无法连接到相机服务 正如在那里的答案中所建议的那样,我试图将目标SDK版本降级到22,但效果