Browse Source

New task antlr. See www.antlr.org.

Submitted by:	Erik Meade <emeade@geekfarm.org>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268151 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 24 years ago
parent
commit
a18fbb4649
9 changed files with 1885 additions and 1 deletions
  1. +1
    -1
      WHATSNEW
  2. +9
    -0
      build.xml
  3. +60
    -0
      src/etc/testcases/taskdefs/optional/antlr/antlr.g
  4. +51
    -0
      src/etc/testcases/taskdefs/optional/antlr/antlr.xml
  5. +1166
    -0
      src/etc/testcases/taskdefs/optional/antlr/java.g
  6. +314
    -0
      src/etc/testcases/taskdefs/optional/antlr/java.tree.g
  7. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  8. +173
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java
  9. +110
    -0
      src/testcases/org/apache/tools/ant/taskdefs/optional/ANTLRTest.java

+ 1
- 1
WHATSNEW View File

@@ -4,7 +4,7 @@ Changes from Ant 1.2 to the current sources
Other changes:
--------------

* New tasks: propertyfile, depend
* New tasks: propertyfile, depend, antlr

* Added output attribute to <java>.



+ 9
- 0
build.xml View File

@@ -70,6 +70,7 @@
<available property="junit.present" classname="junit.framework.TestCase" />
<available property="ftp.present" classname="com.oroinc.net.ftp.FTPClient" />
<available property="starteam.present" classname="com.starbase.util.Platform" />
<available property="antlr.present" classname="antlr.Tool" />
</target>

<!-- =================================================================== -->
@@ -106,6 +107,7 @@
<exclude name="**/junit/*" unless="junit.present" />
<exclude name="**/FTP*.java" unless="ftp.present" />
<exclude name="**/AntStarTeam*.java" unless="starteam.present" />
<exclude name="**/ANTLR.java" unless="antlr.present" />
</javac>
<copy todir="${build.classes}">
@@ -324,6 +326,7 @@
<pathelement location="${lib.dir}/${name}.jar" />
<path refid="classpath" />
</classpath>
<exclude name="org/apache/tools/ant/taskdefs/optional/ANTLRTest.java" unless="antlr.present" />
</javac>
</target>

@@ -332,6 +335,7 @@
<!-- =================================================================== -->
<target name="runtests" depends="compiletests" if="junit.present">
<junit printsummary="no" haltonfailure="yes" fork="${junit.fork}">
<jvmarg value="-classic"/>
<classpath>
<pathelement location="${lib.dir}/${name}.jar" />
<pathelement location="${build.tests}" />
@@ -350,6 +354,9 @@
<!-- these depend on order -->
<exclude name="org/apache/tools/ant/taskdefs/GUnzipTest.java" />
<exclude name="org/apache/tools/ant/taskdefs/GzipTest.java" />

<!-- only run this test if ANTLR is installed -->
<exclude name="org/apache/tools/ant/taskdefs/optional/ANTLRTest.java" unless="antlr.present" />
</fileset>
</batchtest>

@@ -358,12 +365,14 @@
</junit>

<!-- clean up again -->
<delete dir="src/etc/testcases/taskdefs/optional/antlr/antlr.tmp" />
<delete dir="src/etc/testcases/taskdefs/taskdefs.tmp" />
<delete dir="src/etc/testcases/taskdefs.tmp" />
</target>

<target name="run.single.test" if="testcase" depends="compiletests">
<junit printsummary="no" haltonfailure="yes" fork="${junit.fork}">
<jvmarg value="-classic"/>
<classpath>
<pathelement location="${lib.dir}/${name}.jar" />
<pathelement location="${build.tests}" />


+ 60
- 0
src/etc/testcases/taskdefs/optional/antlr/antlr.g View File

@@ -0,0 +1,60 @@
class CalcParser extends Parser;
options {
buildAST = true; // uses CommonAST by default
}

expr
: mexpr (PLUS^ mexpr)* SEMI!
;

mexpr
: atom (STAR^ atom)*
;

atom: INT
;

class CalcLexer extends Lexer;

WS : (' '
| '\t'
| '\n'
| '\r')
{ _ttype = Token.SKIP; }
;

LPAREN: '('
;

RPAREN: ')'
;

STAR: '*'
;

PLUS: '+'
;

SEMI: ';'
;

protected
DIGIT
: '0'..'9'
;

INT : (DIGIT)+
;

class CalcTreeWalker extends TreeParser;

expr returns [float r]
{
float a,b;
r=0;
}
: #(PLUS a=expr b=expr) {r = a+b;}
| #(STAR a=expr b=expr) {r = a*b;}
| i:INT {r = (float)Integer.parseInt(i.getText());}
;


+ 51
- 0
src/etc/testcases/taskdefs/optional/antlr/antlr.xml View File

@@ -0,0 +1,51 @@
<?xml version="1.0"?>

<project name="antlr-test" basedir=".">

<property name="tmp.dir" value="antlr.tmp"/>


<target name="test1">
<antlr/>
</target>

<target name="test2">
<!-- delete the tmp directory, it may exists if a previous ANTLR test
failed. This in turn will cause this test to fail, as it tests
the build exception when the outputdirectory is invalid. -->
<deltree dir="${tmp.dir}"/>
<antlr target="antlr.g" outputdirectory="${tmp.dir}"/>
</target>

<target name="test3">
<mkdir dir="${tmp.dir}"/>
<antlr target="antlr.g" outputdirectory="${tmp.dir}"/>
</target>

<target name="test4">
<deltree dir="${tmp.dir}"/>
<mkdir dir="${tmp.dir}"/>
<antlr target="java.g" outputdirectory="${tmp.dir}"/>
<antlr target="java.tree.g" outputdirectory="${tmp.dir}"/>
</target>

<target name="test5">
<antlr target="java.tree.g" outputdirectory="${tmp.dir}" fork="yes"/>
</target>

<target name="test6">
<deltree dir="${tmp.dir}"/>
<!-- This tmp.dir needs to be deleted by the build file which executes this test. -->
<mkdir dir="${tmp.dir}"/>
<antlr target="java.g" outputdirectory="${tmp.dir}" />
<antlr dir="${tmp.dir}"
target="java.tree.g"
outputdirectory="${tmp.dir}"
fork="yes"/>
</target>

<target name="test7">
<antlr target="antlr.xml"/>
</target>

</project>

+ 1166
- 0
src/etc/testcases/taskdefs/optional/antlr/java.g
File diff suppressed because it is too large
View File


+ 314
- 0
src/etc/testcases/taskdefs/optional/antlr/java.tree.g View File

@@ -0,0 +1,314 @@
/** Java 1.2 AST Recognizer Grammar
*
* Author:
* Terence Parr parrt@jguru.com
*
* Version tracking now done with following ID:
*
* $Id$
*
* This grammar is in the PUBLIC DOMAIN
*
* BUGS
*/
class JavaTreeParser extends TreeParser;

options {
importVocab = Java;
}

compilationUnit
: (packageDefinition)?
(importDefinition)*
(typeDefinition)*
;

packageDefinition
: #( PACKAGE_DEF identifier )
;

importDefinition
: #( IMPORT identifierStar )
;

typeDefinition
: #(CLASS_DEF modifiers IDENT extendsClause implementsClause objBlock )
| #(INTERFACE_DEF modifiers IDENT extendsClause interfaceBlock )
;

typeSpec
: #(TYPE typeSpecArray)
;

typeSpecArray
: #( ARRAY_DECLARATOR typeSpecArray )
| type
;

type: identifier
| builtInType
;

builtInType
: "void"
| "boolean"
| "byte"
| "char"
| "short"
| "int"
| "float"
| "long"
| "double"
;

modifiers
: #( MODIFIERS (modifier)* )
;

modifier
: "private"
| "public"
| "protected"
| "static"
| "transient"
| "final"
| "abstract"
| "native"
| "threadsafe"
| "synchronized"
| "const"
| "volatile"
;

extendsClause
: #(EXTENDS_CLAUSE (identifier)* )
;

implementsClause
: #(IMPLEMENTS_CLAUSE (identifier)* )
;


interfaceBlock
: #( OBJBLOCK
( methodDecl
| variableDef
)*
)
;
objBlock
: #( OBJBLOCK
( ctorDef
| methodDef
| variableDef
| typeDefinition
| #(STATIC_INIT slist)
| #(INSTANCE_INIT slist)
)*
)
;

ctorDef
: #(CTOR_DEF modifiers methodHead slist)
;

methodDecl
: #(METHOD_DEF modifiers typeSpec methodHead)
;

methodDef
: #(METHOD_DEF modifiers typeSpec methodHead (slist)?)
;

variableDef
: #(VARIABLE_DEF modifiers typeSpec variableDeclarator varInitializer)
;

parameterDef
: #(PARAMETER_DEF modifiers typeSpec IDENT )
;

objectinitializer
: #(INSTANCE_INIT slist)
;

variableDeclarator
: IDENT
| LBRACK variableDeclarator
;

varInitializer
: #(ASSIGN initializer)
|
;

initializer
: expression
| arrayInitializer
;

arrayInitializer
: #(ARRAY_INIT (initializer)*)
;

methodHead
: IDENT #( PARAMETERS (parameterDef)* ) (throwsClause)?
;

throwsClause
: #( "throws" (identifier)* )
;

identifier
: IDENT
| #( DOT identifier IDENT )
;

identifierStar
: IDENT
| #( DOT identifier (STAR|IDENT) )
;

slist
: #( SLIST (stat)* )
;

stat: typeDefinition
| variableDef
| expression
| #(LABELED_STAT IDENT stat)
| #("if" expression stat (stat)? )
| #( "for"
#(FOR_INIT (variableDef | elist)?)
#(FOR_CONDITION (expression)?)
#(FOR_ITERATOR (elist)?)
stat
)
| #("while" expression stat)
| #("do" stat expression)
| #("break" (IDENT)? )
| #("continue" (IDENT)? )
| #("return" (expression)? )
| #("switch" expression (caseGroup)*)
| #("throw" expression)
| #("synchronized" expression stat)
| tryBlock
| slist // nested SLIST
| EMPTY_STAT
;

caseGroup
: #(CASE_GROUP (#("case" expression) | "default")+ slist)
;

tryBlock
: #( "try" slist (handler)* (#("finally" slist))? )
;

handler
: #( "catch" parameterDef slist )
;

elist
: #( ELIST (expression)* )
;

expression
: #(EXPR expr)
;

expr: #(QUESTION expr expr expr) // trinary operator
| #(ASSIGN expr expr) // binary operators...
| #(PLUS_ASSIGN expr expr)
| #(MINUS_ASSIGN expr expr)
| #(STAR_ASSIGN expr expr)
| #(DIV_ASSIGN expr expr)
| #(MOD_ASSIGN expr expr)
| #(SR_ASSIGN expr expr)
| #(BSR_ASSIGN expr expr)
| #(SL_ASSIGN expr expr)
| #(BAND_ASSIGN expr expr)
| #(BXOR_ASSIGN expr expr)
| #(BOR_ASSIGN expr expr)
| #(LOR expr expr)
| #(LAND expr expr)
| #(BOR expr expr)
| #(BXOR expr expr)
| #(BAND expr expr)
| #(NOT_EQUAL expr expr)
| #(EQUAL expr expr)
| #(LT expr expr)
| #(GT expr expr)
| #(LE expr expr)
| #(GE expr expr)
| #(SL expr expr)
| #(SR expr expr)
| #(BSR expr expr)
| #(PLUS expr expr)
| #(MINUS expr expr)
| #(DIV expr expr)
| #(MOD expr expr)
| #(STAR expr expr)
| #(INC expr)
| #(DEC expr)
| #(POST_INC expr)
| #(POST_DEC expr)
| #(BNOT expr)
| #(LNOT expr)
| #("instanceof" expr expr)
| #(UNARY_MINUS expr)
| #(UNARY_PLUS expr)
| primaryExpression
;

primaryExpression
: IDENT
| #( DOT
( expr
( IDENT
| arrayIndex
| "this"
| "class"
| #( "new" IDENT elist )
)
| #(ARRAY_DECLARATOR type)
| builtInType ("class")?
)
)
| arrayIndex
| #(METHOD_CALL primaryExpression elist)
| #(TYPECAST typeSpec expr)
| newExpression
| constant
| "super"
| "true"
| "false"
| "this"
| "null"
| typeSpec // type name used with instanceof
;

arrayIndex
: #(INDEX_OP primaryExpression expression)
;

constant
: NUM_INT
| CHAR_LITERAL
| STRING_LITERAL
| NUM_FLOAT
;

newExpression
: #( "new" type
( newArrayDeclarator (arrayInitializer)?
| elist
)
)
;

newArrayDeclarator
: #( ARRAY_DECLARATOR (newArrayDeclarator)? (expression)? )
;

+ 1
- 0
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

@@ -66,6 +66,7 @@ native2ascii=org.apache.tools.ant.taskdefs.optional.Native2Ascii
perforce=org.apache.tools.ant.taskdefs.optional.perforce.P4sync
propertyfile=org.apache.tools.ant.taskdefs.optional.PropertyFile
depend=org.apache.tools.ant.taskdefs.optional.depend.Depend
antlr=org.apache.tools.ant.taskdefs.optional.ANTLR

# deprecated ant tasks (kept for back compatibility)
javadoc2=org.apache.tools.ant.taskdefs.Javadoc


+ 173
- 0
src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java View File

@@ -0,0 +1,173 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.taskdefs.optional;

import java.io.*;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.types.*;
/**
* @author Erik Meade, emeade@geekfarm.org
*/
public class ANTLR extends Task {

private CommandlineJava commandline = new CommandlineJava();
private File target;
private File outputDirectory;
private boolean fork = false;
private File dir;

public ANTLR() {
commandline.setVm("java");
commandline.setClassname("antlr.Tool");
}

public void setTarget(File target) {
log("Setting target to: " + target.toString(), Project.MSG_VERBOSE);
this.target = target;
}

public void setOutputdirectory(File outputDirectory) {
log("Setting output directory to: " + outputDirectory.toString(), Project.MSG_VERBOSE);
this.outputDirectory = outputDirectory;
}

public void setFork(boolean s) {
this.fork = s;
}

/**
* The working directory of the process
*/
public void setDir(File d) {
this.dir = d;
}


public void execute() throws BuildException {
validateAttributes();

//TODO: use ANTLR to parse the grammer file to do this.
if (target.lastModified() > getGeneratedFile().lastModified()) {
commandline.createArgument().setValue("-o");
commandline.createArgument().setValue(outputDirectory.toString());
commandline.createArgument().setValue(target.toString());

if (fork) {
log("Forking " + commandline.toString(), Project.MSG_VERBOSE);
int err = run(commandline.getCommandline());
if (err == 1) {
throw new BuildException("ANTLR returned: "+err, location);
}
}
else {
Execute.runCommand(this, commandline.getCommandline());
}
}
}

private void validateAttributes() throws BuildException{
if (target == null || !target.isFile()) {
throw new BuildException("Invalid target: " + target);
}

// if no output directory is specified, used the target's directory
if (outputDirectory == null) {
String fileName = target.toString();
setOutputdirectory(new File(target.getParent()));
}
if (!outputDirectory.isDirectory()) {
throw new BuildException("Invalid output directory: " + outputDirectory);
}
if (fork && (dir == null || !dir.isDirectory())) {
throw new BuildException("Invalid working directory: " + dir);
}
}

private File getGeneratedFile() throws BuildException {
String generatedFileName = null;
try {
BufferedReader in = new BufferedReader(new FileReader(target));
String line;
while ((line = in.readLine()) != null) {
int extendsIndex = line.indexOf(" extends ");
if (line.startsWith("class ") && extendsIndex > -1) {
generatedFileName = line.substring(6, extendsIndex).trim();
break;
}
}
in.close();
} catch (Exception e) {
throw new BuildException("Unable to determine generated class");
}
if (generatedFileName == null) {
throw new BuildException("Unable to determine generated class");
}
return new File(outputDirectory, generatedFileName + ".java");
}

private int run(String[] command) throws BuildException {
Execute exe = new Execute(new LogStreamHandler(this, Project.MSG_INFO,
Project.MSG_WARN), null);
exe.setAntRun(project);
exe.setWorkingDirectory(dir);
exe.setCommandline(command);
try {
return exe.execute();
} catch (IOException e) {
throw new BuildException(e, location);
}
}
}

+ 110
- 0
src/testcases/org/apache/tools/ant/taskdefs/optional/ANTLRTest.java View File

@@ -0,0 +1,110 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.taskdefs.optional;

import java.io.*;
import org.apache.tools.ant.taskdefs.TaskdefsTest;
/**
* @author Erik Meade <emeade@geekfarm.org>
*/
public class ANTLRTest extends TaskdefsTest {

private final static String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/antlr/";

public ANTLRTest(String name) {
super(name);
}

public void setUp() {
configureProject(TASKDEFS_DIR + "antlr.xml");
}

public void test1() {
expectBuildException("test1", "required argument, target, missing");
}

public void test2() {
expectBuildException("test2", "Invalid output directory");
}

public void test3() {
executeTarget("test3");
File outputDirectory = new File(TASKDEFS_DIR + "antlr.tmp");
String[] calcFiles = outputDirectory.list(new CalcFileFilter());
assert(5 == calcFiles.length);
}

public void test4() {
expectBuildException("test4", "ANTLR exited with an error code of 1 ( try forking )");
}

public void test5() {
expectBuildException("test5", "Invalid working directory");
}

public void test6() {
executeTarget("test6");
}

public void test7() {
expectBuildException("test7", "Unable to determine generated class");
}
}

class CalcFileFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
return name.startsWith("Calc");
}
}

Loading…
Cancel
Save