[antlr-interest] Ant 1.4.1 patch + supergrammars

Bogdan Mitu bogdan_mt at yahoo.com
Wed May 29 06:36:40 PDT 2002


Hi Ant users,

Attached is a patch for Ant 1.4.1 (the current stable Ant version). Aply
this patch to the "optional" package of Ant (and don't forget to put ANTLR
in your classpath, if it's not already there). The previous post was
intended for Ant developers, and worked only with Ant 1.5.1beta. The only
source that is different is ANTLR.java, also attached here. When porting
back the patch to Ant 1.4.1, i included (but not verified) the changes of
Silvain Piree to deal with up to 3 supergrammars. (Silvain, can you check
the supergrammar stuff is working, please?)

Happy ANTLR-ing with Ant,
Bogdan

P.S.
I will try to find a more general way to specify supergrammars - filesets or
something like this, but it may take some time. 

--- Silvain Piree <s.piree at enneya.com> wrote:
> Attached you'll find the patched ANTLR task for ANT.
> It's a quick&dirty solution which adds attributes "glib", "glib2" and
> "glib3", but it gets the job done.
> 
> Silvain
> 
> ----- Original Message -----
> From: "Bogdan Mitu" <bogdan_mt at yahoo.com>
> To: <antlr-interest at yahoogroups.com>
> Sent: Tuesday, May 28, 2002 10:13 AM
> Subject: Re: [antlr-interest] ANTLR and ANT
> 
> 
> > Hi Silvain,
> >
> > If I remember correctly, glib=..." is a command-line-only option. You
> > probably added new attributes to the ANTLR task. My modifications don't
> deal
> > with supergrammars (in fact I don't use them, I prefer to use literate
> > programming to produce different variations of a grammar). But your
> changes
> > and mine can be merged. To make more clear what modifications I made,
> here
> > is a fragment from my post to ant-dev:
> >
> > >>>
> > Working with the ANTLR task I saw that it (the ANTLR task) is somehow
> > limited when it tries to determine if the source grammar is "dirty" or
> not:
> >
> > - It considers the output of ANTLR to be one file per grammar, while in
> fact
> > there are 2 (or even 3): XxxParser.java, XxxParserTokenTypes.java and
> > possibly XxxParserTokenTypes.txt. If any of one is missing, the grammar
> > should be recompiled, which currently happens only for XxxParser.java.
> >
> > - An ANTLR file can contain more than one grammar (any combination of
> lexer,
> > parser and tree parser grammars). Once again, multiple output files, and
> > each of them missing should trigger the recompilation of the grammar.
> >
> > - ANTLR grammars can export/import token lists through "vocabulary
> files" -
> > XxxTokenTypes.txt. If the imported file is newer than the grammar file,
> the
> > grammar should be recompiled to include the correct tokens in generated
> > code.
> >
> > The main problem lays in the method getGeneratedFile(), which returns
> only
> > one file, while in fact we need two lists of files, ones that are
> results
> of
> > the grammar, and should be *older* than the grammar, and a list of
> imported
> > files, which should be *younger* than the grammar file.
> > <<<
> >
> > The new task parses the grammar file to determine all generated files
> and
> > all imported files, so that it can make a better decision. It doesn't
> know
> > anything about supergrammars. And you're right, it should. If you send
> me
> > your changes, I will try to incorporate them.
> >
> > Regards,
> > Bogdan
> >
> >
> > --- Silvain Piree <s.piree at enneya.com> wrote:
> > >
> > > Bogdan,
> > >
> > > > I wrote a new ANTLR task, which uses a parser to analyze all
> > > > dependencies, and sent it to ant-dev. However, the process of
> > > > review/adoption is very slow, ANTLR not being their top priority.
> > > > If someone is interested, I can post the patch.
> > >
> > > I've also made some small changes to the ANTLR task from ANT:
> > > I've added the ability to specify the location of base grammars
> > > from which to inherit using "glib=...", "glib2=...", etc.
> > >
> > > I've also added some checking to see if the base grammars are
> > > more recent than the grammar to be processed, so ANTLR
> > > is only activated when really needed. Works fine for me.
> > >
> > > In what way do your changes of the ANTLR task solve that problem.
> > > Most noteably, how do you know where the base grammars are
> > > located? In my case they are in several different directories.
> > >
> > > Kind greetings, Silvain
> > >
> > >
> > >
> > >
> > >
> > > Your use of Yahoo! Groups is subject to
> http://docs.yahoo.com/info/terms/
> > >
> > >
> > >
> >
> >
> > __________________________________________________
> > Do You Yahoo!?
> > Yahoo! - Official partner of 2002 FIFA World Cup
> > http://fifaworldcup.yahoo.com
> >
> >
> >
> > Your use of Yahoo! Groups is subject to
> http://docs.yahoo.com/info/terms/
> >
> >
> >
> 
>  
> 
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
> 
> 

> ATTACHMENT part 2 application/octet-stream name=ANTLR.java



__________________________________________________
Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com
 

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: Ant_1.4.1_patch.zip
Type: application/x-zip-compressed
Size: 15362 bytes
Desc: Ant_1.4.1_patch.zip
Url : http://www.antlr.org/pipermail/antlr-interest/attachments/20020529/563bee74/Ant_1.4.1_patch.bin
-------------- next part --------------
/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2002 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", "Ant", 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 at 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.antlr;

import java.io.*;
import java.util.*;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.types.*;
/**
 * @author Erik Meade, emeade at geekfarm.org
 * @author <a href="mailto:s.piree at enneya.com">Silvain Piree</a>
 * @author <a href="mailto:bogdan_mt at yahoo.com">Bogdan Mitu</a>
 */
public class ANTLR extends Task {

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

    /** list of files generated by the current grammar file */
    private ArrayList generatedList = null;

    /** list of files imported by the current grammar file */
    private ArrayList importedList = null;


    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;
    }

    public void setGlib(File glib) {
        this.glib = glib;
    }
    public void setGlib2(File glib) {
        this.glib2 = glib;
    }
    public void setGlib3(File glib) {
        this.glib3 = glib;
    }

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


    public void execute() throws BuildException {
        validateAttributes();
        if (isTargetDirty()) {
            //
            // First we delete the affected files.
            // There seems to be a bug in ANTLR, at least in version 2.7.2a1,
            // so we need this workaround.
            //
            String generatedFileName;
            File generatedFile;
            for (int i = 0; i < generatedList.size(); i++) {
                generatedFileName = (String) generatedList.get(i);
                generatedFile = new File(outputDirectory, generatedFileName);
                generatedFile.delete();
            }

            if (glib != null) {
	            commandline.createArgument().setValue("-glib");
                String argument = new String(glib.getAbsolutePath());
                if (glib2 != null) argument = argument + ";" + glib2.getAbsolutePath();
                if (glib3 != null) argument = argument + ";" + glib3.getAbsolutePath();
                commandline.createArgument().setValue(argument);
			}

            //
            // Recompile the grammar.
            //
            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, use 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);
        }
    }

    /** Returns <code>true</code> if the target should be recompiled */ 
    private boolean isTargetDirty() {
        boolean isDirty = false;
        ANTLRParser parser = null;
        try {
            BufferedReader in = new BufferedReader(new FileReader(target));
            parser = new ANTLRParser(new ANTLRLexer(in));
            parser.grammar();
            in.close();
        } catch (Exception e) {
            // throw new BuildException("Unable to analize source file " + target.toString());				
			generatedList = new ArrayList();  // It is better to compile the grammar with ANTLR 
			return isDirty = true;	          // to get real error messages.
        }
        generatedList = parser.getGeneratedList();
        importedList = parser.getImportedList();

        String generatedFileName = null;
        File generatedFile = null;
        String importedFileName = null;
        File importedFile = null;
        int i;

        long importModifTime = 0;
        for (i = 0; i < importedList.size(); i++) {
            if (importedList.get(i) != null) {
                importedFileName = (String) importedList.get(i);
                importedFile = new File(outputDirectory, importedFileName);
                if (importedFile.lastModified() > importModifTime) {
                    importModifTime = importedFile.lastModified();
                }
            }
        }

        for (i = 0; i < generatedList.size(); i++) {
            generatedFileName = (String) generatedList.get(i);
            generatedFile = new File(outputDirectory, generatedFileName);
            if (target.lastModified() > generatedFile.lastModified() |
                importModifTime > generatedFile.lastModified()) 
            {
                isDirty = true;
            }
        }
		//FIXME
		if (glib != null && glib.lastModified() > generatedFile.lastModified())
        	isDirty = true;
		if (glib2 != null && glib2.lastModified() > generatedFile.lastModified())
        	isDirty = true;
		if (glib3 != null && glib3.lastModified() > generatedFile.lastModified())
        	isDirty = true;

       	return isDirty;
    }

    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);
        }
    }

}






More information about the antlr-interest mailing list