/*
* Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC
* All rights reserved.
*
* The source code of this document is proprietary work, and is not licensed for
* distribution. For information about licensing, contact Sam Harwell at:
* sam@tunnelvisionlabs.com
*/
package org.antlr.works.editor.grammar.navigation;
import org.antlr.grammar.v3.ANTLRParser;
import org.antlr.netbeans.editor.text.DocumentSnapshot;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;
import org.antlr.tool.Grammar;
import org.antlr.works.editor.grammar.parser.CompiledFileModelV3;
import org.antlr.works.editor.grammar.parser.CompiledModel;
import org.antlr.works.editor.grammar.parser.CompiledModelV3;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
/**
*
* @author Sam Harwell
*/
public class RuleScannerV3 extends RuleScanner {
@Override
public GrammarNode.GrammarNodeDescription scanImpl(CompiledModel baseModel) {
try {
CompiledModelV3 model = (CompiledModelV3)baseModel;
// GrammarRulesPanelUI ui = GrammarRulesPanel.findGrammarRulesPanelUI();
// if (ui == null) {
// return;
// }
// don't update if there were errors and a result is already displayed
/*if (!result.getParser().getSyntaxErrors().isEmpty() && !ui.isShowingWaitNode()) {
return;
}*/
GrammarNode.GrammarNodeDescription rootDescription = new GrammarNode.GrammarNodeDescription(DeclarationKind.UNDEFINED);
rootDescription.setFileObject(model.getSnapshot().getVersionedDocument().getFileObject());
GrammarNode.GrammarNodeDescription parserRulesRootDescription = new GrammarNode.GrammarNodeDescription(DeclarationKind.PARSER_RULE, "1" + Bundle.LBL_ParserRules());
parserRulesRootDescription.setHtmlHeader(Bundle.LBL_ParserRules());
GrammarNode.GrammarNodeDescription lexerRulesRootDescription = new GrammarNode.GrammarNodeDescription(DeclarationKind.LEXER_RULE, "2" + Bundle.LBL_LexerRules());
lexerRulesRootDescription.setHtmlHeader(Bundle.LBL_LexerRules());
for (CompiledFileModelV3 importedParseResult : model.getImportedGrammarResults()) {
processParseResult(null, importedParseResult, parserRulesRootDescription, lexerRulesRootDescription);
}
processParseResult(model.getSnapshot(), model.getResult(), parserRulesRootDescription, lexerRulesRootDescription);
if (!parserRulesRootDescription.getChildren().isEmpty()) {
rootDescription.getChildren().add(parserRulesRootDescription);
}
if (!lexerRulesRootDescription.getChildren().isEmpty()) {
rootDescription.getChildren().add(lexerRulesRootDescription);
}
return rootDescription;
} catch (RuntimeException ex) {
Exceptions.printStackTrace(ex);
return null;
}
}
private void processParseResult(DocumentSnapshot snapshot,
CompiledFileModelV3 result,
GrammarNode.GrammarNodeDescription parserRulesRootDescription,
GrammarNode.GrammarNodeDescription lexerRulesRootDescription) {
ANTLRParser.grammar__return parseResult = result.getResult();
if (parseResult == null) {
return;
}
FileObject fileObject = result.getFileObject();
Tree tree = parseResult.getTree();
int childCount = tree.getChildCount();
for (int i = 0; i < childCount; i++) {
Object childObject = tree.getChild(i);
if (!(childObject instanceof CommonTree)) {
continue;
}
CommonTree child = (CommonTree) childObject;
if (child.getChildCount() > 0 && "rule".equals(child.getText())) {
String ruleName = child.getChild(0).getText();
if ("Tokens".equals(ruleName)) {
continue;
}
DeclarationKind declarationKind;
if (org.antlr.v4.tool.Grammar.isTokenName(ruleName)) {
declarationKind = DeclarationKind.LEXER_RULE;
} else {
declarationKind = DeclarationKind.PARSER_RULE;
}
GrammarNode.GrammarNodeDescription ruleDescription = new GrammarNode.GrammarNodeDescription(declarationKind, ruleName);
ruleDescription.setOffset(snapshot, fileObject, getElementOffset(child));
ruleDescription.setSpan(getSpan(snapshot, result, child));
ruleDescription.setInherited(snapshot == null); // for now, go on the fact that snapshots aren't available for imported files
if (Character.isLowerCase(ruleName.charAt(0))) {
parserRulesRootDescription.getChildren().add(ruleDescription);
} else {
lexerRulesRootDescription.getChildren().add(ruleDescription);
}
} else if (child.getText() != null && child.getText().startsWith("tokens")) {
for (int j = 0; j < child.getChildCount(); j++) {
CommonTree tokenChild = (CommonTree)child.getChild(j);
if ("=".equals(tokenChild.getText()) && tokenChild.getChildCount() == 2) {
String ruleName = tokenChild.getChild(0).getText();
if (ruleName == null || ruleName.length() == 0) {
continue;
}
GrammarNode.GrammarNodeDescription ruleDescription = new GrammarNode.GrammarNodeDescription(DeclarationKind.TOKEN, ruleName);
ruleDescription.setOffset(snapshot, fileObject, getElementOffset(tokenChild));
ruleDescription.setSpan(getSpan(snapshot, result, child));
ruleDescription.setInherited(snapshot == null); // for now, go on the fact that snapshots aren't available for imported files
if (Character.isLowerCase(ruleName.charAt(0))) {
parserRulesRootDescription.getChildren().add(ruleDescription);
} else {
lexerRulesRootDescription.getChildren().add(ruleDescription);
}
} else if (tokenChild.getChildCount() == 0) {
String ruleName = tokenChild.getText();
if (ruleName == null || ruleName.length() == 0) {
continue;
}
GrammarNode.GrammarNodeDescription ruleDescription = new GrammarNode.GrammarNodeDescription(DeclarationKind.TOKEN, ruleName);
ruleDescription.setOffset(snapshot, fileObject, getElementOffset(tokenChild));
ruleDescription.setSpan(getSpan(snapshot, result, child));
ruleDescription.setInherited(snapshot == null); // for now, go on the fact that snapshots aren't available for imported files
if (Character.isLowerCase(ruleName.charAt(0))) {
parserRulesRootDescription.getChildren().add(ruleDescription);
} else {
lexerRulesRootDescription.getChildren().add(ruleDescription);
}
}
}
}
}
}
private int getElementOffset(CommonTree tree) {
switch (tree.getType()) {
case ANTLRParser.ASSIGN:
case ANTLRParser.RULE:
if (tree.getChildCount() > 0 && tree.getChild(0) instanceof CommonTree) {
CommonTree child = (CommonTree)tree.getChild(0);
if (child.getToken() instanceof CommonToken) {
CommonToken token = (CommonToken)child.getToken();
return token.getStartIndex();
}
}
break;
case ANTLRParser.TOKEN_REF:
break;
default:
throw new UnsupportedOperationException();
}
if (tree.getToken() instanceof CommonToken) {
return ((CommonToken)tree.getToken()).getStartIndex();
}
return 0;
}
}