[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: compiling SableCc natively



Anybody, any objections to this?

My own comments follow....

The changes should be:

lexer.txt, line 106 should become: final URL url = new URL("core:/" +
Lexer.class.getName() + ".lexer.dat");
parser.txt, line 90 should become: final URL url = new URL("core:/" +
Parser.class.getName() + ".parser.dat");
(*)
Are you sure it should be:
Parser.class.getName() + ".pareser.dat" ? It will produce something like:
Lmy.org.Parser.dat

I think it should be: Parser.class.getPackage().getName() + ".pareser.dat", which will produce something like this:
my.org.Parser.dat


By the way, the changes I had to make to SableCc, so that SableCc could be
compiled natively, are rather small as well:

GenLexer.java, line 30: macros = new MacroExpander((new
ResourceReader()).getResourceReader("lexer.txt"));
GenParser.java, line 42: macros = new MacroExpander((new
ResourceReader()).getResourceReader("parser.txt"));
GenProds.java, line 29:  macros = new MacroExpander((new
ResourceReader()).getResourceReader("productions.txt"));
GenTokens.java, line 27: macros = new MacroExpander((new
ResourceReader()).getResourceReader("tokens.txt"));
GenTools.java, line 32:  macros = new MacroExpander((new
ResourceReader()).getResourceReader("tools.txt"));
GenUtils.java, line 26:  macros = new MacroExpander((new
ResourceReader()).getResourceReader("utils.txt"));

ResourceReader centralizes the logic for reading resources. Therefore,
ResourceReader goes through the usual rigmarole, which consists in trying to
read from the jar-file first. If it fails, it tries to read from the core;
by the way, failing to read from the core throws an exception unlike failing
to read from the jar-file. I've made sure to fully qualify the resource to
read, so that multiple lexers and parsers can participate in the same
executable:

package org.sablecc.sablecc;

import java.io.*;
import java.net.URL;

//contributed by Erik Poupaert, in order to compile sablecc natively.

public class ResourceReader
{
	public Reader getResourceReader(String pResourceName)
	{
		InputStream inputStream=null;
		try
		{
			inputStream=getClass().getResourceAsStream(pResourceName);
				//the following line forces an exception if the inputStream could not be
read.
				//In absence of this line, inputStream would just be null and happily
continue.
		       if (inputStream == null) throw new IOException(pResourceName + "
not found");
		       return new InputStreamReader(inputStream);
		}
		catch(Exception e)
		{
			try
			{
			      final URL url = new URL("core:/" +  ResourceReader.class.getName()
+ "." + pResourceName);
			      return new
InputStreamReader(url.openConnection().getInputStream());
		}
		catch(Exception e2)
		{
		    throw new RuntimeException("unable to open " +
ResourceReader.class.getName() + "." + pResourceName);
		}
        }
    }
}


(**)
I suggest renaming this class to ResourceHelper (or similar) just not to make confusion with the Reader interface -- as you pointed out this class does not make a full Reader contract anyway.
I also suggest making it final, because it is being used internally by sablecc, and all modifications will not be done by inheritance anyway. And I suggest making the method final static, so we do not need to instantiate ResourceHelper everytime we load a resource. So we would have something like this:

macros = new MacroExpander(ResourceHelper.getReader("lexer.txt"));

instead of this:
macros = new MacroExpander((new ResourceReader()).getResourceReader("lexer.txt"));


(***)
Again, are you sure it should be:
final URL url = new URL("core:/" + ResourceReader.class.getName() + "." + pResourceName);

and not:

final URL url = new URL("core:/" + ResourceReader.class.getPackage().getName() + "." + pResourceName);

?

I am asking that because I do not really know the mechanisms for loading resources in GCJ and it just looks strange with this "L" in front ;o)


--
cheers
Mariusz