【问题标题】:How can I import an ANTLR lexer grammar into another grammar using Gradle 2.10?如何使用 Gradle 2.10 将 ANTLR 词法分析器语法导入另一个语法?
【发布时间】:2016-02-24 15:01:12
【问题描述】:

我一直在通过 Terence Parr 的 The Definitive ANTLR 4 Reference 了解 ANTLR 4,到目前为止,我一直在使用 Gradle 2.10 及其内置的 ANTLR 插件来关注它。但是,我在获取从第 4 章第 38-41 页改编的一些代码以与我的 Gradle 构建脚本正常工作时遇到了一些麻烦。 (我使用 Gradle 而不是直接使用 ANTLR 的原因是因为我想最终将 ANTLR 集成到我为我的论文而制作的 Java Web 应用程序中,我强烈希望为此使用构建工具,所以我可以自动化 ANTLR-to-Java 代码生成过程并轻松管理我的依赖项。)

我创建了两个 ANTLR 4 语法(我已将其粘贴到本问题的末尾):src/main/antlr/org/jbduncan/Expr.g4(标准语法)和 src/main/antlr/org/jbduncan/CommonLexerRules.g4(词法分析器语法),其中 Expr.g4 取决于 CommonLexerRules.g4通过import CommonLexerRules 声明。但是,当我尝试使用我的 build.gradle 在命令行中运行gradlew generateGrammarSource 时(也与我的 gradle.properties 一起粘贴到这个问题的末尾),我收到以下错误:

12:45:21: Executing external task 'generateGrammarSource'...
:generateGrammarSource
error(110): org\jbduncan\Expr.g4:3:7: can't find or load grammar CommonLexerRules
warning(125): org\jbduncan\Expr.g4:12:11: implicit definition of token NEWLINE in parser
warning(125): org\jbduncan\Expr.g4:13:6: implicit definition of token ID in parser
warning(125): org\jbduncan\Expr.g4:19:6: implicit definition of token INT in parser
:generateGrammarSource FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':generateGrammarSource'.
> There was 1 error during grammar generation

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 3.166 secs
There was 1 error during grammar generation
12:45:24: External task execution finished 'generateGrammarSource'.

查看此错误消息,在我看来,Gradle 的 ANTLR 插件能够找到 Expr.g4,但不知何故无法找到 CommonLexerRules.g4

我尝试使用几个外部 Gradle 插件(https://github.com/melix/antlr4-gradle-pluginhttps://github.com/Abnaxos/gradle-antlr4-plugin)而不是内置插件来解决此错误,但是当我尝试每个插件时,它们都引入了自己的问题我无法解决。

使用直接从 ANTLR 网站下载的 ANTLR 4.5.2 jar 确实让我可以毫无问题地编译我的两个语法,但正如我之前讨论的,这对我来说是一个非常不受欢迎的选择,因为我'必须手动编译我的语法,而我相信 Gradle 可以为我自动完成。

我的问题是:如何解决上述错误并让 Gradle 将我的词法分析器语法导入其他语法?


build.gradle

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'antlr'

sourceCompatibility = 1.8
targetCompatibility = 1.8

[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

group = 'org.jbduncan'
version = '1.0-SNAPSHOT'
mainClassName = 'org.jbduncan.Application'

repositories {
    jcenter()
}

dependencies {
    antlr "org.antlr:antlr4:$antlrVersion"
    compile "com.google.guava:guava:$guavaVersion"
    testCompile "com.google.guava:guava-testlib:$guavaVersion"
    testCompile "com.google.truth:truth:$truthVersion"
    testCompile "junit:junit:$junitVersion"
}

// Send all generated source code to a directory other than build/, to workaround an issue in
// IntelliJ IDEA where it fails to recognise source files in build/.
def generatedJavaSourcesDir = 'src/generated/java'

generateGrammarSource {
    arguments += ['-visitor']
    outputDirectory = file(generatedJavaSourcesDir)
}

sourceSets {
    main {
        java {
            srcDir generatedJavaSourcesDir
        }
    }
}

clean {
    delete generatedJavaSourcesDir
}

task wrapper(type: Wrapper) {
    distributionUrl = "http://services.gradle.org/distributions/gradle-$gradleVersion-bin.zip"
}

gradle.properties

gradleVersion=2.10

# Dependency versions
antlrVersion=4.5
guavaVersion=19.0
junitVersion=4.12
truthVersion=0.28

src/main/antlr/org/jbduncan/Expr.g4

grammar Expr;

import CommonLexerRules; // includes all rules from CommonLexerRules.g4

@header {
    package org.jbduncan;
}

/** The start rule; begin parsing here. */
prog: stat+;

stat: expr NEWLINE # printExpr
    | ID '=' expr NEWLINE # assign
    | NEWLINE # blank
    ;

expr: expr op=('*'|'/') expr # MulDiv
    | expr op=('+'|'-') expr # AddSub
    | INT # int
    | ID # id
    | '(' expr ')' # parens
    ;

MUL: '*'; // assigns token name to '*' used above in grammar
DIV: '/';
ADD: '+';
SUB: '-';

src/main/antlr/org/jbduncan/CommonLexerRules.g4

lexer grammar CommonLexerRules; // note "lexer grammar"

ID: [a-zA-Z]+ ; // match identifiers
INT: [0-9]+ ; // match integers
NEWLINE: '\r'? '\n' ; // return newlines to parser (is end-statement signal)
WS: [ \t] -> skip ; // toss out whitespace

src/main/java/org/jbduncan/Application.java

package org.jbduncan;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public final class Application {
  public static void main(String[] args) throws IOException {
    String inputFile = (args.length > 0) ? args[0] : null;

    InputStream inputStream = (inputFile == null) ? System.in : new FileInputStream(inputFile);
    ANTLRInputStream input = new ANTLRInputStream(inputStream);
    ExprLexer lexer = new ExprLexer(input);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    ExprParser parser = new ExprParser(tokens);
    ParseTree tree = parser.prog(); // parse; start at prog

    System.out.println(tree.toStringTree(parser)); // print tree as text
  }
}

【问题讨论】:

  • 你为什么用import CommonLexerRules;而不是options { tokenVocab = CommonLexerRules; }
  • @KvanTTT:仅仅是因为我不知道options 的存在,因为我还没有在书中提到它们(如果它们被覆盖的话) .我要睡觉了,我现在不打算测试你的建议,但我明天应该有时间,所以如果它适合我​​,我会告诉你的。
  • @KvanTTT:嗯,它似乎对我不起作用。为选项交换导入并运行 gradlew clean build 会产生一个错误,它声称找不到 src\generated\java\CommonLexerRules.tokens(即使我可以在我机器上的项目文件夹中看到它)。
  • 解析器生成需要令牌文件...
  • 我想知道 Gradle 的 ANTLR 插件无法找到 CommonLexerRules.g4CommonLexerRules.tokens 是否在某些方面相关......您还有其他建议 @KvanTTT 吗?

标签: java gradle antlr antlr4


【解决方案1】:

在 Gradle forum 上发布我的问题后,我设法找到了答案:

generateGrammarSource {
  arguments << "-lib" << "src/main/antlr/org/jbduncan" 
}

其中"src/main/antlr/org/jbduncan" 是您的antlr .g4 库的路径。

【讨论】:

    猜你喜欢
    • 2011-01-30
    • 2021-11-18
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多