/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ruby.core;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.jrubyparser.CompatVersion;
import org.jrubyparser.SourcePosition;
import org.jrubyparser.ast.CommentNode;
import org.jrubyparser.lexer.LexerSource;
import org.jrubyparser.lexer.SyntaxException;
import org.jrubyparser.parser.ParserConfiguration;
import org.jrubyparser.parser.ParserResult;
import org.jrubyparser.parser.ParserSupport;
import org.jrubyparser.parser.ParserSupport19;
import org.jrubyparser.parser.Ruby18Parser;
import org.jrubyparser.parser.Ruby19Parser;
import com.aptana.core.build.IProblem;
import com.aptana.core.logging.IdeLog;
import com.aptana.parsing.AbstractParser;
import com.aptana.parsing.IParseState;
import com.aptana.parsing.WorkingParseResult;
import com.aptana.parsing.ast.IParseError;
import com.aptana.parsing.ast.IParseNode;
import com.aptana.parsing.ast.ParseError;
import com.aptana.ruby.core.ast.SourceElementVisitor;
import com.aptana.ruby.internal.core.RubyComment;
import com.aptana.ruby.internal.core.RubyScript;
public class RubyParser extends AbstractParser
{
public RubyParser()
{
}
protected void parse(IParseState parseState, WorkingParseResult working)
{
String source = parseState.getSource();
RubyScript root = new RubyScript(parseState.getStartingOffset(), parseState.getStartingOffset()
+ source.length() - 1);
CompatVersion compatVersion = CompatVersion.BOTH;
int lineNumber = 0;
String fileName = "<unnamed file>"; //$NON-NLS-1$
if (parseState instanceof RubyParseState)
{
RubyParseState rubyParseState = (RubyParseState) parseState;
compatVersion = rubyParseState.getCompatVersion();
lineNumber = rubyParseState.getStartingLineNumber();
fileName = rubyParseState.getFilename();
}
CollectingRubyWarnings warnings = new CollectingRubyWarnings(fileName);
org.jrubyparser.parser.RubyParser parser = null;
ParserConfiguration config = new ParserConfiguration(lineNumber, compatVersion);
if (compatVersion == CompatVersion.RUBY1_8)
{
ParserSupport support = new ParserSupport();
support.setConfiguration(config);
parser = new Ruby18Parser(support);
}
else
{
ParserSupport19 support = new ParserSupport19();
support.setConfiguration(config);
parser = new Ruby19Parser(support);
}
parser.setWarnings(warnings);
LexerSource lexerSource = LexerSource.getSource(fileName, new StringReader(source), config);
lexerSource.setOffset(parseState.getStartingOffset());
ParserResult result = new NullParserResult();
try
{
result = parser.parse(config, lexerSource);
RubyStructureBuilder builder = new RubyStructureBuilder(root);
SourceElementVisitor visitor = new SourceElementVisitor(builder);
visitor.acceptNode(result.getAST());
List<IParseNode> commentParseNodes = new ArrayList<IParseNode>();
for (CommentNode commentNode : result.getCommentNodes())
{
commentParseNodes.add(new RubyComment(commentNode, getText(source, commentNode.getPosition())));
}
root.setCommentNodes(commentParseNodes);
}
catch (SyntaxException se)
{
int start = se.getPosition().getStartOffset();
working.addError(new ParseError(IRubyConstants.CONTENT_TYPE_RUBY, start, se.getPosition().getEndOffset()
- start, se.getMessage(), IParseError.Severity.ERROR));
}
catch (IOException e)
{
IdeLog.logError(RubyCorePlugin.getDefault(), "Failed to parse ruby code due to IOException", e); //$NON-NLS-1$
}
// Add warnings
CollectingRubyWarnings collector = (CollectingRubyWarnings) warnings;
for (IParseError warning : collector.getWarnings())
{
working.addError(warning);
}
working.setParseResult(root);
}
private String getText(String source, SourcePosition position)
{
return new String(source.substring(position.getStartOffset(), position.getEndOffset()));
}
}