got basic tree parser ^(A B) stuff in.

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9068]
This commit is contained in:
parrt 2011-09-18 16:49:52 -08:00
parent a8195e5d7c
commit 6c45753bea
26 changed files with 654 additions and 75 deletions

View File

@ -35,6 +35,10 @@ import java.util.ArrayList;
<parser>
>>
TreeParserFile(file, parser, namedActions) ::= <<
<ParserFile(...)>
>>
ListenerFile(listener, header) ::= <<
<header>
import org.antlr.v4.runtime.tree.ParseTreeListener;
@ -106,6 +110,10 @@ public class <parser.name> extends Parser {
}
>>
TreeParserModel(parser, scopes, funcs, atn, sempredFuncs) ::= <<
<Parser(...)>
>>
dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= <<
<if(actionFuncs)>
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
@ -344,6 +352,19 @@ cases(ttypes) ::= <<
<ttypes:{t | case <t>:}; separator="\n">
>>
MatchTree(t, elems) ::= <<
// match tree
<elems; separator="\n">
>>
MatchDOWN(m) ::= <<
move(<m.stateNumber>); match(Token.DOWN);
>>
MatchUP(m) ::= <<
move(<m.stateNumber>); match(Token.UP);
>>
InvokeRule(r, argExprsChunks) ::= <<
move(<r.stateNumber>); <if(r.labels)><r.labels:{l | <labelref(l)> = }><endif><r.name>(<argExprsChunks:{e| <e>}>);
>>

View File

@ -263,6 +263,7 @@ public class Tool {
// BUILD ATN FROM AST
ATNFactory factory;
if ( g.isLexer() ) factory = new LexerATNFactory((LexerGrammar)g);
else if ( g.isTreeGrammar() ) factory = new TreeParserATNFactory(g);
else factory = new ParserATNFactory(g);
g.atn = factory.createATN();

View File

@ -69,7 +69,7 @@ public interface ATNFactory {
Handle set(GrammarAST associatedAST, List<GrammarAST> alts, boolean invert);
Handle tree(List<Handle> els);
Handle tree(GrammarAST node, List<Handle> els);
Handle range(GrammarAST a, GrammarAST b);

View File

@ -49,7 +49,7 @@ import java.util.*;
public class ParserATNFactory implements ATNFactory {
public Grammar g;
public Rule currentRule;
ATN atn;
public ATN atn;
public ParserATNFactory(Grammar g) { this.g = g; atn = new ATN(); }
@ -133,8 +133,8 @@ public class ParserATNFactory implements ATNFactory {
return new Handle(left, right);
}
public Handle tree(List<Handle> els) {
return null;
public Handle tree(GrammarAST node, List<Handle> els) {
throw new UnsupportedOperationException("^(...) not allowed in non-tree grammar");
}
/** Not valid for non-lexers */
@ -142,19 +142,6 @@ public class ParserATNFactory implements ATNFactory {
throw new UnsupportedOperationException();
}
/** ~atom only */
/*
public Handle not(GrammarAST node) {
ATNState left = newState(node);
ATNState right = newState(node);
int ttype = getTokenType((GrammarAST) node.getChild(0));
left.transition = new NotAtomTransition(ttype, right);
right.incidentTransition = left.transition;
node.atnState = left;
return new Handle(left, right);
}
*/
protected int getTokenType(GrammarAST atom) {
int ttype;
if ( g.isLexer() ) {
@ -319,6 +306,10 @@ public class ParserATNFactory implements ATNFactory {
// }
public Handle alt(List<Handle> els) {
return elemList(els);
}
public Handle elemList(List<Handle> els) {
Handle prev = null;
for (Handle el : els) { // hook up elements
if ( prev!=null ) epsilon(prev.right, el.left);
@ -327,7 +318,7 @@ public class ParserATNFactory implements ATNFactory {
Handle first = els.get(0);
Handle last = els.get(els.size()-1);
if ( first==null || last==null ) {
g.tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, "alt Handle has first|last == null");
g.tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, "element list has first|last == null");
}
return new Handle(first.left, last.right);
}

View File

@ -0,0 +1,76 @@
/*
[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.automata;
import org.antlr.v4.tool.*;
import java.util.List;
/** Build ATNs for tree grammars */
public class TreeParserATNFactory extends ParserATNFactory {
public TreeParserATNFactory(Grammar g) {
super(g);
}
/** x y z from ^(x y z) becomes o-x->o-DOWN->o-y->o-z->o-UP->o */
public Handle tree(GrammarAST node, List<Handle> els) {
Handle h = elemList(els);
return h;
// ATNState first = h.left;
// ATNState last = h.right;
// node.atnState = first;
//
// // find root transition first side node
// ATNState p = first;
// while ( p.transition(0) instanceof EpsilonTransition ||
// p.transition(0) instanceof PredicateTransition ||
// p.transition(0) instanceof RangeTransition ||
// p.transition(0) instanceof ActionTransition )
// {
// p = p.transition(0).target;
// }
// ATNState rootLeftNode = p;
// ATNState rootRightNode = rootLeftNode.transition(0).target;
// ATNState downLeftNode = newState(node);
// downLeftNode.transition = new AtomTransition(Token.DOWN, rootRightNode);
// rootRightNode.incidentTransition = downLeftNode.transition;
// rootLeftNode.transition.target = downLeftNode;
// downLeftNode.incidentTransition = rootLeftNode.transition;
//
// ATNState upRightNode = newState(node);
// last.transition = new AtomTransition(Token.UP, upRightNode);
// upRightNode.incidentTransition = last.transition;
// last = upRightNode;
//
// return new Handle(first, last);
}
}

View File

@ -44,6 +44,9 @@ public class CodeGenPipeline {
if ( g.isLexer() ) {
gen.writeRecognizer(gen.generateLexer());
}
else if ( g.isTreeGrammar() ) {
gen.writeRecognizer(gen.generateTreeParser());
}
else {
gen.writeRecognizer(gen.generateParser());
gen.writeListener(gen.generateListener());

View File

@ -32,16 +32,12 @@ package org.antlr.v4.codegen;
import org.antlr.v4.Tool;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.*;
import org.stringtemplate.v4.*;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
/** General controller for code gen. Can instantiate sub generator(s).
*/
@ -171,6 +167,29 @@ public class CodeGenerator {
return st;
}
public ST generateTreeParser() {
OutputModelFactory factory = new TreeParserFactory(this);
// CREATE OUTPUT MODEL FROM GRAMMAR OBJ AND AST WITHIN RULES
OutputModelController controller = new OutputModelController(factory);
if ( g.hasASTOption() ) {
controller.addExtension( new ParserASTExtension(factory) );
}
factory.setController(controller);
OutputModelObject outputModel = controller.buildTreeParserOutputModel();
OutputModelWalker walker = new OutputModelWalker(tool, templates);
ST st = walker.walk(outputModel);
if ( tool.launch_ST_inspector ) {
st.inspect();
//if ( templates.isDefined("headerFile") ) headerFileST.inspect();
}
return st;
}
public ST generateListener() {
OutputModelFactory factory = new ParserFactory(this);

View File

@ -52,6 +52,10 @@ public class CodeGeneratorExtension {
public Lexer lexer(Lexer l) { return l; }
public TreeParserFile treeParserFile(TreeParserFile f) { return f; }
public TreeParserModel treeParser(TreeParserModel p) { return p; }
public RuleFunction rule(RuleFunction rf) { return rf; }
public List<SrcOp> rulePostamble(List<SrcOp> ops) { return ops; }
@ -72,6 +76,8 @@ public class CodeGeneratorExtension {
public List<SrcOp> wildcard(List<SrcOp> ops) { return ops; }
public MatchTree tree(MatchTree matchTree) { return matchTree; }
// ACTIONS
public List<SrcOp> action(List<SrcOp> ops) { return ops; }

View File

@ -75,6 +75,21 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
public int getTreeLevel() { return controller.treeLevel; }
@Override
public TreeParserFile treeParserFile(String fileName) {
return null;
}
@Override
public TreeParserModel treeParser(TreeParserFile file) {
return null;
}
@Override
public MatchTree tree(GrammarAST treeBeginAST, List<? extends SrcOp> omos) {
throw new UnsupportedOperationException("^(...) in non-tree grammar");
}
// MISC
public static List<SrcOp> list(Object... values) {

View File

@ -102,6 +102,21 @@ public class OutputModelController {
return file;
}
public OutputModelObject buildTreeParserOutputModel() {
Grammar g = delegate.getGrammar();
CodeGenerator gen = delegate.getGenerator();
TreeParserFile file = treeParserFile(gen.getRecognizerFileName());
setRoot(file);
Parser parser = treeParser(file);
file.parser = parser;
for (Rule r : g.rules.values()) {
buildRuleFunction(parser, r);
}
return file;
}
public OutputModelObject buildListenerOutputModel() {
CodeGenerator gen = delegate.getGenerator();
return new ListenerFile(delegate, gen.getListenerFileName());
@ -132,6 +147,18 @@ public class OutputModelController {
return new Lexer(delegate, file);
}
public TreeParserFile treeParserFile(String fileName) {
TreeParserFile f = delegate.treeParserFile(fileName);
for (CodeGeneratorExtension ext : extensions) f = ext.treeParserFile(f);
return f;
}
public TreeParserModel treeParser(TreeParserFile file) {
TreeParserModel p = delegate.treeParser(file);
for (CodeGeneratorExtension ext : extensions) p = ext.treeParser(p);
return p;
}
/** Create RuleFunction per rule and update sempreds,actions of parser
* output object with stuff found in r.
*/
@ -342,6 +369,12 @@ public class OutputModelController {
return ops;
}
public MatchTree tree(GrammarAST treeBeginAST, List<? extends SrcOp> omos) {
MatchTree matchTree = delegate.tree(treeBeginAST, omos);
for (CodeGeneratorExtension ext : extensions) matchTree = ext.tree(matchTree);
return matchTree;
}
public Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label) {
Choice c = delegate.getChoiceBlock(blkAST, alts, label);
for (CodeGeneratorExtension ext : extensions) c = ext.getChoiceBlock(c);

View File

@ -52,6 +52,10 @@ public interface OutputModelFactory {
Lexer lexer(LexerFile file);
TreeParserFile treeParserFile(String fileName);
TreeParserModel treeParser(TreeParserFile file);
RuleFunction rule(Rule r);
List<SrcOp> rulePostamble(RuleFunction function, Rule r);
@ -84,6 +88,8 @@ public interface OutputModelFactory {
List<SrcOp> wildcard(GrammarAST ast, GrammarAST labelAST, GrammarAST astOp);
MatchTree tree(GrammarAST treeBeginAST, List<? extends SrcOp> omos);
Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label);
Choice getEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts);

View File

@ -108,7 +108,7 @@ element returns [List<? extends SrcOp> omos]
| subrule {$omos = $subrule.omos;}
| ACTION {$omos = controller.action($ACTION);}
| SEMPRED {$omos = controller.sempred($SEMPRED);}
| treeSpec
| treeSpec {$omos = DefaultOutputModelFactory.list($treeSpec.treeMatch);}
;
labeledElement returns [List<? extends SrcOp> omos]
@ -118,8 +118,14 @@ labeledElement returns [List<? extends SrcOp> omos]
| ^(PLUS_ASSIGN ID block[$ID,null,null]) {$omos = $block.omos;}
;
treeSpec returns [SrcOp omo]
: ^(TREE_BEGIN (e=element )+)
treeSpec returns [MatchTree treeMatch]
@init {
List<SrcOp> elems = new ArrayList<SrcOp>();
}
: ^(TREE_BEGIN
(e=element {if ($e.omos!=null) elems.addAll($e.omos);})+
)
{$treeMatch = controller.tree($TREE_BEGIN, elems);}
;
subrule returns [List<? extends SrcOp> omos]
@ -187,6 +193,8 @@ terminal[GrammarAST label, GrammarAST astOp] returns [List<SrcOp> omos]
| ^(TOKEN_REF ARG_ACTION .) {$omos = controller.tokenRef($TOKEN_REF, $label, $ARG_ACTION, $astOp);}
| ^(TOKEN_REF .) {$omos = controller.tokenRef($TOKEN_REF, $label, null, $astOp);}
| TOKEN_REF {$omos = controller.tokenRef($TOKEN_REF, $label, null, $astOp);}
| DOWN_TOKEN {$omos = controller.tokenRef($DOWN_TOKEN, null, null, null);}
| UP_TOKEN {$omos = controller.tokenRef($UP_TOKEN, null, null, null);}
;
elementOptions

View File

@ -0,0 +1,57 @@
/*
[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;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.tool.GrammarAST;
import java.util.List;
public class TreeParserFactory extends ParserFactory {
public TreeParserFactory(CodeGenerator gen) {
super(gen);
}
@Override
public TreeParserFile treeParserFile(String fileName) {
return new TreeParserFile(this, fileName);
}
@Override
public TreeParserModel treeParser(TreeParserFile file) {
return new TreeParserModel(this, file);
}
@Override
public MatchTree tree(GrammarAST treeBeginAST, List<? extends SrcOp> omos) {
return new MatchTree(this, treeBeginAST, omos);
}
}

View File

@ -0,0 +1,38 @@
/*
[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;
import org.antlr.v4.codegen.model.ParserFile;
public class TreeParserFile extends ParserFile {
public TreeParserFile(OutputModelFactory factory, String fileName) {
super(factory, fileName);
}
}

View File

@ -0,0 +1,39 @@
/*
[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.tool.GrammarAST;
public class MatchDOWN extends RuleElement {
public MatchDOWN(OutputModelFactory factory, GrammarAST ast) {
super(factory, ast);
}
}

View File

@ -0,0 +1,45 @@
/*
[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.tool.GrammarAST;
import java.util.List;
public class MatchTree extends RuleElement {
@ModelElement public List<? extends SrcOp> elems;
public MatchTree(OutputModelFactory factory, GrammarAST ast, List<? extends SrcOp> elems) {
super(factory, ast);
this.elems = elems;
}
}

View File

@ -0,0 +1,39 @@
/*
[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.tool.GrammarAST;
public class MatchUP extends RuleElement {
public MatchUP(OutputModelFactory factory, GrammarAST ast) {
super(factory, ast);
}
}

View File

@ -93,6 +93,9 @@ tokens {
ST_RESULT; // distinguish between ST and tree rewrites
RESULT;
ALT_REWRITE; // indicate ALT is rewritten
DOWN_TOKEN; // AST node representing DOWN node in tree parser code gen
UP_TOKEN;
}
// Include the copyright in this source and also the generated source
@ -650,12 +653,17 @@ treeSpec
// Only a subset of elements are allowed to be a root node. However
// we allow any element to appear here and reject silly ones later
// when we walk the AST.
element
root=element
// After the tree root we get the usual suspects,
// all members of the element set
element+
(kids+=element)+
RPAREN
-> ^(TREE_BEGIN element+)
-> ^(TREE_BEGIN
$root
DOWN_TOKEN<DownAST>[$TREE_BEGIN]
$kids+
UP_TOKEN<UpAST>[$TREE_BEGIN]
)
;
// A block of gramamr structure optionally followed by standard EBNF

View File

@ -98,6 +98,8 @@ element returns [ATNFactory.Handle p]
| ^(ROOT a=astOperand) {$p = $a.p;}
| ^(BANG a=astOperand) {$p = $a.p;}
| ^(NOT b=blockSet[true]) {$p = $b.p;}
| DOWN_TOKEN {$p = factory.tokenRef((DownAST)$start);}
| UP_TOKEN {$p = factory.tokenRef((UpAST)$start);}
;
astOperand returns [ATNFactory.Handle p]
@ -112,7 +114,8 @@ labeledElement returns [ATNFactory.Handle p]
treeSpec returns [ATNFactory.Handle p]
@init {List<ATNFactory.Handle> els = new ArrayList<ATNFactory.Handle>();}
: ^(TREE_BEGIN (e=element {els.add($e.p);})+) {$p = factory.tree(els);}
: ^(TREE_BEGIN (e=element {els.add($e.p);})+ )
{$p = factory.tree($TREE_BEGIN, els);}
;
subrule returns [ATNFactory.Handle p]

View File

@ -170,6 +170,14 @@ public void rewriteStringRef(TerminalAST ast, GrammarAST options) { }
public void rewriteRuleRef(GrammarAST ast) { }
public void rewriteLabelRef(GrammarAST ast) { }
public void rewriteAction(ActionAST ast) { }
public void traceIn(String ruleName, int ruleIndex) {
System.err.println("enter "+ruleName+": "+input.LT(1));
}
public void traceOut(String ruleName, int ruleIndex) {
System.err.println("exit "+ruleName+": "+input.LT(1));
}
}
grammarSpec
@ -363,7 +371,7 @@ labeledElement
;
treeSpec
: ^(TREE_BEGIN element+)
: ^(TREE_BEGIN element DOWN_TOKEN element+ UP_TOKEN )
;
subrule

View File

@ -0,0 +1,49 @@
/*
[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.tool;
import org.antlr.runtime.Token;
public class DownAST extends TerminalAST {
public DownAST(int type, Token t) {
super(type, t);
}
@Override
public String getText() {
return "DOWN";
}
@Override
public String toString() {
return getText();
}
}

View File

@ -176,11 +176,6 @@ public class GrammarAST extends CommonTree {
return (GrammarAST)adaptor.dupTree(t);
}
@Override
public String toString() {
return super.toString();
}
public String toTokenString() {
CharStream input = this.token.getInputStream();
GrammarASTAdaptor adaptor = new GrammarASTAdaptor(input);

View File

@ -0,0 +1,48 @@
/*
[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.tool;
import org.antlr.runtime.Token;
public class UpAST extends TerminalAST {
public UpAST(int type, Token t) {
super(type, t);
}
@Override
public String getText() {
return "UP";
}
@Override
public String toString() {
return getText();
}
}

View File

@ -36,6 +36,7 @@ import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.semantics.SemanticPipeline;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.Rule;
import org.junit.*;
import org.stringtemplate.v4.ST;
@ -737,6 +738,23 @@ public abstract class BaseTest {
return filtered;
}
void checkRuleATN(Grammar g, String ruleName, String expecting) {
ParserATNFactory f = new ParserATNFactory(g);
if ( g.isTreeGrammar() ) f = new TreeParserATNFactory(g);
ATN atn = f.createATN();
DOTGenerator dot = new DOTGenerator(g);
System.out.println(dot.getDOT(atn.ruleToStartState[g.getRule(ruleName).index]));
Rule r = g.getRule(ruleName);
ATNState startState = atn.ruleToStartState[r.index];
ATNPrinter serializer = new ATNPrinter(g, startState);
String result = serializer.asString();
//System.out.print(result);
assertEquals(expecting, result);
}
public static class StreamVacuum implements Runnable {
StringBuffer buf = new StringBuffer();
BufferedReader in;

View File

@ -16,7 +16,7 @@ public class TestATNConstruction extends BaseTest {
"s2-A->s3\n" +
"s3->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s4\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAB() throws Exception {
@ -30,7 +30,7 @@ public class TestATNConstruction extends BaseTest {
"s4-B->s5\n" +
"s5->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s6\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAorB() throws Exception {
@ -49,7 +49,7 @@ public class TestATNConstruction extends BaseTest {
"s6-action_0:-1->s7\n" + // actionIndex -1 since not forced action
"RuleStop_a_1-EOF->s10\n" +
"s7->BlockEnd_9\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testSetAorB() throws Exception {
@ -66,7 +66,7 @@ public class TestATNConstruction extends BaseTest {
"s5->BlockEnd_7\n" +
"BlockEnd_7->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s8\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testLexerIsntSetMultiCharString() throws Exception {
@ -138,7 +138,7 @@ public class TestATNConstruction extends BaseTest {
"s5->BlockEnd_7\n" +
"BlockEnd_7->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s8\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testABorCD() throws Exception {
@ -159,7 +159,7 @@ public class TestATNConstruction extends BaseTest {
"s9->BlockEnd_11\n" +
"BlockEnd_11->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s12\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testbA() throws Exception {
@ -174,13 +174,13 @@ public class TestATNConstruction extends BaseTest {
"s6-A->s7\n" +
"s7->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s10\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
expecting =
"RuleStart_b_2->s8\n" +
"s8-B->s9\n" +
"s9->RuleStop_b_3\n" +
"RuleStop_b_3->s5\n";
checkRule(g, "b", expecting);
checkRuleATN(g, "b", expecting);
}
@Test public void testFollow() throws Exception {
@ -195,7 +195,7 @@ public class TestATNConstruction extends BaseTest {
"s11->RuleStop_b_3\n" +
"RuleStop_b_3->s7\n" +
"RuleStop_b_3->s13\n";
checkRule(g, "b", expecting);
checkRuleATN(g, "b", expecting);
}
@Test public void testAorEpsilon() throws Exception {
@ -212,7 +212,7 @@ public class TestATNConstruction extends BaseTest {
"s5->BlockEnd_7\n" +
"BlockEnd_7->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s8\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAOptional() throws Exception {
@ -227,7 +227,7 @@ public class TestATNConstruction extends BaseTest {
"BlockEnd_5->RuleStop_a_1\n" +
"s3->BlockEnd_5\n" +
"RuleStop_a_1-EOF->s6\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAorBoptional() throws Exception {
@ -247,7 +247,7 @@ public class TestATNConstruction extends BaseTest {
"RuleStop_a_1-EOF->s10\n" +
"s4-action_0:-1->s5\n" +
"s5->BlockEnd_9\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testSetAorBoptional() throws Exception {
@ -262,7 +262,7 @@ public class TestATNConstruction extends BaseTest {
"BlockEnd_5->RuleStop_a_1\n" +
"s3->BlockEnd_5\n" +
"RuleStop_a_1-EOF->s6\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAorBthenC() throws Exception {
@ -276,7 +276,7 @@ public class TestATNConstruction extends BaseTest {
"s4-C->s5\n" +
"s5->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s6\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAplus() throws Exception {
@ -293,7 +293,7 @@ public class TestATNConstruction extends BaseTest {
"PlusLoopBack_6->s7\n" +
"s7->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s8\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAorBplus() throws Exception {
@ -315,7 +315,7 @@ public class TestATNConstruction extends BaseTest {
"s7->BlockEnd_9\n" +
"s11->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s12\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAorBorEmptyPlus() throws Exception {
@ -338,7 +338,7 @@ public class TestATNConstruction extends BaseTest {
"PlusLoopBack_10->s11\n" +
"s11->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s12\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAStar() throws Exception {
@ -356,7 +356,7 @@ public class TestATNConstruction extends BaseTest {
"s3->BlockEnd_5\n" +
"BlockEnd_5->StarLoopBack_8\n" +
"StarLoopBack_8->StarLoopEntry_6\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testNestedAstar() throws Exception {
@ -382,7 +382,7 @@ public class TestATNConstruction extends BaseTest {
"StarLoopBack_15->StarLoopEntry_13\n" +
"BlockEnd_7->StarLoopBack_10\n" +
"StarLoopBack_10->StarLoopEntry_8\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testAorBstar() throws Exception {
@ -405,7 +405,7 @@ public class TestATNConstruction extends BaseTest {
"s6-action_0:-1->s7\n" +
"StarLoopBack_12->StarLoopEntry_10\n" +
"s7->BlockEnd_9\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
@Test public void testPredicatedAorB() throws Exception {
@ -426,7 +426,7 @@ public class TestATNConstruction extends BaseTest {
"s9->BlockEnd_11\n" +
"BlockEnd_11->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s12\n";
checkRule(g, "a", expecting);
checkRuleATN(g, "a", expecting);
}
/*
@ -978,19 +978,4 @@ public class TestATNConstruction extends BaseTest {
assertEquals(expecting, result);
}
void checkRule(Grammar g, String ruleName, String expecting) {
ParserATNFactory f = new ParserATNFactory(g);
ATN atn = f.createATN();
DOTGenerator dot = new DOTGenerator(g);
System.out.println(dot.getDOT(atn.ruleToStartState[g.getRule(ruleName).index]));
Rule r = g.getRule(ruleName);
ATNState startState = atn.ruleToStartState[r.index];
ATNPrinter serializer = new ATNPrinter(g, startState);
String result = serializer.asString();
//System.out.print(result);
assertEquals(expecting, result);
}
}

View File

@ -0,0 +1,68 @@
/*
[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.test;
import org.antlr.v4.tool.Grammar;
import org.junit.Test;
public class TestATNTreeGrammarConstruction extends BaseTest {
@Test public void testAB() throws Exception {
Grammar g = new Grammar(
"tree grammar P;\n"+
"a : A B ;");
String expecting =
"RuleStart_a_0->s2\n" +
"s2-A->s3\n" +
"s3->s4\n" +
"s4-B->s5\n" +
"s5->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s6\n";
checkRuleATN(g, "a", expecting);
}
@Test public void testTreeAB() throws Exception {
Grammar g = new Grammar(
"tree grammar P;\n"+
"a : ^(A B) ;");
String expecting =
"RuleStart_a_0->s2\n" +
"s2-A->s3\n" +
"s3->s4\n" +
"s4-DOWN->s5\n" +
"s5->s6\n" +
"s6-B->s7\n" +
"s7->s8\n" +
"s8-UP->s9\n" +
"s9->RuleStop_a_1\n" +
"RuleStop_a_1-EOF->s10\n";
checkRuleATN(g, "a", expecting);
}
}