forked from jasder/antlr
Added lots of little stuff
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9310]
This commit is contained in:
parent
c8e9e12a74
commit
27cbd249ac
|
@ -181,7 +181,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
|
|||
|
||||
public void reportNoViableAlternative(BaseRecognizer recognizer,
|
||||
NoViableAltException e)
|
||||
throws RecognitionException
|
||||
throws RecognitionException
|
||||
{
|
||||
TokenStream tokens = (TokenStream)recognizer.getInputStream();
|
||||
String input = tokens.toString(e.startToken, e.offendingToken);
|
||||
|
|
|
@ -32,7 +32,9 @@ package org.antlr.v4.runtime;
|
|||
import org.antlr.v4.runtime.tree.*;
|
||||
import org.antlr.v4.runtime.tree.gui.TreeViewer;
|
||||
|
||||
public class DefaultANTLRTreeGrammarErrorStrategy extends DefaultANTLRErrorStrategy {
|
||||
import java.util.*;
|
||||
|
||||
public class DefaultANTLRTreeGrammarErrorStrategy<T> extends DefaultANTLRErrorStrategy {
|
||||
@Override
|
||||
public void beginErrorCondition(BaseRecognizer recognizer) {
|
||||
}
|
||||
|
@ -42,25 +44,74 @@ public class DefaultANTLRTreeGrammarErrorStrategy extends DefaultANTLRErrorStrat
|
|||
throws RecognitionException
|
||||
{
|
||||
super.reportError(recognizer, e);
|
||||
ASTNodeStream input = ((TreeParser) recognizer).getInputStream();
|
||||
TreeParser<T> parser = (TreeParser<T>)recognizer;
|
||||
ASTNodeStream input = parser.getInputStream();
|
||||
Object root = input.getTreeSource();
|
||||
if ( root instanceof AST ) {
|
||||
// If instanceof Tree, we can show in TreeViewer
|
||||
if ( root instanceof Tree ) {
|
||||
TreeViewer viewer = new TreeViewer(recognizer, (Tree)root);
|
||||
viewer.open();
|
||||
List<T> unmatchedNodes = null;
|
||||
if ( e instanceof NoViableTreeGrammarAltException ) {
|
||||
NoViableTreeGrammarAltException nva =
|
||||
(NoViableTreeGrammarAltException)e;
|
||||
// ((AST)nva.startNode).get
|
||||
unmatchedNodes = getNodeList(input, nva);
|
||||
}
|
||||
else {
|
||||
|
||||
unmatchedNodes = new ArrayList<T>();
|
||||
unmatchedNodes.add((T)e.offendingNode);
|
||||
}
|
||||
// input.get()
|
||||
// viewer.addHighlightedNodes();
|
||||
// TODO: highlight error node
|
||||
viewer.setHighlightedBoxColor(TreeViewer.LIGHT_RED);
|
||||
viewer.addHighlightedNodes((List<Tree>)unmatchedNodes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportNoViableAlternative(BaseRecognizer recognizer,
|
||||
NoViableAltException e)
|
||||
throws RecognitionException
|
||||
{
|
||||
TreeParser<T> parser = (TreeParser<T>)recognizer;
|
||||
ASTNodeStream input = parser.getInputStream();
|
||||
List<T> unmatchedNodes =
|
||||
getNodeList(input, (NoViableTreeGrammarAltException)e);
|
||||
StringBuffer buf = new StringBuffer();
|
||||
ASTAdaptor<T> adap = input.getTreeAdaptor();
|
||||
for (int i = 0; i < unmatchedNodes.size(); i++) {
|
||||
if ( i>0 ) buf.append(" ");
|
||||
T t = unmatchedNodes.get(i);
|
||||
buf.append(adap.getText(t));
|
||||
}
|
||||
String s = buf.toString();
|
||||
String msg = "no viable alternative at node(s) "+escapeWSAndQuote(s);
|
||||
recognizer.notifyListeners(e.offendingToken, msg, e);
|
||||
}
|
||||
|
||||
protected List<T> getNodeList(ASTNodeStream input,
|
||||
NoViableTreeGrammarAltException nva)
|
||||
{
|
||||
List<T> unmatchedNodes;
|
||||
T start = (T)nva.startNode;
|
||||
T stop = (T)nva.offendingNode;
|
||||
if ( input instanceof BufferedASTNodeStream) {
|
||||
BufferedASTNodeStream<T> b =
|
||||
(BufferedASTNodeStream<T>)input;
|
||||
unmatchedNodes = b.get(start, stop);
|
||||
}
|
||||
else {
|
||||
// if not buffered then we can't get from start to stop;
|
||||
// just highlight the start/stop nodes, but not in between
|
||||
unmatchedNodes = new ArrayList<T>();
|
||||
if ( nva.startNode!=null ) {
|
||||
unmatchedNodes.add((T)nva.startNode);
|
||||
}
|
||||
if ( nva.startNode==null || nva.offendingNode!=nva.startNode ) {
|
||||
unmatchedNodes.add((T)nva.offendingNode);
|
||||
}
|
||||
}
|
||||
return unmatchedNodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object recoverInline(BaseRecognizer recognizer) throws RecognitionException {
|
||||
InputMismatchException e = new InputMismatchException(recognizer);
|
||||
|
@ -70,9 +121,7 @@ public class DefaultANTLRTreeGrammarErrorStrategy extends DefaultANTLRErrorStrat
|
|||
|
||||
@Override
|
||||
public void recover(BaseRecognizer recognizer, RecognitionException e) {
|
||||
throw new RecognitionException(recognizer,
|
||||
recognizer.getInputStream(),
|
||||
recognizer._ctx);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -136,7 +136,7 @@ public abstract class Lexer extends Recognizer<LexerATNSimulator>
|
|||
}
|
||||
catch (LexerNoViableAltException e) {
|
||||
notifyListeners(e); // report error
|
||||
recover();
|
||||
recover(e);
|
||||
ttype = SKIP;
|
||||
}
|
||||
if ( input.LA(1)==CharStream.EOF ) {
|
||||
|
@ -301,7 +301,7 @@ public abstract class Lexer extends Recognizer<LexerATNSimulator>
|
|||
return null;
|
||||
}
|
||||
|
||||
public void recover() {
|
||||
public void recover(LexerNoViableAltException e) {
|
||||
_interp.consume(input); // skip a char and try again
|
||||
}
|
||||
|
||||
|
|
|
@ -38,16 +38,24 @@ public class NoViableTreeGrammarAltException extends NoViableAltException {
|
|||
protected Object offendingNode;
|
||||
|
||||
public NoViableTreeGrammarAltException(BaseRecognizer recognizer) {
|
||||
super(recognizer);
|
||||
this(recognizer,
|
||||
(ASTNodeStream<Object>)recognizer.getInputStream(),
|
||||
recognizer.getCurrentInputSymbol(),
|
||||
recognizer.getCurrentInputSymbol(),
|
||||
null,
|
||||
recognizer._ctx);
|
||||
}
|
||||
|
||||
public NoViableTreeGrammarAltException(BaseRecognizer recognizer,
|
||||
ASTNodeStream input,
|
||||
ASTNodeStream<Object> input,
|
||||
Object startNode,
|
||||
Object offendingNode,
|
||||
OrderedHashSet<ATNConfig> deadEndConfigs,
|
||||
RuleContext ctx) {
|
||||
super(recognizer, input, null, null, deadEndConfigs, ctx);
|
||||
super(recognizer, input,
|
||||
input.getTreeAdaptor().getToken(startNode),
|
||||
input.getTreeAdaptor().getToken(offendingNode),
|
||||
deadEndConfigs, ctx);
|
||||
this.startNode = startNode;
|
||||
this.offendingNode = offendingNode;
|
||||
}
|
||||
|
|
|
@ -852,15 +852,20 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
public int throwNoViableAlt(ObjectStream input, RuleContext outerContext,
|
||||
OrderedHashSet<ATNConfig> configs, int startIndex)
|
||||
{
|
||||
Object startNode = null;
|
||||
if ( input instanceof BufferedASTNodeStream ) {
|
||||
startNode = input.get(startIndex);
|
||||
}
|
||||
if ( parser instanceof TreeParser) {
|
||||
throw new NoViableTreeGrammarAltException(parser, (ASTNodeStream)input,
|
||||
input.get(startIndex),
|
||||
throw new NoViableTreeGrammarAltException(parser,
|
||||
(ASTNodeStream<Object>)input,
|
||||
startNode,
|
||||
input.LT(1),
|
||||
configs, outerContext);
|
||||
}
|
||||
else {
|
||||
throw new NoViableAltException(parser, input,
|
||||
(Token)input.get(startIndex),
|
||||
(Token) startNode,
|
||||
(Token)input.LT(1),
|
||||
configs, outerContext);
|
||||
}
|
||||
|
|
|
@ -42,17 +42,18 @@ import java.util.List;
|
|||
public interface ASTAdaptor<T> {
|
||||
// BEGIN new v4 stuff
|
||||
|
||||
// If not null root, add kids to it
|
||||
//public void addChildren(Object root, List kids);
|
||||
|
||||
//public List getChildren(Object root);
|
||||
|
||||
/** Used to track elements to left of -> for use in rewrite. These
|
||||
* are some kind of trees, but we generically use Object
|
||||
* for tree types in ANTLR.
|
||||
*/
|
||||
public List<T> createElementList();
|
||||
|
||||
/** Get the absolute index starting from 0 of this note within
|
||||
* a node stream. This should w
|
||||
ork even if the stream is not buffered
|
||||
*/
|
||||
// public int getNodeIndex(T t);
|
||||
|
||||
// END new v4 stuff
|
||||
|
||||
// C o n s t r u c t i o n
|
||||
|
|
|
@ -213,6 +213,29 @@ public class BufferedASTNodeStream<T> implements ASTNodeStream<T> {
|
|||
return nodes.get(i);
|
||||
}
|
||||
|
||||
public List<T> get(int i, int j) {
|
||||
if ( p==-1 ) {
|
||||
fillBuffer();
|
||||
}
|
||||
return nodes.subList(i,j+1);
|
||||
}
|
||||
|
||||
public List<T> get(T start, T stop) {
|
||||
int i=0;
|
||||
for (; i<nodes.size(); i++) {
|
||||
T t = nodes.get(i);
|
||||
if ( t==start ) break;
|
||||
}
|
||||
int j=i;
|
||||
for (; j<nodes.size(); j++) {
|
||||
T t = nodes.get(j);
|
||||
if ( t==stop ) break;
|
||||
}
|
||||
if ( i>=nodes.size() ) return null;
|
||||
if ( j>=nodes.size() ) j = nodes.size()-1;
|
||||
return get(i,j);
|
||||
}
|
||||
|
||||
public T LT(int k) {
|
||||
if ( p==-1 ) {
|
||||
fillBuffer();
|
||||
|
|
|
@ -130,6 +130,7 @@ public class CommonASTAdaptor extends BaseASTAdaptor<CommonAST> {
|
|||
* override this in your own adaptor.
|
||||
*/
|
||||
public Token getToken(CommonAST t) {
|
||||
if ( t==null ) return null;
|
||||
return t.getToken();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class TreeParser<T> extends BaseRecognizer {
|
|||
public static final int DOWN = Token.DOWN;
|
||||
public static final int UP = Token.UP;
|
||||
|
||||
public ASTAdaptor _adaptor = new CommonASTAdaptor();
|
||||
public ASTAdaptor<T> _adaptor = (ASTAdaptor<T>)new CommonASTAdaptor();
|
||||
|
||||
// precompiled regex used by inContext
|
||||
static String dotdot = ".*[^.]\\.\\.[^.].*";
|
||||
|
@ -53,7 +53,7 @@ public class TreeParser<T> extends BaseRecognizer {
|
|||
|
||||
public TreeParser(ASTNodeStream<T> input) {
|
||||
super(input);
|
||||
_errHandler = new DefaultANTLRTreeGrammarErrorStrategy();
|
||||
_errHandler = new DefaultANTLRTreeGrammarErrorStrategy<T>();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
|
|
|
@ -232,6 +232,7 @@ public class TreeViewer extends JComponent {
|
|||
ok.addActionListener(
|
||||
new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dialog.setVisible(false);
|
||||
dialog.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
grammar E;
|
||||
|
||||
@lexer::members {
|
||||
public void recover(LexerNoViableAltException e) {
|
||||
super.recover(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
prog: classDef+ ; // match one or more class definitions
|
||||
|
||||
classDef
|
||||
|
|
|
@ -188,12 +188,10 @@ RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAc
|
|||
<postamble; separator="\n">
|
||||
<namedActions.after>
|
||||
}
|
||||
<if(currentRule.catch_)>
|
||||
catch (RecognitionException re) {
|
||||
_errHandler.reportError(this, re);
|
||||
_errHandler.recover(this, re);
|
||||
}
|
||||
<endif>
|
||||
finally {
|
||||
<finallyAction>
|
||||
exitRule(RULE_<currentRule.name>);
|
||||
|
@ -378,6 +376,14 @@ case <i>:
|
|||
Sync(s) ::= "sync(<s.expecting.name>);"
|
||||
|
||||
ThrowNoViableAlt(t) ::= "throw new NoViableAltException(this);"
|
||||
ThrowNoViableTreeAlt(t) ::= <<
|
||||
/*
|
||||
NoViableTreeGrammarAltException e<choice.uniqueID> = new NoViableTreeGrammarAltException(this);
|
||||
_errHandler.reportError(this, e<choice.uniqueID>);
|
||||
throw e<choice.uniqueID>;
|
||||
*/
|
||||
throw new NoViableTreeGrammarAltException(this);
|
||||
>>
|
||||
|
||||
TestSetInline(s) ::= <<
|
||||
<s.ttypes:{ttype | <s.varName>==<ttype>}; separator=" || ">
|
||||
|
|
|
@ -30,14 +30,12 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.model.decl.Decl;
|
||||
import org.antlr.v4.codegen.model.decl.TokenTypeDecl;
|
||||
import org.antlr.v4.codegen.model.decl.*;
|
||||
import org.antlr.v4.misc.Utils;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/** The class hierarchy underneath SrcOp is pretty deep but makes sense that,
|
||||
* for example LL1StarBlock is a kind of LL1Loop which is a kind of Choice.
|
||||
|
@ -89,4 +87,15 @@ public abstract class Choice extends RuleElement {
|
|||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
public ThrowNoViableAlt getThrowNoViableAlt(OutputModelFactory factory,
|
||||
GrammarAST blkAST,
|
||||
IntervalSet expecting) {
|
||||
if ( factory.getGrammar().isTreeGrammar() ) {
|
||||
return new ThrowNoViableTreeAlt(factory, blkAST, expecting);
|
||||
}
|
||||
else {
|
||||
return new ThrowNoViableAlt(factory, blkAST, expecting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public class LL1AltBlock extends LL1Choice {
|
|||
altLook = getAltLookaheadAsStringLists(altLookSets);
|
||||
|
||||
IntervalSet expecting = IntervalSet.or(altLookSets); // combine alt sets
|
||||
this.error = new ThrowNoViableAlt(factory, blkAST, expecting);
|
||||
this.error = getThrowNoViableAlt(factory, blkAST, expecting);
|
||||
System.out.println(blkAST.toStringTree()+" LL1AltBlock expecting="+expecting);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class LL1OptionalBlockSingleAlt extends LL1Choice {
|
|||
IntervalSet followLook = altLookSets[2];
|
||||
|
||||
IntervalSet expecting = (IntervalSet)look.or(followLook);
|
||||
this.error = new ThrowNoViableAlt(factory, blkAST, expecting);
|
||||
this.error = getThrowNoViableAlt(factory, blkAST, expecting);
|
||||
System.out.println(blkAST.toStringTree()+" LL1OptionalBlockSingleAlt expecting="+expecting);
|
||||
|
||||
expr = addCodeForLookaheadTempVar(look);
|
||||
|
|
|
@ -29,8 +29,7 @@
|
|||
|
||||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.CodeGenerator;
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.*;
|
||||
import org.antlr.v4.runtime.atn.PlusBlockStartState;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
|
@ -67,7 +66,7 @@ public class LL1PlusBlock extends LL1Loop {
|
|||
IntervalSet all = new IntervalSet();
|
||||
for (IntervalSet s : altLookSets) all.addAll(s);
|
||||
|
||||
this.error = new ThrowNoViableAlt(factory, plusRoot, all);
|
||||
this.error = getThrowNoViableAlt(factory, plusRoot, all);
|
||||
|
||||
loopExpr = addCodeForLoopLookaheadTempVar(all);
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public class PlusBlock extends Loop {
|
|||
stateNumber = blkStart.loopBackState.stateNumber;
|
||||
blockStartStateNumber = blkStart.stateNumber;
|
||||
loopBackStateNumber = loop.stateNumber;
|
||||
this.error = new ThrowNoViableAlt(factory, plusRoot, null);
|
||||
this.error = getThrowNoViableAlt(factory, plusRoot, null);
|
||||
decision = loop.decision;
|
||||
exitAlt = alts.size()+1;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ public class RuleFunction extends OutputModelObject {
|
|||
public int index;
|
||||
public Collection<Attribute> args = null;
|
||||
public Rule rule;
|
||||
public boolean catch_;
|
||||
|
||||
@ModelElement public List<SrcOp> code;
|
||||
@ModelElement public OrderedHashSet<Decl> locals; // TODO: move into ctx?
|
||||
|
@ -74,8 +73,6 @@ public class RuleFunction extends OutputModelObject {
|
|||
|
||||
index = r.index;
|
||||
|
||||
catch_ = !r.g.isTreeGrammar();
|
||||
|
||||
ruleCtx = r.g.isTreeGrammar() ?
|
||||
new TreeParserStructDecl(factory, r) :
|
||||
new StructDecl(factory, r);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
[The "BSD license"]
|
||||
Copyright (c) 2011 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
|
||||
public class ThrowNoViableTreeAlt extends ThrowNoViableAlt {
|
||||
public ThrowNoViableTreeAlt(OutputModelFactory factory,
|
||||
GrammarAST blkOrEbnfRootAST,
|
||||
IntervalSet expecting)
|
||||
{
|
||||
super(factory, blkOrEbnfRootAST, expecting);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue