/*
* Author: Chris
*
* Copyright (c) 2005 RubyPeople.
*
* This file is part of the Ruby Development Tools (RDT) plugin for eclipse.
* RDT is subject to the "Common Public License (CPL) v 1.0". You may not use
* RDT except in compliance with the License. For further information see
* org.rubypeople.rdt/rdt.license.
*/
package org.rubypeople.rdt.internal.core.parser;
import java.io.Reader;
import java.io.StringReader;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.jruby.CompatVersion;
import org.jruby.ast.Node;
import org.jruby.common.IRubyWarnings;
import org.jruby.common.NullWarnings;
import org.jruby.lexer.yacc.LexerSource;
import org.jruby.lexer.yacc.SyntaxException;
import org.jruby.parser.DefaultRubyParser;
import org.jruby.parser.ParserConfiguration;
import org.jruby.parser.ParserSupport;
import org.jruby.parser.RubyParserPool;
import org.jruby.parser.RubyParserResult;
import org.jruby.util.KCode;
import org.rubypeople.rdt.internal.core.builder.IoUtils;
import org.rubypeople.rdt.internal.core.util.Util;
/**
* @author cawilliams
*/
public class RubyParser
{
private final RubyParserPool pool;
private IRubyWarnings warnings;
private static boolean isDebug;
private static int count = 0;
public RubyParser()
{
this(new NullWarnings());
}
public RubyParser(IRubyWarnings warnings)
{
this.warnings = warnings;
this.pool = RubyParserPool.getInstance();
}
private RubyParserResult parse(String fileName, Reader content)
{
if (fileName == null)
{
fileName = "";
}
DefaultRubyParser parser = null;
try
{
ParserConfiguration config = getParserConfig();
parser = getDefaultRubyParser(config);
parser.setWarnings(warnings);
if (isDebug)
System.out.println("Parse count: " + count++ + " on file: " + fileName);
LexerSource lexerSource = LexerSource.getSource(fileName, content, null, config);
RubyParserResult result = parser.parse(config, lexerSource);
// XXX Do a pass through the comments and associate the comment nodes to the normal AST nodes?!
postProcessResult(result);
return result;
}
catch (SyntaxException e)
{
throw e;
}
finally
{
IoUtils.closeQuietly(content);
returnBorrowedParser(parser);
}
}
/**
* Hook for subclasses to do extra work on the resulting AST, comments, etc. Meant as a way for the refactoring code
* to associate comments to the AST node, but to only do so in those cases where we actually care about the
* comments.
*
* @param result
*/
protected void postProcessResult(RubyParserResult result)
{
// do nothing
}
protected void returnBorrowedParser(DefaultRubyParser parser)
{
pool.returnParser(parser);
}
protected DefaultRubyParser getDefaultRubyParser(ParserConfiguration config)
{
ParserSupport support = new ParserSupport();
support.setConfiguration(config);
return new DefaultRubyParser(support);
}
protected ParserConfiguration getParserConfig()
{
return new ParserConfiguration(KCode.NIL, 0, true, false, CompatVersion.RUBY1_8);
}
public static void setDebugging(boolean b)
{
isDebug = b;
}
public static boolean isDebugging()
{
return isDebug;
}
public Node parse(IFile file) throws CoreException
{
return parse(file.getName(), new String(Util.getResourceContentsAsCharArray(file))).getAST();
}
/**
* If possible, please use {@link #parse(String, String)} to provide the filename as well (useful for debugging).
*
* @param source
* @return
*/
public RubyParserResult parse(String source)
{
return parse((String) null, source);
}
public RubyParserResult parse(IFile file, String source)
{
String name = "";
if (file != null)
name = file.getName();
return parse(name, source);
}
public RubyParserResult parse(String fileName, String source)
{
return parse(fileName, source, false);
}
/**
* @param fileName
* @param source
* @param bypassCache
* boolean indicating if we want to force a parse and bypass any cached results.
* @return
*/
public RubyParserResult parse(String fileName, String source, boolean bypassCache)
{
if (source == null)
return new NullParserResult();
RubyParserResult ast = parse(fileName, new StringReader(source));
if (ast == null)
ast = new NullParserResult();
return ast;
}
}