2015-06-04 14 views
12

próbuję użyć Gradle wtyczki antlr, ale uruchomić na kilka problemów.Generowanie ANTLR4 pliki gramatyki z deklaracji pakietu w Gradle

Mam plik gramatyki zwany wls.g4:

grammar WlsScript; 

@header { 
    package hu.pmi.wls.antlr.ws; 
} 

program 
    : 'statementList'? EOF 
    ; 

// Several more grammar and lexer rules 

(. Uwaga: zrobiłem statementList do hasła tylko do prawidłowego grammer bez włączając całą gramatykę ;-))

Plik ten znajduje się w katalogu/src/main/antlr (jako domyślny folder źródłowy plików gramatyki produkcji antlr).

Oto urywek z build.gradle:

project('common') { 

    apply plugin: 'antlr' 

    dependencies { 
     // Some dependencies 

     antlr "org.antlr:antlr4:4.5" 
    } 
} 

Kiedy używam generateGrammarSource Gradle zadania (comming od antlr plugin) do generowania plików źródłowych generuje pliki w folderze build/generated-src/antlr/main który jest domyślnie.

Co jest nie tak, że nie tworzy folderów pakietu java (hu/pmi/wls/antlr/ws w naszym przypadku), więc źródło będzie niepoprawnie umieszczone w środowisku Eclipse.

Moim głównym pytaniem jest, jak mogę zmusić zadanie do generowania plików źródłowych w sposób pakiet zorganizowany? Innymi słowy, w jaki sposób mogę skonfigurować zadanie gradle, aby używać deklaracji pakietu z gramatyki?

Dzięki!

+1

Mam taki sam problem z ANTLR 4.5. Korzystam tylko z org.antlr.v4.Tool do przetworzenia pliku .g4 i nie mogłem go wygenerować źródła Java w strukturze folderów odpowiadających im nazw pakietów. Może generować pliki zgodnie z katalogiem określonym przez opcję "-o". Tak więc jedynym sposobem jest jawne określenie struktury folderu pakietów w opcji "-o". Nie znam Gradle'a, ale szukam sposobu, aby Gradle mógł przekazać opcje podczas wykonywania narzędzia ANTLR. – anonymous

Odpowiedz

9

Miałem dokładnie to samo pytanie i mogłem zmienić outputDirectory używany przez AntlrTask, aby uzyskać tam nazwę pakietu.

generateGrammarSource { 
    outputDirectory = new File("${project.buildDir}/generated-src/antlr/main/net/example".toString()) 
} 

Nie znalazłem łatwego sposobu na wyodrębnienie pakietu gramatycznego z plików, więc musiałem je zakodować w zadaniu.

+0

Jak pogodzić to w IDE? Mógłbym napisać coś w stylu 'import whatever.gen.MyParser' i' MyParser x = new MyParser (...) ', ale ide krzyczy o tym, jak nie może znaleźć źródła - ponieważ źródło jest" w samą porę " ", z braku lepszego zdania. Może lepiej jest mieć folder gen-src, który został potwierdzony przez IDE, ale zignorowany pod kontrolą wersji? czy to jest sprzeczne z konwencjami? – Groostav

+1

Możesz dodać katalog generowany-src jako katalog źródłowy w IDE (używam IntelliJ) –

0

mam podobny problem przy użyciu antlr3. Można ustalić pozycje dołączenie przetwarzanie post do zadania generateGrammarSource:

/* Antlr generated files have wrong position so fix it with a post generation processing */ 
import groovy.io.FileType 
generateGrammarSource << { 
    logger.info("Antlr doesn't produce files to rigth place. Fix using package declaration") 
    def move = [/*File wrong position*/:/*File rigth position*/] 
    generateGrammarSource.outputDirectory.eachFileMatch(FileType.FILES, ~/.*\.java/) { f -> 
     def pkg = f.readLines().find { it.trim() =~ /^package/ } 
     if (pkg) { 
      pkg = pkg.split(' ')[1].replace(';','') 
      pkg = pkg.replace('.','/') 
      move.put(f,new File("${generateGrammarSource.outputDirectory}/$pkg/${f.name}")) 
     } 
    } 
    move.each { s,t -> 
    logger.info("Moving ${s.name} to right location ..") 
    t.parentFile.mkdirs() 
    s.renameTo(t.absolutePath) 
} 
2

dodać do swojej podprojektu build.gradle

generateGrammarSource { 
    outputDirectory = file("src/main/java/com/example/parser") 
} 

dodać do swojej gramatyki po „gramatyki”;

@header { 
    package com.example.parser; 
} 

Przetestowane i pracy z Java8 grammar from antlr example grammars

dodatkowy link (ów):

Here is a short guide of the Antlr plugin from docs.gradle.org

Nie przetestowane podczas oddawania go w macierzystym projekcie jak to wygląda jak ty , ale powinno to być wystarczająco łatwe do rozszerzenia, aby to zrobić. (Staram się zachować projektu nadrzędnego pusty innych niż repozytoria do użytku.)

0

transferu plików generowane ANTLR do folderu projektu i ZZZ podkatalogu.

antlr.g4

....

@header { 
package XXX.YYY.ZZZ; 
} 

.....

build.gradle

group 'XXX' 
version '0.0.1' 

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

mainClassName = 'XXX.YYY.Test' 
final antlr4Version = '4.7' 
final antlrGen = 'gen' 
final baseDir = 'src/main/java' 

repositories { 
    mavenCentral() 
} 

dependencies { 
    antlr "org.antlr:antlr4:"+antlr4Version 
} 

generateGrammarSource { 
    outputDirectory = file(antlrGen) 
    maxHeapSize = '64m' 
    arguments += ['-visitor', '-long-messages'] 
} 

generateGrammarSource.doLast { 
    moveAntlrGeneratedFilesToTheirPackages(source, antlrGen, baseDir) 
} 

def moveAntlrGeneratedFilesToTheirPackages(FileTree grammarFiles, generatedFolder, destFolder) { 
    grammarFiles.each {File file -> 
     final grammarName = file.name.lastIndexOf('.') >= 0 ? file.name[0 .. file.name.lastIndexOf('.') - 1] : file.name 
     final grammarPackage = extractPackageNameFromGrammerFile(file) 
     copy { 
      from generatedFolder 
      include "${grammarName}*.*" 
      into destFolder + "/" + grammarPackage.replaceAll("\\.", "/") 
     } 
    } 
    project.delete fileTree(generatedFolder).include('*.*') 
} 

def extractPackageNameFromGrammerFile(File grammarFile) { 
    def grammarPackage = "unknown.package" 
    def packageRegex = ~/[ ]*package[ ]*([a-zA-Z]+[a-zA-Z0-9.-_]*)[ ]*;/ 
    grammarFile.eachLine { line -> 
     def matcher = packageRegex.matcher(line) 
     if (matcher.find()){ 
      grammarPackage = matcher.group(1) 
     } 
    } 
    return grammarPackage 
} 

jar { 
    baseName = 'XXX.YYY' 
    version = '1.0.0' 
    manifest.attributes('Main-Class': mainClassName); 
} 

task wrapper(type: Wrapper) { 
} 

Test.java

package XXX.YYY; 

import java.lang.Exception; 
import org.antlr.v4.runtime.CharStreams; 
import org.antlr.v4.runtime.CommonTokenStream; 
import org.antlr.v4.runtime.tree.ParseTree; 
import XXX.YYY.ZZZ.*; 

public static void main(String[] args) throws Exception { 

...

Powiązane problemy