Exceptions now work on rules. If you specify at least one catch, then it overrides all catches that ANTLR generates. Otherwise, there would be no way to override the generic recognition exception clause.

This commit is contained in:
Terence Parr 2012-09-22 11:58:41 -07:00
parent 8a928d4326
commit 01b5510be1
14 changed files with 150 additions and 59 deletions

View File

@ -1,10 +1,9 @@
grammar A;
s : e ;
e : e '*' e # Mult
| INT # primary
;
s : INT ;
catch[T x] {foo}
catch[U y] {bar}
finally { xxxxx }
INT : [0-9]+ ;
WS : [ \t\n]+ -> skip ;

View File

@ -187,7 +187,7 @@ case <index> : return <actions.(index)>;}; separator="\n">
}
>>
RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble) ::= <<
RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble,exceptions) ::= <<
<ruleCtx>
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
@ -205,12 +205,15 @@ RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAc
<postamble; separator="\n">
<namedActions.after>
}
<currentRule.exceptions>
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
<if(exceptions)>
<exceptions; separator="\n">
<else>
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
<endif>
finally {
<finallyAction>
exitRule();
@ -473,6 +476,12 @@ setState(<p.stateNumber>);
if (!(<chunks>)) throw new FailedPredicateException(this, <if(p.msg)><p.msg><else><failChunks><endif>);
>>
ExceptionClause(e, catchArg, catchAction) ::= <<
catch (<catchArg>) {
<catchAction>
}
>>
// lexer actions are not associated with model objects
LexerSkipCommand() ::= "skip();"

View File

@ -29,10 +29,21 @@
package org.antlr.v4.codegen;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.Choice;
import org.antlr.v4.codegen.model.CodeBlockForAlt;
import org.antlr.v4.codegen.model.LabeledOp;
import org.antlr.v4.codegen.model.Lexer;
import org.antlr.v4.codegen.model.LexerFile;
import org.antlr.v4.codegen.model.Parser;
import org.antlr.v4.codegen.model.ParserFile;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import java.util.List;
@ -84,13 +95,10 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory {
// ACTIONS
@Override
public List<SrcOp> action(GrammarAST ast) { return null; }
public List<SrcOp> action(ActionAST ast) { return null; }
@Override
public List<SrcOp> forcedAction(GrammarAST ast) { return null; }
@Override
public List<SrcOp> sempred(GrammarAST ast) { return null; }
public List<SrcOp> sempred(ActionAST ast) { return null; }
// BLOCKS

View File

@ -410,13 +410,13 @@ public class OutputModelController {
return ops;
}
public List<SrcOp> action(GrammarAST ast) {
public List<SrcOp> action(ActionAST ast) {
List<SrcOp> ops = delegate.action(ast);
for (CodeGeneratorExtension ext : extensions) ops = ext.action(ops);
return ops;
}
public List<SrcOp> sempred(GrammarAST ast) {
public List<SrcOp> sempred(ActionAST ast) {
List<SrcOp> ops = delegate.sempred(ast);
for (CodeGeneratorExtension ext : extensions) ops = ext.sempred(ops);
return ops;

View File

@ -29,11 +29,25 @@
package org.antlr.v4.codegen;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.Choice;
import org.antlr.v4.codegen.model.CodeBlockForAlt;
import org.antlr.v4.codegen.model.CodeBlockForOuterMostAlt;
import org.antlr.v4.codegen.model.LabeledOp;
import org.antlr.v4.codegen.model.Lexer;
import org.antlr.v4.codegen.model.LexerFile;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.codegen.model.Parser;
import org.antlr.v4.codegen.model.ParserFile;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.codegen.model.decl.CodeBlock;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import java.util.List;
@ -76,11 +90,9 @@ public interface OutputModelFactory {
List<SrcOp> wildcard(GrammarAST ast, GrammarAST labelAST);
List<SrcOp> action(GrammarAST ast);
List<SrcOp> action(ActionAST ast);
List<SrcOp> forcedAction(GrammarAST ast);
List<SrcOp> sempred(GrammarAST ast);
List<SrcOp> sempred(ActionAST ast);
Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label);

View File

@ -30,13 +30,50 @@
package org.antlr.v4.codegen;
import org.antlr.v4.analysis.AnalysisPipeline;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.codegen.model.Action;
import org.antlr.v4.codegen.model.AddToLabelList;
import org.antlr.v4.codegen.model.AltBlock;
import org.antlr.v4.codegen.model.Choice;
import org.antlr.v4.codegen.model.CodeBlockForAlt;
import org.antlr.v4.codegen.model.CodeBlockForOuterMostAlt;
import org.antlr.v4.codegen.model.InvokeRule;
import org.antlr.v4.codegen.model.LL1AltBlock;
import org.antlr.v4.codegen.model.LL1OptionalBlock;
import org.antlr.v4.codegen.model.LL1OptionalBlockSingleAlt;
import org.antlr.v4.codegen.model.LL1PlusBlock;
import org.antlr.v4.codegen.model.LL1PlusBlockSingleAlt;
import org.antlr.v4.codegen.model.LL1StarBlock;
import org.antlr.v4.codegen.model.LL1StarBlockSingleAlt;
import org.antlr.v4.codegen.model.LabeledOp;
import org.antlr.v4.codegen.model.LeftRecursiveRuleFunction;
import org.antlr.v4.codegen.model.MatchNotSet;
import org.antlr.v4.codegen.model.MatchSet;
import org.antlr.v4.codegen.model.MatchToken;
import org.antlr.v4.codegen.model.OptionalBlock;
import org.antlr.v4.codegen.model.Parser;
import org.antlr.v4.codegen.model.ParserFile;
import org.antlr.v4.codegen.model.PlusBlock;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.codegen.model.SemPred;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.codegen.model.StarBlock;
import org.antlr.v4.codegen.model.TestSetInline;
import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
import org.antlr.v4.codegen.model.decl.TokenDecl;
import org.antlr.v4.codegen.model.decl.TokenListDecl;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.atn.DecisionState;
import org.antlr.v4.runtime.atn.PlusBlockStartState;
import org.antlr.v4.runtime.atn.StarLoopEntryState;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.TerminalAST;
import java.util.List;
@ -83,10 +120,10 @@ public class ParserFactory extends DefaultOutputModelFactory {
}
@Override
public List<SrcOp> action(GrammarAST ast) { return list(new Action(this, ast)); }
public List<SrcOp> action(ActionAST ast) { return list(new Action(this, ast)); }
@Override
public List<SrcOp> sempred(GrammarAST ast) { return list(new SemPred(this, ast)); }
public List<SrcOp> sempred(ActionAST ast) { return list(new SemPred(this, ast)); }
@Override
public List<SrcOp> ruleRef(GrammarAST ID, GrammarAST label, GrammarAST args) {

View File

@ -107,10 +107,10 @@ element returns [List<? extends SrcOp> omos]
: labeledElement {$omos = $labeledElement.omos;}
| atom[null,false] {$omos = $atom.omos;}
| subrule {$omos = $subrule.omos;}
| ACTION {$omos = controller.action($ACTION);}
| SEMPRED {$omos = controller.sempred($SEMPRED);}
| ^(ACTION elementOptions) {$omos = controller.action($ACTION);}
| ^(SEMPRED elementOptions) {$omos = controller.sempred($SEMPRED);}
| ACTION {$omos = controller.action((ActionAST)$ACTION);}
| SEMPRED {$omos = controller.sempred((ActionAST)$SEMPRED);}
| ^(ACTION elementOptions) {$omos = controller.action((ActionAST)$ACTION);}
| ^(SEMPRED elementOptions) {$omos = controller.sempred((ActionAST)$SEMPRED);}
;
labeledElement returns [List<? extends SrcOp> omos]

View File

@ -30,20 +30,24 @@
package org.antlr.v4.codegen.model;
import org.antlr.runtime.CommonToken;
import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.model.chunk.*;
import org.antlr.v4.codegen.ActionTranslator;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.chunk.ActionChunk;
import org.antlr.v4.codegen.model.chunk.ActionTemplate;
import org.antlr.v4.codegen.model.chunk.ActionText;
import org.antlr.v4.codegen.model.decl.StructDecl;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.ast.*;
import org.antlr.v4.tool.ast.ActionAST;
import org.stringtemplate.v4.ST;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
/** */
public class Action extends RuleElement {
@ModelElement public List<ActionChunk> chunks;
public Action(OutputModelFactory factory, GrammarAST ast) {
public Action(OutputModelFactory factory, ActionAST ast) {
super(factory,ast);
RuleFunction rf = factory.getCurrentRuleFunction();
if (ast != null) {

View File

@ -30,12 +30,12 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.ActionAST;
public class ArgAction extends Action {
/** Context type of invoked rule */
public String ctxType;
public ArgAction(OutputModelFactory factory, GrammarAST ast, String ctxType) {
public ArgAction(OutputModelFactory factory, ActionAST ast, String ctxType) {
super(factory, ast);
this.ctxType = ctxType;
}

View File

@ -0,0 +1,18 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.ast.ActionAST;
public class ExceptionClause extends SrcOp {
@ModelElement public Action catchArg;
@ModelElement public Action catchAction;
public ExceptionClause(OutputModelFactory factory,
ActionAST catchArg,
ActionAST catchAction)
{
super(factory, catchArg);
this.catchArg = new Action(factory, catchArg);
this.catchAction = new Action(factory, catchAction);
}
}

View File

@ -31,7 +31,7 @@ package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.ActionAST;
import java.util.HashMap;
import java.util.Map;
@ -45,7 +45,7 @@ public class LexerFile extends OutputFile {
namedActions = new HashMap<String, Action>();
Grammar g = factory.getGrammar();
for (String name : g.namedActions.keySet()) {
GrammarAST ast = g.namedActions.get(name);
ActionAST ast = g.namedActions.get(name);
namedActions.put(name, new Action(factory, ast));
}
}

View File

@ -31,9 +31,10 @@ package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.ActionAST;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
/** */
public class ParserFile extends OutputFile {
@ -45,7 +46,7 @@ public class ParserFile extends OutputFile {
Grammar g = factory.getGrammar();
namedActions = new HashMap<String, Action>();
for (String name : g.namedActions.keySet()) {
GrammarAST ast = g.namedActions.get(name);
ActionAST ast = g.namedActions.get(name);
namedActions.put(name, new Action(factory, ast));
}
}

View File

@ -71,7 +71,6 @@ public class RuleFunction extends OutputModelObject {
public String ctxType;
public Collection<String> ruleLabels;
public Collection<String> tokenLabels;
public List<String> exceptions;
public ATNState startState;
public int index;
public Collection<Attribute> args = null;
@ -85,6 +84,7 @@ public class RuleFunction extends OutputModelObject {
@ModelElement public Map<String,AltLabelStructDecl> altLabelCtxs;
@ModelElement public Map<String,Action> namedActions;
@ModelElement public Action finallyAction;
@ModelElement public List<ExceptionClause> exceptions;
@ModelElement public List<SrcOp> postamble;
public RuleFunction(OutputModelFactory factory, Rule r) {
@ -117,10 +117,13 @@ public class RuleFunction extends OutputModelObject {
ruleLabels = r.getElementLabelNames();
tokenLabels = r.getTokenRefs();
for (GrammarAST e : r.exceptions) {
// TODO:Made new exception object here!!!
ActionAST a = (ActionAST)e.getChild(1);
exceptions = Utils.nodesToStrings(r.exceptions);
if ( r.exceptions!=null ) {
exceptions = new ArrayList<ExceptionClause>();
for (GrammarAST e : r.exceptions) {
ActionAST catchArg = (ActionAST)e.getChild(0);
ActionAST catchAction = (ActionAST)e.getChild(1);
exceptions.add(new ExceptionClause(factory, catchArg, catchAction));
}
}
if ( r.finallyAction!=null ) finallyAction = new Action(factory, r.finallyAction);
@ -156,7 +159,7 @@ public class RuleFunction extends OutputModelObject {
public void fillNamedActions(OutputModelFactory factory, Rule r) {
namedActions = new HashMap<String, Action>();
for (String name : r.namedActions.keySet()) {
GrammarAST ast = r.namedActions.get(name);
ActionAST ast = r.namedActions.get(name);
namedActions.put(name, new Action(factory, ast));
}
}

View File

@ -45,7 +45,7 @@ public class SemPred extends Action {
@ModelElement public List<ActionChunk> failChunks;
public SemPred(OutputModelFactory factory, GrammarAST ast) {
public SemPred(OutputModelFactory factory, ActionAST ast) {
super(factory,ast);
GrammarAST failNode = ((PredAST)ast).getOptionAST("fail");
CodeGenerator gen = factory.getGenerator();