本文介绍了如何使用 Gradle 2.10 将 ANTLR 词法分析器语法导入另一个语法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在通过 Terence Parr 的权威的 ANTLR 4 参考了解 ANTLR 4,到目前为止我一直在使用 Gradle 2.10 及其内置的 ANTLR 插件.但是,我在获取一些从第 4 章第 38-41 页改编的代码以与我的 Gradle 构建脚本一起正常工作时遇到了一些麻烦.(我使用 Gradle 而不是直接使用 ANTLR 的原因是我想最终将 ANTLR 集成到我正在为我的论文制作的 Java Web 应用程序中,并且我非常喜欢为此使用构建工具我可以自动执行 ANTLR 到 Java 的代码生成过程并轻松管理我的依赖项.)

I've been learning about ANTLR 4 with Terence Parr's The Definitive ANTLR 4 Reference, which I've been following so far using Gradle 2.10 and its built-in ANTLR plugin. However I'm having some trouble getting some code which I adapted from Chapter 4, pp. 38-41 to work properly with my Gradle build script. (The reason I'm using Gradle, rather than ANTLR directly, is because I want to eventually integrate ANTLR into a Java web application which I'm making for my dissertation, and I'd strongly prefer to use a build tool for this so I can automate the ANTLR-to-Java code generation process and easily manage my dependencies.)

我创建了两个 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),我收到以下错误:

I've created two ANTLR 4 grammars (which I've pasted towards the end of this question): src/main/antlr/org/jbduncan/Expr.g4 (a standard grammar) and src/main/antlr/org/jbduncan/CommonLexerRules.g4 (a lexer grammar), where Expr.g4 depends on CommonLexerRules.g4 via an import CommonLexerRules statement. But when I try to run gradlew generateGrammarSource at the command-line with my build.gradle (also pasted towards the end of this question along with my gradle.properties), I get the following error:

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.

Looking at this error message, it seems to me that Gradle's ANTLR plugin is able to find Expr.g4 but is somehow not able to find CommonLexerRules.g4.

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

I've made an attempt to resolve this error using a couple of external Gradle plugins (https://github.com/melix/antlr4-gradle-plugin and https://github.com/Abnaxos/gradle-antlr4-plugin) instead of the built-in one, but when I tried each of them, they introduced their own problems which I wasn't able to resolve.

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

Using the ANTLR 4.5.2 jar downloaded straight from the ANTLR website does let me to compile my two grammars without problems, but as I discussed earlier this is a really undesirable option for me, as I'd have to compile my grammars manually whereas I believe Gradle could do it automatically for me.

我的问题是:如何解决上述错误并让 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
  }
}

推荐答案

我在 Gradle 上发布问题后设法找到了答案 论坛:

I managed to find an answer to my question after posting it on the Gradle forum:

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

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

where "src/main/antlr/org/jbduncan" is a path with your antlr .g4 library.

这篇关于如何使用 Gradle 2.10 将 ANTLR 词法分析器语法导入另一个语法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 10:20