package org.deved.antlride.internal.core.parser; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import org.antlr.runtime.ANTLRStringStream; import org.antlr.runtime.CommonToken; import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.RecognitionException; import org.antlr.runtime.Token; import org.antlr.runtime.TokenStream; import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.CommonTreeNodeStream; import org.antlr.runtime.tree.Tree; import org.deved.antlride.core.build.AntlrBuildUnit; import org.deved.antlride.core.build.AntlrBuildUnitRepository; import org.deved.antlride.core.model.ASTSuffix; import org.deved.antlride.core.model.GrammarType; import org.deved.antlride.core.model.IAlternative; import org.deved.antlride.core.model.IBlock; import org.deved.antlride.core.model.ICallExpression; import org.deved.antlride.core.model.ICallExpressionOption; import org.deved.antlride.core.model.ICompositeStatement; import org.deved.antlride.core.model.IGrammar; import org.deved.antlride.core.model.IGrammarAction; import org.deved.antlride.core.model.IGrammarScope; import org.deved.antlride.core.model.IImport; import org.deved.antlride.core.model.IModelElement; import org.deved.antlride.core.model.IOption; import org.deved.antlride.core.model.IParameter; import org.deved.antlride.core.model.IReturn; import org.deved.antlride.core.model.IRule; import org.deved.antlride.core.model.IRuleAction; import org.deved.antlride.core.model.IRuleCatch; import org.deved.antlride.core.model.IRuleScope; import org.deved.antlride.core.model.IScope; import org.deved.antlride.core.model.IScopeAttribute; import org.deved.antlride.core.model.IScopeReference; import org.deved.antlride.core.model.ISemanticPredicate; import org.deved.antlride.core.model.ISourceElement; import org.deved.antlride.core.model.IStatement; import org.deved.antlride.core.model.ISyntacticPredicate; import org.deved.antlride.core.model.ITemplateParameter; import org.deved.antlride.core.model.IToken; import org.deved.antlride.core.model.ITreeStatement; import org.deved.antlride.core.model.IRule.RuleAccessModifier; import org.deved.antlride.core.model.ISemanticPredicate.PredicateType; import org.deved.antlride.core.model.IStatement.EBNF; import org.deved.antlride.core.util.AntlrTextHelper; import org.deved.antlride.internal.core.model.AAbstractModelElement; import org.deved.antlride.internal.core.model.AAlternative; import org.deved.antlride.internal.core.model.AAssign; import org.deved.antlride.internal.core.model.ABangOperator; import org.deved.antlride.internal.core.model.ABlock; import org.deved.antlride.internal.core.model.ACallExpression; import org.deved.antlride.internal.core.model.ACallExpressionOption; import org.deved.antlride.internal.core.model.AGrammar; import org.deved.antlride.internal.core.model.AGrammarAction; import org.deved.antlride.internal.core.model.AGrammarScope; import org.deved.antlride.internal.core.model.AImport; import org.deved.antlride.internal.core.model.AImports; import org.deved.antlride.internal.core.model.ANotOperator; import org.deved.antlride.internal.core.model.AOption; import org.deved.antlride.internal.core.model.AOptionName; import org.deved.antlride.internal.core.model.AOptionValue; import org.deved.antlride.internal.core.model.AOptions; import org.deved.antlride.internal.core.model.AParameter; import org.deved.antlride.internal.core.model.AParameters; import org.deved.antlride.internal.core.model.ARange; import org.deved.antlride.internal.core.model.AReturn; import org.deved.antlride.internal.core.model.AReturns; import org.deved.antlride.internal.core.model.ARootOperator; import org.deved.antlride.internal.core.model.ARule; import org.deved.antlride.internal.core.model.ARuleAction; import org.deved.antlride.internal.core.model.ARuleBody; import org.deved.antlride.internal.core.model.ARuleCatch; import org.deved.antlride.internal.core.model.ARuleFinally; import org.deved.antlride.internal.core.model.ARuleScope; import org.deved.antlride.internal.core.model.ARuleThrows; import org.deved.antlride.internal.core.model.AScope; import org.deved.antlride.internal.core.model.AScopeAttribute; import org.deved.antlride.internal.core.model.AScopeReference; import org.deved.antlride.internal.core.model.ASemanticPredicate; import org.deved.antlride.internal.core.model.ASourceElement; import org.deved.antlride.internal.core.model.AStatement; import org.deved.antlride.internal.core.model.AStatementAction; import org.deved.antlride.internal.core.model.ASyntacticPredicate; import org.deved.antlride.internal.core.model.ATemplate; import org.deved.antlride.internal.core.model.ATemplateParameter; import org.deved.antlride.internal.core.model.AToken; import org.deved.antlride.internal.core.model.ATokens; import org.deved.antlride.internal.core.model.ATreeStatement; import org.deved.antlride.internal.core.model.AVariable; import org.deved.antlride.internal.core.parser.ANTLRParser.grammarDef_return; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.dltk.core.builder.ISourceLineTracker; import org.eclipse.dltk.utils.TextUtils; public class DefaultGrammarBuilder implements GrammarBuilder, GrammarBuilderFactory { private class DefaultRuleBuilder implements RuleBuilder { private ARule rule; private OptionsBuilder optionsBuilder; private List<IRuleScope> scopes; private List<IScopeReference> scopeReferences; private List<IRuleAction> actions; private List<IRuleCatch> catchs; public DefaultRuleBuilder() { rule = new ARule(grammar); rule.setAccessModifier(RuleAccessModifier.PUBLIC); scopes = new ArrayList<IRuleScope>(); scopeReferences = new ArrayList<IScopeReference>(); actions = new ArrayList<IRuleAction>(); catchs = new ArrayList<IRuleCatch>(); optionsBuilder = ExceptionSafeProxy.create( new DefaultOptionsBuilder(), OptionsBuilder.class); } public RuleBuilder documentation(CommonTree documentationNode) { rule.setDocumentation(documentationNode.getText()); return this; } public RuleBuilder accessModifier(RuleAccessModifier modifier) { rule.setAccessModifier(modifier); return this; } public RuleBuilder scope(CommonTree scopeNode, CommonTree bodyNode) { ARuleScope ruleScope = new ARuleScope(rule); ruleScope.setSourceStart(_start(scopeNode)); ruleScope.setSourceEnd(_end(bodyNode)); IScopeAttribute[] attrs = createScopeAttrs(ruleScope, bodyNode); ruleScope.setAttributes(attrs); scopes.add(ruleScope); return this; } public RuleBuilder scopeReference(CommonTree scopeNameNode) { IGrammarScope grammarScope = grammar.findScope(scopeNameNode .getText()); if (grammarScope == null) { grammarScope = new AGrammarScope(grammar, createSourceElement( scopeNameNode.getText(), -1, -1, false)); } AScopeReference scopeReference = new AScopeReference(rule, grammarScope, createSourceElement(scopeNameNode.getText(), _start(scopeNameNode), _end(scopeNameNode), false)); scopeReferences.add(scopeReference); return this; } public RuleBuilder body(BlockBuilder block) { block.body(); ARuleBody body = (ARuleBody) block.build(); rule.setBody(body); return this; } public RuleBuilder bodyStart(CommonTree node) { ((AAbstractModelElement) rule.getBody()) .setSourceStart(_start(node) + 1); return this; } public RuleBuilder bodyEnd(CommonTree node) { ((AAbstractModelElement) rule.getBody()) .setSourceEnd(_end(node) - 1); return this; } public RuleBuilder astSuffix(ASTSuffix suffix) { rule.setAstSuffix(suffix); return this; } public RuleBuilder name(CommonTree nameNode) { rule.setName(createSourceElement(nameNode)); return this; } public IRule build() { rule.setRuleScopes(scopes); rule.setUsesScopes(scopeReferences); rule.setActions(actions); rule.setCatchs(catchs); this.actions.clear(); this.scopeReferences.clear(); this.scopes.clear(); this.catchs.clear(); return rule; } public RuleBuilder option(CommonTree name, CommonTree value) { optionsBuilder.option(name, value); return this; } public RuleBuilder options(CommonTree startNode, CommonTree endNode) { optionsBuilder.options(startNode, endNode); AOptions options = optionsBuilder.build(); rule.setOptions(options); options.setParent(rule); return this; } public RuleBuilder returns(CommonTree returnsNode) { int sourceStart = _start(returnsNode); int sourceEnd = _end(returnsNode); String text = AntlrTextHelper.removeComments(returnsNode.getText()); String[] args = text.split(","); IReturn[] rets = new IReturn[args.length]; int start, end; AReturns returns = new AReturns(rule, sourceStart, sourceEnd); for (int i = 0; i < args.length; i++) { // get param name and type String[] arg = splitVariableDecl(args[i]); // create param name start = sourceStart + text.indexOf(arg[0]) + 1; end = start + arg[0].length(); ISourceElement paramName = new ASourceElement(arg[0], start, end); ISourceElement paramType = null; // create param type if (arg[1] != null) { start = sourceStart + text.indexOf(arg[1]); end = start + arg[1].length(); paramType = new ASourceElement(arg[1], start, end); } rets[i] = new AReturn(returns, paramName, paramType); } returns.setReturns(rets); returns.setText(text); rule.setReturns(returns); return this; } public RuleBuilder parameters(CommonTree paramNode) { AParameters params = createParameters(rule, paramNode); rule.setParameters(params); return this; } public RuleBuilder action(CommonTree nameNode, CommonTree bodyNode) { int start = _start(nameNode); int end = _end(bodyNode); ARuleAction action = new ARuleAction(rule, createSourceElement(nameNode), createSourceElement(bodyNode), start, end); actions.add(action); return this; } public RuleBuilder ruleStart(CommonTree startNode) { rule.setSourceStart(_start(startNode)); return this; } public RuleBuilder ruleEnd(CommonTree endNode) { rule.setSourceEnd(_end(endNode)); return this; } public RuleBuilder ruleCatch(CommonTree catchNode, CommonTree argNode, CommonTree actionNode) { ARuleCatch ruleCatch = new ARuleCatch(_text(argNode), createSourceElement(actionNode)); catchs.add(ruleCatch); return this; } public RuleBuilder ruleFinally(CommonTree finallyNode, CommonTree actionNode) { ARuleFinally ruleFinally = new ARuleFinally( createSourceElement(actionNode)); rule.setFinally(ruleFinally); return this; } public RuleBuilder ruleThrows(List<CommonTree> exceptionList) { String[] exceptions = new String[exceptionList.size()]; for (int i = 0; i < exceptions.length; i++) { exceptions[i] = _text(exceptionList.get(i)); } ARuleThrows ruleThrows = new ARuleThrows(exceptions); rule.setThrows(ruleThrows); return this; } } private class DefaultOptionsBuilder implements OptionsBuilder { private Collection<IOption> optionList; private AOptions options; public DefaultOptionsBuilder() { optionList = new ArrayList<IOption>(); } public OptionsBuilder option(CommonTree nameNode, CommonTree valueNode) { ISourceElement name = createSourceElement(nameNode); ISourceElement value = createSourceElement(valueNode); int sourceStart = name.sourceStart(); int sourceEnd = value.sourceEnd() + 1; AOption option = new AOption(sourceStart, sourceEnd); // name option.setName(new AOptionName(option, name)); // value option.setValue(new AOptionValue(option, value)); this.optionList.add(option); return this; } public OptionsBuilder options(CommonTree startNode, CommonTree endNode) { int sourceStart = _start(startNode); int sourceEnd = _end(endNode) + 1;// plus '}' options = new AOptions(sourceStart, sourceEnd, _line(sourceStart), _line(sourceEnd)); options.setOptions(this.optionList); return this; } public AOptions build() { optionList.clear(); return options; } } private class DefaultBlockBuilder extends AbstractStatementBuilder implements BlockBuilder { private OptionsBuilder optionsBuilder; private ABlock block; private boolean body = false; public DefaultBlockBuilder(boolean ruleBody) { optionsBuilder = ExceptionSafeProxy.create( new DefaultOptionsBuilder(), OptionsBuilder.class); block = ruleBody ? new ARuleBody() : new ABlock(); } public BlockBuilder body() { body = true; return this; } public BlockBuilder start(CommonTree start) { block.setSourceStart(_start(start)); return this; } public BlockBuilder end(CommonTree node) { block.setSourceEnd(_end(node)); return this; } public BlockBuilder statement(StatementBuilder statement) { block.add(statement.build()); return this; } @Override protected IStatement getTarget() { if (!body) { if (block.hasOptions() || block.getLeftParenthesis() != null || block.getRightParenthesis() != null) { return block; } IStatement statement = null; ICompositeStatement compositeStatement = block; // simplify while (compositeStatement.size() == 1) { statement = compositeStatement.first(); if (statement instanceof IAlternative) { compositeStatement = (ICompositeStatement) statement; } else { break; } } if (statement != null) { // found something if (statement instanceof ICompositeStatement) { if (statement instanceof ITreeStatement) { // simplify // from:: block->alternative->tree-statement // to:: tree-statement return statement; } } else { // simplify // from:: block->alternative->call // to:: call ((AStatement) statement).setEbnfOperator(block .getEbnfOperator()); return statement; } } } return block; } public OptionsAware option(CommonTree nameNode, CommonTree valueNode) { optionsBuilder.option(nameNode, valueNode); return this; } public OptionsAware options(CommonTree startNode, CommonTree endNode) { optionsBuilder.options(startNode, endNode); AOptions options = optionsBuilder.build(); options.setParent(block); block.setOptions(options); return this; } public BlockBuilder lp(CommonTree node) { if ("(".equals(node.getText())) { block.setLeftParenthesis(createSourceElement(node, true)); } return this; } public BlockBuilder rp(CommonTree node) { if (")".equals(node.getText())) { block.setRightParenthesis(createSourceElement(node, true)); } return this; } } private abstract class AbstractStatementBuilder implements StatementBuilder { private ISourceElement not; private ISourceElement root; private ISourceElement bang; private EBNF ebnf = EBNF.NONE; public StatementBuilder bang(CommonTree commonTree) { bang = createSourceElement(commonTree); return this; } public StatementBuilder not(CommonTree commonTree) { not = createSourceElement(commonTree); return this; } public StatementBuilder root(CommonTree commonTree) { root = createSourceElement(commonTree); return this; } public StatementBuilder ebnf(CommonTree ebnfValue) { ebnf = EBNF.fromString(ebnfValue.getText()); return this; } public StatementBuilder treeOp(CommonTree commonTree) { ASTSuffix suffix = ASTSuffix.getASTSuffix(commonTree.getText()); if (suffix == ASTSuffix.BANG) { bang(commonTree); } else if (suffix == ASTSuffix.ROOT) { root(commonTree); } return this; } protected abstract IStatement getTarget(); public final IStatement build() { IStatement statement = getTarget(); // apply operators in order if (not != null) { statement = new ANotOperator(not, statement); } // ast operators if (bang != null) { statement = new ABangOperator(bang, statement); } else if (root != null) { statement = new ARootOperator(root, statement); } // ebnf ((AStatement) statement).setEbnfOperator(ebnf); return statement; } } private class DefaultAssignBuilder extends AbstractStatementBuilder implements AssignBuilder { private AAssign assign; @Override protected IStatement getTarget() { return assign; } public AssignBuilder assign(CommonTree operatorNode, CommonTree variableNode, StatementBuilder statement) { AVariable variable = new AVariable( createSourceElement(variableNode)); assign = new AAssign(createSourceElement(operatorNode), variable, statement.build()); return this; } } private class DefaultSynPredBuilder extends AbstractStatementBuilder implements SynPredicateBuilder { private StatementBuilder statement; @Override protected IStatement getTarget() { return new ASyntacticPredicate(statement.build()); } public SynPredicateBuilder predicate(StatementBuilder statement) { this.statement = statement; return this; } } private class DefaultTreeBuilder extends AbstractStatementBuilder implements TreeBuilder { private ATreeStatement tree; public DefaultTreeBuilder() { tree = new ATreeStatement(); } public TreeBuilder statement(StatementBuilder statement) { tree.add(statement.build()); return this; } @Override protected IStatement getTarget() { return tree; } } private class DefaultAlternativeBuilder extends AbstractStatementBuilder implements AlternativeBuilder { private AAlternative alternative; private List<IStatement> elements; public DefaultAlternativeBuilder() { alternative = new AAlternative(); elements = new ArrayList<IStatement>(); } public AlternativeBuilder start(CommonTree node) { alternative.setSourceStart(_start(node)); return this; } public AlternativeBuilder end(CommonTree node) { alternative.setSourceEnd(_end(node)); return this; } @Override protected IStatement getTarget() { Iterator<IStatement> iterator = elements.iterator(); while (iterator.hasNext()) { IStatement statement = iterator.next(); if (statement instanceof ISemanticPredicate && iterator.hasNext()) { ASemanticPredicate semanticPredicate = (ASemanticPredicate) statement; semanticPredicate.setPredicate(iterator.next()); AAlternative sempredAlt = new AAlternative(); sempredAlt.add(semanticPredicate); ABlock block = new ABlock(); block.add(sempredAlt); alternative.add(block); } else if (statement instanceof ISyntacticPredicate) { ASyntacticPredicate synpredicate = (ASyntacticPredicate) statement; AAlternative synElementAlts = new AAlternative(); // just eat all the elements while (iterator.hasNext()) { synElementAlts.add(iterator.next()); } ABlock synBlock = new ABlock(); synBlock.add(synElementAlts); synpredicate.setPredicate(synBlock); AAlternative synAlt = new AAlternative(); synAlt.add(synpredicate); ABlock block = new ABlock(); block.add(synAlt); alternative.add(block); } else { alternative.add(statement); } } elements.clear(); return alternative; } public AlternativeBuilder statement(StatementBuilder statement) { elements.add(statement.build()); return this; } public AlternativeBuilder statement(int index, StatementBuilder statement) { elements.add(index, statement.build()); return this; } public AlternativeBuilder rewrite(StatementBuilder statement) { ((BlockBuilder) statement).body(); alternative.setRewriteAlternative((IBlock) statement.build()); return this; } } private class DefaultActionBuilder extends AbstractStatementBuilder implements ActionBuilder { private ISourceElement action; @Override protected IStatement getTarget() { return new AStatementAction(action); } public ActionBuilder action(CommonTree actionNode) { action = createSourceElement(actionNode); return this; } } private class DefaultSemPredBuilder extends AbstractStatementBuilder implements SemPredicateBuilder { private ISourceElement condition; private PredicateType predicateType; private StatementBuilder predicate; @Override protected IStatement getTarget() { return new ASemanticPredicate(predicateType, condition, predicate != null ? predicate.build() : null); } public DefaultSemPredBuilder condition(CommonTree operatorNode) { condition = createSourceElement(operatorNode); return this; } public SemPredicateBuilder type(PredicateType predicateType) { this.predicateType = predicateType; return this; } public SemPredicateBuilder predicate(StatementBuilder predicate) { this.predicate = predicate; return this; } } private class DefaultRangeBuilder extends AbstractStatementBuilder implements RangeBuilder { private ICallExpression from; private ICallExpression to; private ISourceElement operator; @Override protected IStatement getTarget() { return new ARange(operator, from, to); } public RangeBuilder operator(CommonTree operatorNode) { operator = createSourceElement(operatorNode); return this; } public RangeBuilder from(CommonTree fromNode) { from = (ICallExpression) new DefaultCallExpressionBuilder().name( fromNode).build(); return this; } public RangeBuilder to(CommonTree toNode) { to = (ICallExpression) new DefaultCallExpressionBuilder().name( toNode).build(); return this; } } private class DefaultCallExpressionBuilder extends AbstractStatementBuilder implements CallExpressionBuilder { private ISourceElement name; private boolean label = false; private ASTSuffix suffix = ASTSuffix.NONE; private AParameters parameters; private List<ICallExpressionOption> options; public DefaultCallExpressionBuilder() { this.options = new ArrayList<ICallExpressionOption>(); } public CallExpressionBuilder name(CommonTree nameNode) { this.name = createSourceElement(nameNode); return this; } public CallExpressionBuilder parameters(CommonTree paramNode) { parameters = createParameters(null, paramNode); return this; } public CallExpressionBuilder option(CommonTree optionNode) { options.add(new ACallExpressionOption( createSourceElement(optionNode))); return this; } public CallExpressionBuilder option(CommonTree optionNode, CommonTree optionValue) { options.add(new ACallExpressionOption( createSourceElement(optionNode), createSourceElement(optionValue))); return this; } @Override public IStatement getTarget() { ACallExpression callExpression = new ACallExpression(name, suffix, label); if (parameters != null) { parameters.setParent(callExpression); callExpression.setParameters(parameters); } callExpression.setOptions(options .toArray(new ACallExpressionOption[options.size()])); return callExpression; } public CallExpressionBuilder labeled() { label = true; return this; } } private class DefaultTemplateBuilder extends AbstractStatementBuilder implements TemplateBuilder { private List<ITemplateParameter> parameters; private ATemplate template; public DefaultTemplateBuilder() { template = new ATemplate(); parameters = new ArrayList<ITemplateParameter>(); } @Override protected IStatement getTarget() { template.setParameters(parameters); if (!template.isInline() && template.hasParameters()) { // adjust the end position template.setSourceEnd(parameters.get(parameters.size() - 1) .sourceEnd()); } return template; } public TemplateBuilder name(CommonTree node) { template.setName(createSourceElement(node)); template.setSourceStart(_start(node)); return this; } public TemplateBuilder action(CommonTree node) { ISourceElement action = createSourceElement(node); template.setAction(action); template.setSourceStart(action.sourceStart()); template.setSourceEnd(action.sourceEnd()); return this; } public TemplateBuilder setSimpleActionTemplate(boolean value) { template.setSimpleActionTemplate(value); return this; } public TemplateBuilder parameter(CommonTree id, CommonTree action) { ITemplateParameter parameter = new ATemplateParameter( createSourceElement(id), createSourceElement(action)); parameters.add(parameter); return this; } public TemplateBuilder inlineTemplate(CommonTree node) { template.setInlineTemplate(createSourceElement(node)); template.setSourceEnd(_end(node)); return this; } } private AGrammar grammar; private Collection<IToken> tokens; private Collection<IScope> scopes; private Collection<IGrammarAction> actions; private Collection<IRule> rules; private Collection<IImport> imports; private String content; private RuleBuilder rule; private OptionsBuilder optionsBuilder; private ISourceLineTracker lineTracker; public DefaultGrammarBuilder(AGrammar grammar) { this.grammar = grammar; tokens = new ArrayList<IToken>(); scopes = new ArrayList<IScope>(5); actions = new ArrayList<IGrammarAction>(5); optionsBuilder = ExceptionSafeProxy.create(new DefaultOptionsBuilder(), OptionsBuilder.class); rules = new ArrayList<IRule>(); imports = new ArrayList<IImport>(); this.content = grammar.getSource(); lineTracker = TextUtils.createLineTracker(this.content); } public GrammarBuilderFactory importGrammar(CommonTree name) { importGrammar(name, null); return this; } public GrammarBuilderFactory imports(CommonTree startNode, CommonTree endNode) { AImports imports = new AImports(this.imports .toArray(new IImport[this.imports.size()])); imports.setSourceStart(_start(startNode)); imports.setSourceEnd(_end(endNode)); grammar.setImports(imports); return this; } private void processImports() { if (grammar.getFile() == null || !grammar.hasImports()) { return; } AntlrBuildUnit unit = AntlrBuildUnitRepository.create(grammar); Set<IFile> dependents = new HashSet<IFile>(); IImport[] imports = grammar.getImports().getImports(); for (IImport imp : imports) { try { IPath dependentPath = unit.getLibraryPath().append( imp.getElementName()).addFileExtension("g"); IFile dependentFile = ResourcesPlugin.getWorkspace().getRoot() .getFile(dependentPath); dependents.add(dependentFile); } catch (Exception ex) { ex.printStackTrace(); } } // check for self reference and remove it Iterator<IFile> iterator = dependents.iterator(); while (iterator.hasNext()) { IFile f = iterator.next(); if (f.getFullPath().equals(grammar.getFile())) { // avoid self reference iterator.remove(); } } unit.setDependents(dependents); } public GrammarBuilderFactory importGrammar(CommonTree name, CommonTree alias) { AImport imp = new AImport(createSourceElement(name), alias == null ? null : createSourceElement(alias)); imports.add(imp); return this; } public GrammarBuilderFactory action(CommonTree ampersandNode, CommonTree scopeNode, CommonTree nameNode, CommonTree actionNode) { int sourceStart = _start(ampersandNode); int sourceEnd = _end(actionNode); ISourceElement scope = scopeNode == null ? null : createSourceElement(scopeNode); ISourceElement name = nameNode == null ? null : createSourceElement(nameNode); ISourceElement actionCode = actionNode == null ? null : createSourceElement(actionNode); IGrammarAction action = new AGrammarAction(scope, name, actionCode, sourceStart, sourceEnd, _line(sourceStart), _line(sourceEnd)); this.actions.add(action); return this; } public GrammarBuilderFactory beginRule() { rule = ExceptionSafeProxy.create(new DefaultRuleBuilder(), RuleBuilder.class); return this; } public GrammarBuilderFactory endRule() { rules.add(rule.build()); rule = null; return this; } public RuleBuilder rule() { return rule; } public GrammarBuilderFactory rules() { grammar.setRules(rules); return this; } public GrammarBuilderFactory actions() { grammar.setActions(actions); return this; } public GrammarBuilderFactory action(CommonTree ampersandNode, CommonTree nameName, CommonTree actionNode) { return action(ampersandNode, null, nameName, actionNode); } public GrammarBuilderFactory scope(CommonTree nameNode, CommonTree actionNode) { AGrammarScope scope = new AGrammarScope(grammar, createSourceElement(nameNode)); IScopeAttribute[] attrs = createScopeAttrs(scope, actionNode); scope.setAttributes(attrs); scope.setSourceStart(_start(nameNode)); scope.setSourceEnd(_end(actionNode)); scopes.add(scope); return this; } public GrammarBuilderFactory scopes() { grammar.setScopes(scopes); return this; } public GrammarBuilder option(CommonTree name, CommonTree value) { optionsBuilder.option(name, value); return this; } public GrammarBuilder options(CommonTree startNode, CommonTree endNode) { optionsBuilder.options(startNode, endNode); AOptions options = optionsBuilder.build(); grammar.setOptions(options); options.setParent(grammar); return this; } public GrammarBuilderFactory type(GrammarType grammarType) { grammar.setGrammarType(grammarType); return this; } public GrammarBuilderFactory name(CommonTree node) { grammar.setName(createSourceElement(node)); return this; } public GrammarBuilderFactory documentation(CommonTree node) { grammar.setDocumentation(node.getText()); return this; } public GrammarBuilderFactory token(CommonTree nameNode, CommonTree valueNode) { ISourceElement name = createSourceElement(nameNode); ISourceElement value = valueNode == null ? null : createSourceElement(valueNode); AToken token = new AToken(name, value); this.tokens.add(token); return this; } public GrammarBuilderFactory token(CommonTree nameNode) { return token(nameNode, null); } public GrammarBuilderFactory tokens(CommonTree startNode, CommonTree endNode) { ATokens tokens = new ATokens(grammar, _start(startNode), _end(endNode)); tokens.setTokens(this.tokens); grammar.setTokens(tokens); return this; } protected ISourceElement createSourceElement(CommonTree node) { return createSourceElement(node, true); } protected ISourceElement createSourceElement(CommonTree node, boolean check) { CommonToken token = (CommonToken) node.getToken(); return createSourceElement(token, check); } protected int _start(Token token) { return _start((CommonToken) token); } protected int _start(CommonToken token) { return token.getStartIndex(); } protected int _start(CommonTree node) { return _start(node.token); } protected int _line(int offset) { return lineTracker.getLineNumberOfOffset(offset); } protected int _end(Token token) { return _end((CommonToken) token); } protected String _text(CommonTree node) { return _text(node.getToken()); } protected String _text(Token token) { if (token == null) return ""; String text = token.getText(); return text == null ? "" : text; } protected int _end(CommonToken token) { return token.getStopIndex(); } protected int _end(CommonTree node) { return _end(node.token); } public CallExpressionBuilder newCallExpressionBuilder() { return ExceptionSafeProxy.create(new DefaultCallExpressionBuilder(), CallExpressionBuilder.class); } public RangeBuilder newRangeBuilder() { return ExceptionSafeProxy.create(new DefaultRangeBuilder(), RangeBuilder.class); } public SemPredicateBuilder newSemPredBuilder() { return ExceptionSafeProxy.create(new DefaultSemPredBuilder(), SemPredicateBuilder.class); } public SynPredicateBuilder newSynPredBuilder() { return ExceptionSafeProxy.create(new DefaultSynPredBuilder(), SynPredicateBuilder.class); } public BlockBuilder newBlockBuilder() { return newBlockBuilder(false); } public BlockBuilder newBlockBuilder(boolean ruleBody) { return ExceptionSafeProxy.create(new DefaultBlockBuilder(ruleBody), BlockBuilder.class); } public ActionBuilder newActionBuilder() { return ExceptionSafeProxy.create(new DefaultActionBuilder(), ActionBuilder.class); } public AlternativeBuilder newAlternativeBuilder() { return ExceptionSafeProxy.create(new DefaultAlternativeBuilder(), AlternativeBuilder.class); } public AssignBuilder newAssignBuilder() { return ExceptionSafeProxy.create(new DefaultAssignBuilder(), AssignBuilder.class); } public TreeBuilder newTreeBuilder() { return ExceptionSafeProxy.create(new DefaultTreeBuilder(), TreeBuilder.class); } public TemplateBuilder newTemplateBuilder() { return ExceptionSafeProxy.create(new DefaultTemplateBuilder(), TemplateBuilder.class); } @SuppressWarnings("unchecked") public GrammarBuilder newGrammarBuilder() { return (GrammarBuilder) ExceptionSafeProxy.create(this, GrammarBuilder.class, GrammarBuilderFactory.class); } protected ISourceElement createSourceElement(CommonToken node) { return createSourceElement(node, node.getTokenIndex() != -1); } protected ISourceElement createSourceElement(CommonToken node, boolean check) { String text = node.getText(); int start = node.getStartIndex(); int end = node.getStopIndex() + 1; return createSourceElement(text, start, end, check); } protected ISourceElement createSourceElement(String text, int start, int end) { return createSourceElement(text, start, end, true); } protected ISourceElement createSourceElement(String text, int start, int end, boolean check) { try { if (check) { String chunk = content.substring(start, end); if (!text.equals(chunk)) { throw new IllegalArgumentException(String.format( "Expected %s found %s at %s..%s", text, chunk, start, end)); } } } catch (StringIndexOutOfBoundsException ex) { ex.printStackTrace(); } catch (IllegalArgumentException ex) { ex.printStackTrace(); } return new ASourceElement(text, start, end); } private IScopeAttribute[] createScopeAttrs(AScope scope, CommonTree action) { int offset = _start(action); String text = action.getText(); if (text.startsWith("{")) { text = text.substring(1); } if (text.endsWith("}")) { text = text.substring(0, text.length() - 1); } scope.setText(text); text = AntlrTextHelper.removeComments(text); String[] attrs = split(text, ",;"); int start, end; IScopeAttribute[] attributes = new IScopeAttribute[attrs.length]; int startIndex = 0; for (int i = 0; i < attrs.length; i++) { String[] attr = splitVariableDecl(attrs[i]); // create param name start = offset + text.indexOf(attr[0], startIndex) + 1; end = start + attr[0].length(); ISourceElement attrName = createSourceElement(attr[0], start, end); ISourceElement attrType = null; // create param type if (attr[1] != null) { int startType = offset + text.indexOf(attr[1], startIndex) + 1; end = startType + attr[1].length(); attrType = createSourceElement(attr[1], startType, end); } attributes[i] = new AScopeAttribute(scope, attrName, attrType); startIndex = start - offset + attr[0].length(); } return attributes; } private AParameters createParameters(IModelElement parent, CommonTree paramNode) { String text = AntlrTextHelper.removeComments(AntlrTextHelper .trimBracket(_text(paramNode))); int pstart = _start(paramNode); int pend = _end(paramNode); if (pstart == pend - 1) { pend = pstart + text.length(); } else { // eat the "[" pstart++; } ISourceElement action = createSourceElement(text, pstart, pend); String[] args = split(text, ","); IParameter[] params = new IParameter[args.length]; int start, end; for (int i = 0; i < args.length; i++) { // get param name and type String[] arg = splitVariableDecl(args[i]); // create param name start = action.sourceStart() + text.indexOf(arg[0]); end = start + arg[0].length(); ISourceElement paramName = createSourceElement(arg[0], start, end); ISourceElement paramType = null; // create param type if (arg[1] != null) { start = action.sourceStart() + text.indexOf(arg[1]); end = start + arg[1].length(); paramType = createSourceElement(arg[1], start, end); } AParameter parameter = new AParameter(paramName, paramType); params[i] = parameter; } AParameters parameters = new AParameters(parent, action); parameters.setParemeters(params); return parameters; } private String[] split(String text, String separators) { StringTokenizer tokenizer = new StringTokenizer(text, separators); Collection<String> tokens = new ArrayList<String>(5); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken().trim(); if (token.length() > 0) { tokens.add(token); } } String[] result = new String[tokens.size()]; result = tokens.toArray(result); tokens.clear(); return result; } private String[] splitVariableDecl(String text) { return splitVariableDecl(text, " \t\n\r\f"); } private String[] splitVariableDecl(String text, String separators) { StringTokenizer tokenizer = new StringTokenizer(text, separators); String[] arg = { null, null }; int tokenCount = tokenizer.countTokens(); if (tokenCount > 1) { arg[1] = tokenizer.nextToken().trim(); arg[0] = tokenizer.nextToken().trim(); } else if (tokenCount == 1) { arg[0] = tokenizer.nextToken().trim(); } return arg; } @Override public String toString() { return grammar.toString(); } public IGrammar build() { processImports(); this.actions.clear(); this.content = null; this.rules.clear(); this.scopes.clear(); this.tokens.clear(); this.imports.clear(); return grammar; } public static void main(String[] args) throws IOException, RecognitionException { String file = "grammar's/ANTLR/ANTLRv3.g"; String content = getContent(file); ANTLRLexer lexer = new ANTLRLexer(new ANTLRStringStream(content)); TokenStream tokens = new CommonTokenStream(lexer); ANTLRParser parser = new ANTLRParser(tokens); grammarDef_return grammarDef = parser.grammarDef(); CommonTreeNodeStream nodes = new CommonTreeNodeStream( (Tree) grammarDef.tree); nodes.setTokenStream(tokens); ANTLRTreeWalker walker = new ANTLRWalker(nodes); DefaultGrammarBuilder builder = new DefaultGrammarBuilder(new AGrammar( content)); walker.grammarDef(builder); } public static String getContent(String file) throws IOException { StringBuilder builder = new StringBuilder(); BufferedInputStream bis = new BufferedInputStream(new FileInputStream( file)); int readed = bis.read(); while (readed != -1) { builder.append((char) readed); readed = bis.read(); } bis.close(); return builder.toString(); } }