/*
* AS3FragmentParser.java
*
* Copyright (c) 2007 David Holroyd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.co.badgersinfoil.metaas.impl;
import org.antlr.runtime.ParserRuleReturnScope;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.asdt.core.internal.antlr.AS3Parser;
import uk.co.badgersinfoil.metaas.ActionScriptFactory;
import uk.co.badgersinfoil.metaas.SyntaxException;
import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree;
public class AS3FragmentParser {
public static LinkedListTree parseStatement(String statement) {
// We need to add a ';' so that LA(2) at the end of an
// expression-statement will not unexpectedly find EOF. we add
// a second ';' so that the trailing ';' can simply be ommitted
// by the caller
// TODO: assert that there really is no extra code trailing the
// parsed statement
AS3Parser parser = ASTUtils.parse(statement+";;");
LinkedListTree stmt;
try {
stmt = tree(parser.statement());
} catch (RecognitionException e) {
throw ASTUtils.buildSyntaxException(statement, parser, e);
}
return stmt;
}
public static LinkedListTree parseExprStatement(String expr) {
AS3Parser parser = ASTUtils.parse(expr + ";");
try {
return tree(parser.expressionStatement());
} catch (RecognitionException e) {
throw ASTUtils.buildSyntaxException(expr, parser, e);
}
}
/**
* Attempts to parse the given string as an AS3 expression for use as
* a parenthesised conditional or with-statement parameter (the
* surronding parenthesis should not be included).
*
* @throws SyntaxException if the given text doesn't form a valid
* expression.
*/
public static LinkedListTree parseCondition(String expr) {
AS3Parser parser = ASTUtils.parse("(" + expr + ")");
try {
return tree(parser.condition());
} catch (RecognitionException e) {
throw new SyntaxException("invalid condition "+ActionScriptFactory.str(expr), e);
}
}
/**
* Attempts to parse the given string as an AS3 expression.
*
* @throws SyntaxException if the given text doesn't form a valid
* expression.
*/
public static LinkedListTree parseExpr(String expr) {
AS3Parser parser = ASTUtils.parse(expr + ")");
try {
LinkedListTree result = tree(parser.expression());
ensureRemainingInputIs(parser.getTokenStream(), AS3Parser.RPAREN, expr);
// zap the trailing ')'
result.getStopToken().setNext(null);
return result;
} catch (RecognitionException e) {
throw new SyntaxException("invalid expression "+ActionScriptFactory.str(expr), e);
}
}
/**
* Attempts to parse the given string as an AS3 expression list.
*
* @throws SyntaxException if the given text doesn't form a valid
* expression.
*/
public static LinkedListTree parseExprList(String expr) {
AS3Parser parser = ASTUtils.parse(expr + ")");
try {
return tree(parser.expressionList());
} catch (RecognitionException e) {
throw new SyntaxException("invalid expression-list "+ActionScriptFactory.str(expr), e);
}
}
/**
* Helper to access the AST produced by a parser production
*/
public static LinkedListTree tree(ParserRuleReturnScope returnScope) {
return (LinkedListTree)returnScope.getTree();
}
/**
* Parses the given value, returning an IDENT node.
*
* @throws SyntaxException if the given text doesn't form a valid
* identifier.
*/
public static LinkedListTree parseIdent(String value) {
AS3Parser parser = ASTUtils.parse(value);
try {
LinkedListTree result = tree(parser.identifier());
parser.endOfFile();
return result;
} catch (RecognitionException e) {
throw new SyntaxException("invalid identifier "+ActionScriptFactory.str(value), e);
}
}
public static LinkedListTree parseParameterDefault(String value) {
AS3Parser parser = ASTUtils.parse("="+value);
LinkedListTree def;
try {
def = tree(parser.parameterDefault());
} catch (RecognitionException e) {
throw new SyntaxException(e.getMessage());
}
return def;
}
public static LinkedListTree parseForInit(String expr) {
AS3Parser parser = ASTUtils.parse(expr + ";");
try {
LinkedListTree result = tree(parser.forInit());
ensureRemainingInputIs(parser.getTokenStream(), AS3Parser.SEMI, expr);
return result;
} catch (RecognitionException e) {
throw new SyntaxException(e);
}
}
public static LinkedListTree parseForCond(String expr) {
AS3Parser parser = ASTUtils.parse(expr + ";");
try {
LinkedListTree result = tree(parser.forCond());
ensureRemainingInputIs(parser.getTokenStream(), AS3Parser.SEMI, expr);
return result;
} catch (RecognitionException e) {
throw new SyntaxException(e);
}
}
public static LinkedListTree parseForIter(String expr) {
AS3Parser parser = ASTUtils.parse(expr + ")");
try {
LinkedListTree result = tree(parser.forIter());
ensureRemainingInputIs(parser.getTokenStream(), AS3Parser.RPAREN, expr);
return result;
} catch (RecognitionException e) {
throw new SyntaxException(e);
}
}
/**
* Given the type name to import, creates an IMPORT AST node
*/
public static LinkedListTree parseImport(String name) {
AS3Parser parser = ASTUtils.parse("import "+name+";");
try {
LinkedListTree result = tree(parser.importDefinition());
parser.endOfFile(); // assert no trailing data
return result;
} catch (RecognitionException e) {
throw new SyntaxException(e);
}
}
/**
* Parses the given value as an IDENT, using it to construct a new
* TYPE_SPEC node.
*
* @throws SyntaxException if the given text doesn't form a valid
* identifier.
*/
public static LinkedListTree parseTypeSpec(String value) {
AS3Parser parser = ASTUtils.parse(":" + value);
try {
LinkedListTree result = tree(parser.typeExpression());
ensureNoMoreInput(parser.getTokenStream(), value);
return result;
} catch (RecognitionException e) {
throw new SyntaxException("invalid type-spec "+ActionScriptFactory.str(value), e);
}
}
private static void ensureNoMoreInput(TokenStream input, String value) {
if (input.LA(1) != AS3Parser.EOF) {
throw new SyntaxException("Unexpected tokens in input: "+value);
}
}
private static void ensureRemainingInputIs(TokenStream input, int expectedTokenType, String value) {
if (input.LA(1) != expectedTokenType) {
throw new SyntaxException("Unexpected tokens in input: "+value);
}
}
public static LinkedListTree parseForInVar(String expr) {
AS3Parser parser = ASTUtils.parse(expr + " in");
try {
return tree(parser.forInClauseDecl());
} catch (RecognitionException e) {
throw new SyntaxException(e);
}
}
public static LinkedListTree parseForInIterated(String expr) {
AS3Parser parser = ASTUtils.parse(expr + ")");
try {
return tree(parser.forInClauseTail());
} catch (RecognitionException e) {
throw new SyntaxException(e);
}
}
public static LinkedListTree parseVariableDeclarator(String assignment) {
AS3Parser parser = ASTUtils.parse(assignment + ";");
try {
return tree(parser.variableDeclarator());
} catch (RecognitionException e) {
throw new SyntaxException(e);
}
}
public static LinkedListTree parseSimpleIdent(String value) {
AS3Parser parser = ASTUtils.parse(value);
try {
LinkedListTree result = tree(parser.ident());
parser.endOfFile();
return result;
} catch (RecognitionException e) {
throw new SyntaxException("invalid identifier "+ActionScriptFactory.str(value), e);
}
}
public static LinkedListTree parseXMLLiteral(String value) {
AS3Parser parser = ASTUtils.parse(value+" ");
try {
LinkedListTree result = tree(parser.xmlLiteral());
parser.endOfFile();
return result;
} catch (RecognitionException e) {
throw ASTUtils.buildSyntaxException(value, parser, e);
}
}
public static LinkedListTree parseRegexpLiteral(String value) {
AS3Parser parser = ASTUtils.parse(value + " ");
try {
LinkedListTree result = tree(parser.regexpLiteral());
parser.endOfFile();
return result;
} catch (RecognitionException e) {
throw ASTUtils.buildSyntaxException(value, parser, e);
}
}
public static LinkedListTree parseQualifiedIdent(String value) {
AS3Parser parser = ASTUtils.parse(value);
try {
LinkedListTree result = tree(parser.qualifiedIdent());
parser.endOfFile();
return result;
} catch (RecognitionException e) {
throw new SyntaxException("invalid identifier "+ActionScriptFactory.str(value), e);
}
}
}