/* * 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.st4.parser; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import org.antlr.netbeans.editor.parsing.SyntaxError; import org.antlr.netbeans.editor.text.DocumentSnapshot; import org.antlr.netbeans.parsing.spi.BaseParserData; import org.antlr.netbeans.parsing.spi.ParseContext; import org.antlr.netbeans.parsing.spi.ParserDataDefinition; import org.antlr.netbeans.parsing.spi.ParserResultHandler; import org.antlr.netbeans.parsing.spi.ParserTaskManager; import org.antlr.runtime.ANTLRStringStream; import org.antlr.runtime.CommonToken; import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.RecognitionException; import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.CommonTreeAdaptor; import org.antlr.runtime.tree.TreeAdaptor; import org.antlr.works.editor.st4.TemplateParserDataDefinitions; import org.netbeans.api.annotations.common.NonNull; import org.openide.filesystems.FileObject; import org.openide.util.Parameters; import org.stringtemplate.v4.compiler.CompiledST; import org.stringtemplate.v4.compiler.GroupLexer; /** * * @author Sam Harwell */ public class CompiledModelParser { // -J-Dorg.antlr.works.editor.st4.parser.CompiledModelParser.level=FINE private static final Logger LOGGER = Logger.getLogger(CompiledModelParser.class.getName()); private final Object lock = new Object(); private DocumentSnapshot lastSnapshot; private CompiledFileModel lastResult; private Throwable lastException; public void parse(ParserTaskManager taskManager, ParseContext context, DocumentSnapshot snapshot, Collection<? extends ParserDataDefinition<?>> requestedData, ParserResultHandler results) throws InterruptedException, ExecutionException { try { if (requestedData.contains(TemplateParserDataDefinitions.COMPILED_MODEL)) { CompiledModel result = parseImpl(taskManager, context, snapshot); BaseParserData<CompiledModel> data = new BaseParserData<>(context, TemplateParserDataDefinitions.COMPILED_MODEL, snapshot, result); results.addResult(data); } } catch (ExecutionException ex) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "An error occurred while parsing.", ex); } } } protected CompiledModel parseImpl(@NonNull ParserTaskManager taskManager, ParseContext context, DocumentSnapshot snapshot) throws InterruptedException, ExecutionException { Parameters.notNull("snapshot", snapshot); synchronized (lock) { if (snapshot.equals(lastSnapshot)) { if (lastException != null) { throw new ExecutionException("An unexpected error occurred.", lastException); } return new CompiledModel(snapshot, lastResult); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Reparsing snapshot {0}", snapshot); } try { final List<SyntaxError> syntaxErrors = new ArrayList<>(); ANTLRStringStream input = new ANTLRStringStream(snapshot.getText().toString()); input.name = snapshot.getVersionedDocument().getFileObject().getNameExt(); GroupLexer lexer = new GroupLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); GroupParserWrapper parser = new GroupParserWrapper(tokens, snapshot); TemplateGroupWrapper group = new TemplateGroupWrapper('<', '>'); try { parser.group(group, "/"); TemplateGroupRuleReturnScope returnScope = buildAstForGroupTemplates(group); FileObject fileObject = snapshot.getVersionedDocument().getFileObject(); CommonToken[] groupTokens = tokens.getTokens().toArray(new CommonToken[0]); lastSnapshot = snapshot; lastResult = new CompiledFileModel(parser, returnScope, syntaxErrors, fileObject, groupTokens); lastException = null; return new CompiledModel(snapshot, lastResult); } catch (RecognitionException ex) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "A recognition exception occurred while parsing.", ex); } lastSnapshot = snapshot; lastResult = null; lastException = null; return null; } } catch (Exception ex) { lastSnapshot = snapshot; lastResult = null; lastException = ex; throw new ExecutionException("An unexpected error occurred.", ex); } } } private TemplateGroupRuleReturnScope buildAstForGroupTemplates(TemplateGroupWrapper group) { TreeAdaptor adaptor = new CommonTreeAdaptor(); Object tree = adaptor.nil(); for (CompiledST template : group.getCompiledTemplates()) { adaptor.addChild(tree, template.ast); } return new TemplateGroupRuleReturnScope(group, (CommonTree)tree); } }