Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.jangaroo.jooc.mxml.MxmlParserHelper Maven / Gradle / Ivy
package net.jangaroo.jooc.mxml;
import com.google.common.collect.Iterables;
import java_cup.runtime.Symbol;
import net.jangaroo.jooc.JangarooParser;
import net.jangaroo.jooc.JooParser;
import net.jangaroo.jooc.JooSymbol;
import net.jangaroo.jooc.ast.Annotation;
import net.jangaroo.jooc.ast.AssignmentOpExpr;
import net.jangaroo.jooc.ast.AstNode;
import net.jangaroo.jooc.ast.ClassBody;
import net.jangaroo.jooc.ast.ClassDeclaration;
import net.jangaroo.jooc.ast.CompilationUnit;
import net.jangaroo.jooc.ast.Directive;
import net.jangaroo.jooc.ast.Expr;
import net.jangaroo.jooc.ast.Extends;
import net.jangaroo.jooc.ast.FunctionDeclaration;
import net.jangaroo.jooc.ast.Ide;
import net.jangaroo.jooc.ast.Implements;
import net.jangaroo.jooc.ast.ImportDirective;
import net.jangaroo.jooc.ast.PackageDeclaration;
import net.jangaroo.jooc.ast.SemicolonTerminatedStatement;
import net.jangaroo.jooc.ast.TypedIdeDeclaration;
import net.jangaroo.jooc.input.InputSource;
import net.jangaroo.jooc.mxml.ast.MxmlCompilationUnit;
import net.jangaroo.jooc.mxml.ast.XmlAttribute;
import net.jangaroo.jooc.mxml.ast.XmlElement;
import net.jangaroo.jooc.mxml.ast.XmlHeader;
import net.jangaroo.jooc.mxml.ast.XmlTag;
import net.jangaroo.utils.CompilerUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
public class MxmlParserHelper {
private static final String TPL_CLASS_BODY = "package{class ___${\n%s\n}}";
private static final String TPL_CONSTRUCTOR_BODY = "package{class ___${function ___$(){\n%s\n}}}";
private static final String TPL_EXPRESSION = "package{class ___${x= %s}}";
private static final String TPL_IMPLEMENTS = "package{class ___$ implements %s\n{}}";
private static final String TPL_IMPORT = "package{\nimport %s;\nclass ___$ {}}";
private static final String TPL_IDE = "package{var ___$:%s;}";
private static final String TPL_METADATA = "package{\n%s\nclass ___$ {}}";
private static final String TPL_EXTENDS = "package{class ___$ extends %s {}}";
private static final String TPL_PACKAGE = "package %s {class ___$ {}}";
private final JooParser parser;
private InputSource inputSource;
public MxmlParserHelper(JooParser parser) {
this.parser = parser;
}
public XmlTag createXmlTag(JooSymbol lt, Ide tagName, List attributes, JooSymbol gt) {
return new XmlTag(lt, tagName, attributes, gt);
}
public XmlAttribute createXmlAttribute(Ide ide, JooSymbol eq, JooSymbol value){
return new XmlAttribute(ide, eq, value);
}
public XmlElement createXmlElement(XmlTag openingMxmlTag, List children, XmlTag closingMxmlTag) {
return new XmlElement(openingMxmlTag, children, closingMxmlTag);
}
public CompilationUnit createCompilationUnit(XmlHeader optXmlHeader, XmlElement root) throws Exception {
return new MxmlCompilationUnit(getInputSource(), optXmlHeader, root, this);
}
InputSource getInputSource() {
if(null == inputSource) {
inputSource = parser.getScannerBase().getInputSource();
}
return inputSource;
}
@Nonnull
public PackageDeclaration parsePackageDeclaration(String classQName) {
String text = CompilerUtils.packageName(classQName);
CompilationUnit unit = (CompilationUnit) parser.parseEmbedded(String.format(TPL_PACKAGE, text), 0, 0).value;
return unit.getPackageDeclaration();
}
@Nonnull
public ClassBody parseClassBody(@Nonnull JooSymbol symbol) {
String text = (String) symbol.getJooValue();
String template = TPL_CLASS_BODY;
int[] position = position(symbol, template);
CompilationUnit unit = (CompilationUnit) parser.parseEmbedded(String.format(template, text), position[0], position[1]).value;
return ((ClassDeclaration)unit.getPrimaryDeclaration()).getBody();
}
@Nonnull
public List parseConstructorBody(@Nonnull String text) {
Symbol parsed = parser.parseEmbedded(String.format(TPL_CONSTRUCTOR_BODY, text), 0, 0);
CompilationUnit unit = (CompilationUnit) parsed.value;
List directives = ((ClassDeclaration) unit.getPrimaryDeclaration()).getBody().getDirectives();
if(null != directives) {
Directive first = Iterables.getFirst(directives, null);
if(first instanceof FunctionDeclaration) {
return ((FunctionDeclaration)first).getBody().getDirectives();
}
}
return Collections.emptyList();
}
@Nullable
public Implements parseImplements(@Nonnull JooSymbol symbol) {
String text = (String) symbol.getJooValue();
String template = TPL_IMPLEMENTS;
int[] position = position(symbol, template);
CompilationUnit unit = (CompilationUnit) parser.parseEmbedded(String.format(template, text), position[0], position[1]).value;
return ((ClassDeclaration)unit.getPrimaryDeclaration()).getOptImplements();
}
@Nonnull
public Extends parseExtends(@Nonnull JangarooParser parser, @Nonnull XmlElement rootNode, @Nonnull String classQName) {
JooSymbol rootNodeSymbol = rootNode.getSymbol();
String superClassName = getClassNameForElement(parser, rootNode);
if (superClassName.equals(classQName)) {
throw JangarooParser.error(rootNodeSymbol, "Cyclic inheritance error: Super class and this component are the same.");
}
String template = TPL_EXTENDS;
int[] position = position(rootNodeSymbol, template);
CompilationUnit unit = (CompilationUnit) this.parser.parseEmbedded(String.format(template, superClassName), position[0], position[1]).value;
return ((ClassDeclaration)unit.getPrimaryDeclaration()).getOptExtends();
}
@Nullable
public ImportDirective parseImport(@Nonnull JooSymbol symbol) {
String text = (String) symbol.getJooValue();
String template = TPL_IMPORT;
int[] position = position(symbol, template);
try {
Symbol parsed = parser.silent().parseEmbedded(String.format(template, text), position[0], position[1]);
CompilationUnit unit = (CompilationUnit) parsed.value;
return (ImportDirective) Iterables.getFirst(unit.getDirectives(), null);
} catch (Exception ignored) {
}
return null;
}
@Nullable
public List parseMetadata(@Nonnull JooSymbol symbol) {
String text = (String) symbol.getJooValue();
String template = TPL_METADATA;
int[] position = position(symbol, template);
try {
Symbol parsed = parser.silent().parseEmbedded(String.format(template, text), position[0], position[1]);
CompilationUnit unit = (CompilationUnit) parsed.value;
return unit.getAnnotations();
} catch (Exception ignored) {
}
return null;
}
@Nullable
public ImportDirective parseImport(@Nonnull String text) {
String template = TPL_IMPORT;
Symbol parsed = parser.parseEmbedded(String.format(template, text), 0, 0);
CompilationUnit unit = (CompilationUnit) parsed.value;
return (ImportDirective) Iterables.getFirst(unit.getDirectives(), null);
}
public Ide parseIde(@Nonnull String text) {
String template = TPL_IDE;
Symbol parsed = parser.parseEmbedded(String.format(template, text), 0, 0);
CompilationUnit unit = (CompilationUnit) parsed.value;
return ((TypedIdeDeclaration)unit.getPrimaryDeclaration()).getOptTypeRelation().getType().getIde();
}
@Nonnull
static int[] position(@Nonnull JooSymbol symbol, @Nonnull String template) {
String[] lines = template.split("\\n");
int lineCount = 0;
for(String line : lines) {
lineCount ++;
int index = line.indexOf("%s");
if(-1 != index) {
return new int[] {symbol.getLine() - lineCount, symbol.getColumn() - index};
}
}
throw new IllegalStateException("cannot find %s in template string '" + template + "'");
}
@Nonnull
public String getClassNameForElement(JangarooParser parser, XmlElement xmlElement){
String name = xmlElement.getLocalName();
String uri = xmlElement.getNamespaceURI();
if (uri != null) {
String packageName = parsePackageFromNamespace(uri);
if (packageName != null) {
String qName = CompilerUtils.qName(packageName, name);
if (qName.equals(CompilerUtils.qNameFromRelativePath(getInputSource().getRelativePath()))) {
return qName;
}
if (parser.isClass(qName)) {
return qName;
}
} else {
String className = parser.getMxmlComponentRegistry().getClassName(uri, name);
if(null != className) {
return className;
}
}
}
String nodeName = xmlElement.getName();
if (xmlElement.getPrefix() != null) {
nodeName = xmlElement.getPrefix() + ":" + nodeName;
}
throw JangarooParser.error(xmlElement, "Could not resolve class from MXML node <" + nodeName + "/>");
}
static String parsePackageFromNamespace(String uri) {
return uri.endsWith(".*") ? uri.substring(0, uri.length() -2)
: uri.equals("*") || MxmlUtils.isMxmlNamespace(uri) ? "" : null;
}
@Nonnull
public Expr parseExpression(@Nonnull JooSymbol symbol) {
String text = symbol.getText();
String template = TPL_EXPRESSION;
int[] position = position(symbol, template);
String input = String.format(template, text);
CompilationUnit unit = (CompilationUnit) parser.parseEmbedded(input, position[0], position[1]).value;
List classBodyDirectives = ((ClassDeclaration) unit.getPrimaryDeclaration()).getBody().getDirectives();
if(null != classBodyDirectives) {
Directive directive = Iterables.getFirst(classBodyDirectives, null);
if(directive instanceof SemicolonTerminatedStatement) {
AstNode astNode = ((SemicolonTerminatedStatement) directive).getOptStatement();
if(astNode instanceof AssignmentOpExpr) {
return ((AssignmentOpExpr) astNode).getArg2();
}
}
}
throw new IllegalStateException("Unexpected AST obtained when parsing '" + input + "'");
}
}