A B+ -> ^(A B)* works! fixed ant build

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8838]
This commit is contained in:
parrt 2011-07-06 13:42:35 -08:00
parent df80cb7622
commit f8abf5d40b
29 changed files with 601 additions and 169 deletions

View File

@ -28,7 +28,7 @@
<target name="antlr" depends="init">
<echo>parse</echo>
<echo>parse grammars</echo>
<java classname="org.antlr.Tool" fork="true" failonerror="false" maxmemory="300m"
dir="${basedir}/tool/src/org/antlr/v4/parse">
<arg value="-make"/>
@ -51,6 +51,7 @@
<arg value="../parse"/>
<arg value="BasicSemanticTriggers.g"/>
<arg value="CollectSymbols.g"/>
<arg value="Refs.g"/>
<classpath>
<pathelement location="${antlr3.jar}"/>
<pathelement path="${java.class.path}"/>
@ -89,7 +90,9 @@
<mkdir dir="${build.dir}/classes"/>
<mkdir dir="${build.dir}/src"/>
<copy todir="${build.dir}/src" >
<fileset dir="src/"/>
<fileset dir="${basedir}/tool/src/"/>
<fileset dir="${basedir}/runtime/Java/src/"/>
<fileset dir="${basedir}/gunit/src/"/>
</copy>
<replace dir="${build.dir}/src" token="@version@" value="${version}"/>
<javac
@ -120,12 +123,24 @@
<mkdir dir="${install.root.dir}/src"/>
<copy todir="${install.root.dir}/src">
<fileset dir="src/">
<include name="**/*.java"/>
<include name="**/*.g"/>
<include name="**/*.st"/>
<include name="**/*.stg"/>
</fileset>
<fileset dir="${basedir}/tool/src/">
<include name="**/*.java"/>
<include name="**/*.g"/>
<include name="**/*.st"/>
<include name="**/*.stg"/>
</fileset>
<fileset dir="${basedir}/runtime/Java/src/">
<include name="**/*.java"/>
<include name="**/*.g"/>
<include name="**/*.st"/>
<include name="**/*.stg"/>
</fileset>
<fileset dir="${basedir}/gunit/src/">
<include name="**/*.java"/>
<include name="**/*.g"/>
<include name="**/*.st"/>
<include name="**/*.stg"/>
</fileset>
</copy>
<copy todir="${install.root.dir}">

View File

@ -53,7 +53,7 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
*/
public List<Object> createElementList() {
return new ArrayList(3);
return new ElementList<Object>(this);
}
// END v4 stuff

View File

@ -0,0 +1,79 @@
/*
[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.runtime.tree;
import java.util.*;
/** This list tracks elements to left of -> for use on right of -> */
public class ElementList<E> extends ArrayList<E> {
protected TreeAdaptor adaptor;
public class ElementListIterator implements Iterator<E> {
int cursor = 0;
public boolean hasNext() {
int n = size();
return (n==1 && cursor<1) || (n>1 && cursor<n);
}
public E next() {
int n = size();
if ( n == 0 ) throw new RewriteEmptyStreamException("n/a");
if ( cursor >= n) { // out of elements?
if ( n == 1 ) { // if size is 1, it's ok; return and we'll dup
return (E)adaptor.dupTree( get(0) );
}
// out of elements and size was not 1, so we can't dup
throw new RewriteCardinalityException("size=="+n+" and out of elements");
}
// we have elements
if ( n == 1 ) {
cursor++; // move cursor even for single element list
return (E)adaptor.dupTree( get(0) );
}
// must have more than one in list, pull from elements
E e = get(cursor);
cursor++;
return e;
}
public void remove() { throw new UnsupportedOperationException(); }
}
public ElementList(TreeAdaptor adaptor) {
this.adaptor = adaptor;
}
@Override
public Iterator<E> iterator() {
return new ElementListIterator();
}
}

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.runtime.tree;
/** Base class for all exceptions thrown during AST rewrite construction.
* This signifies a case where the cardinality of two or more elements
* in a subrule are different: (ID INT)* where |ID|!=|INT|
*/
public class RewriteCardinalityException extends RuntimeException {
public String elementDescription;
public RewriteCardinalityException(String elementDescription) {
this.elementDescription = elementDescription;
}
public String getMessage() {
if ( elementDescription!=null ) {
return elementDescription;
}
return null;
}
}

View File

@ -0,0 +1,37 @@
/*
[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.runtime.tree;
/** Ref to ID or expr but no tokens in ID stream or subtrees in expr stream */
public class RewriteEmptyStreamException extends RewriteCardinalityException {
public RewriteEmptyStreamException(String elementDescription) {
super(elementDescription);
}
}

View File

@ -1,15 +1,15 @@
grammar T;
options {output=AST;}
tokens {I;}
/*
a : A b C -> ^(A ^(b C))
| B
tokens {I;D;}
a : A B+ -> ^(A B)*
;
b : B | C ;
*/
c : A B C -> (A B C*)* ;
/*
c : A B C -> A ( D A B C*)* (B A*)? ;
*/
A : 'a';
B : 'b';

View File

@ -2,6 +2,7 @@ import org.antlr.v4.Tool;
import org.antlr.v4.automata.ParserATNFactory;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.tree.Tree;
import org.antlr.v4.semantics.SemanticPipeline;
import org.antlr.v4.tool.*;
@ -12,8 +13,8 @@ public class TestT {
TLexer t = new TLexer(new ANTLRFileStream(args[0]));
CommonTokenStream tokens = new CommonTokenStream(t);
TParser p = new TParser(tokens);
// ParserRuleContext ret = p.a();
// System.out.println(((Tree)ret.tree).toStringTree());
ParserRuleContext ret = p.a();
System.out.println(((Tree)ret.tree).toStringTree());
}
public static void dump() throws Exception {

View File

@ -381,8 +381,10 @@ ElementListName(elemName) ::= "_track_<elemName>"
TrackRuleElement(e) ::= "<e.name>.add(<labelref(e.label)>.tree);"
TrackTokenElement(e) ::= "<e.name>.add(_adaptor.create(<labelref(e.label)>));"
// assume roots are always locals in tree rewrites
TreeRewrite(tr, locals, preamble, ops) ::= <<
// rewrite: ...
// rewrite: code level= <tr.codeBlockLevel>, tree level = <tr.treeLevel>
<locals; separator="\n">
<preamble; separator="\n">
<ops; separator="\n">
@ -394,41 +396,52 @@ RewriteIteratorInit(i) ::= "<i.decl.name> = <i.decl.listName>.iterator();"
RewriteIteratorName(elemName,level) ::= "it<level>_<elemName>"
RewriteTreeOptional(o, locals, preamble, ops) ::= <<
// ?
<locals; separator="\n">
<preamble; separator="\n">
//if ( true ) {
<ops; separator="\n">
//}
>>
RewriteTreeClosure(c, locals, preamble, ops) ::= <<
// *
<locals; separator="\n">
<preamble; separator="\n">
//while ( <c.iteratorDecls:{d | <d.name>.hasNext()}; separator=" || "> ) {
<ops; separator="\n">
//}
>>
RewriteTreeStructure(t, locals, preamble, ops) ::= <<
// ? code level= <o.codeBlockLevel>, tree level = <o.treeLevel>
{
<locals; separator="\n">
<preamble; separator="\n">
<ops; separator="\n">
_adaptor.addChild(<labelref(t.enclosingBlock.rootDecl)>, <labelref(t.rootDecl)>);
<locals; separator="\n">
<preamble; separator="\n">
if ( <o.conditionalDecls:{d | <d.name>.hasNext()}; separator=" || "> ) {
<ops; separator="\n">
}
}
>>
RewriteTokenRef(t) ::= "_adaptor.addChild(<t.rootName>, <t.decl.name>.next());"
RewriteTokenRefIsRoot(t) ::= <<
<t.rootName> = _adaptor.becomeRoot(<t.decl.name>.next(), <t.rootName>);
RewriteTreeClosure(c, locals, preamble, ops) ::= <<
// * code level= <c.codeBlockLevel>, tree level = <c.treeLevel>
{
<locals; separator="\n">
<preamble; separator="\n">
while ( <c.iteratorDecls:{d | <d.name>.hasNext()}; separator=" || "> ) {
<ops; separator="\n">
}
}
>>
RewriteRuleRef(r) ::= "_adaptor.addChild(<r.enclosingBlock.rootDecl.name>, <r.decl.name>.next());"
RewriteRuleRefIsRoot(r) ::= <%
<labelref(r.enclosingBlock.rootDecl)> =
_adaptor.becomeRoot(<r.decl.name>.next(), <labelref(r.enclosingBlock.rootDecl)>);
RewriteTreeStructure(t, locals, ops) ::= <<
// TREE code level= <t.codeBlockLevel>, tree level = <t.treeLevel>
{
<locals; separator="\n">
<ops; separator="\n">
_adaptor.addChild(_root<t.enclosingTreeLevel>, _root<t.treeLevel>);
}
>>
RewriteTokenRef(t) ::= "_adaptor.addChild(<t.rootName>, <t.iterName>.next());"
RewriteTokenRefIsRoot(t) ::= <<
<t.rootName> = _adaptor.becomeRoot(<t.iterName>.next(), <t.rootName>);
>>
//adaptor.addChild(root_0, (Object)adaptor.create(D, "D"));
RewriteImagTokenRef(t) ::=
"_adaptor.addChild(<t.rootName>, _adaptor.create(<t.ast.text>, \"<t.ast.text>\"));"
RewriteImagTokenRefIsRoot(t) ::= <%
<t.rootName> =
_adaptor.becomeRoot(_adaptor.create(<t.ast.text>, "<t.ast.text>"),
<t.rootName>);
%>
RewriteRuleRef(r) ::= "_adaptor.addChild(<r.rootName>, <r.iterName>.next());"
RewriteRuleRefIsRoot(r) ::=
"<r.rootName> = _adaptor.becomeRoot(<r.iterName>.next(), <r.rootName>);"
/*
BitSetDecl(b) ::= <<

View File

@ -111,6 +111,7 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
}
public Decl getCurrentDeclForName(String name) {
if ( getCurrentBlock().locals==null ) return null;
for (Decl d : getCurrentBlock().locals.elements()) {
if ( d.name.equals(name) ) return d;
}

View File

@ -296,7 +296,6 @@ public class OutputModelController implements OutputModelFactory {
}
public RewriteTreeClosure rewrite_closure(GrammarAST ast) {
List<GrammarAST> refs = getElementReferencesShallow(ast);
RewriteTreeClosure c = delegate.rewrite_closure(ast);
for (CodeGeneratorExtension ext : extensions) c = ext.rewrite_closure(c);
return c;
@ -348,69 +347,12 @@ public class OutputModelController implements OutputModelFactory {
// SUPPORT
/** Given (('?'|'*') (REWRITE_BLOCK (ALT ...))) return list of element refs at
* top level of REWRITE_BLOCK.
*/
public List<GrammarAST> getElementReferencesShallow(GrammarAST ebnfRoot) {
if ( ebnfRoot.getType()!=ANTLRParser.CLOSURE &&
ebnfRoot.getType()!=ANTLRParser.OPTIONAL )
{
return null;
}
GrammarAST blkAST = (GrammarAST)ebnfRoot.getChild(0);
if ( blkAST.getType()!=ANTLRParser.REWRITE_BLOCK ) return null;
GrammarAST altAST = (GrammarAST)blkAST.getChild(0);
if ( altAST.getType()!=ANTLRParser.ALT ) return null;
IntervalSet elementTokenTypes = getRewriteElementTokenTypeSet();
Alternative alt = getCurrentAlt();
List<GrammarAST> elems = new ArrayList<GrammarAST>();
for (Object o : altAST.getChildren()) {
GrammarAST ref = (GrammarAST)o;
if ( elementTokenTypes.member(ref.getType()) ) {
boolean imaginary = ref.getType()==ANTLRParser.TOKEN_REF &&
!alt.tokenRefs.containsKey(ref.getText());
if ( !imaginary ) elems.add(ref);
}
}
return elems;
}
/** Given (('?'|'*') (REWRITE_BLOCK (ALT ...))) return list of element refs at
* or below toplevel REWRITE_BLOCK.
*/
public List<GrammarAST> getElementReferencesDeep(GrammarAST ebnfRoot) {
if ( ebnfRoot.getType()!=ANTLRParser.CLOSURE &&
ebnfRoot.getType()!=ANTLRParser.OPTIONAL )
{
return null;
}
GrammarAST blkAST = (GrammarAST)ebnfRoot.getChild(0);
if ( blkAST.getType()!=ANTLRParser.REWRITE_BLOCK ) return null;
GrammarAST altAST = (GrammarAST)blkAST.getChild(0);
if ( altAST.getType()!=ANTLRParser.ALT ) return null;
List<GrammarAST> elems = new ArrayList<GrammarAST>();
Alternative alt = getCurrentAlt();
IntervalSet elementTokenTypes = getRewriteElementTokenTypeSet();
List<GrammarAST> refs = altAST.getNodesWithType(elementTokenTypes);
if ( refs!=null ) {
for (GrammarAST ref : refs) {
boolean imaginary = ref.getType()==ANTLRParser.TOKEN_REF &&
!alt.tokenRefs.containsKey(ref.getText());
if ( !imaginary ) elems.add(ref);
}
}
return elems;
}
public IntervalSet getRewriteElementTokenTypeSet() {
IntervalSet elementTokenTypes = new IntervalSet();
elementTokenTypes.add(ANTLRParser.TOKEN_REF); // might be imaginary
elementTokenTypes.add(ANTLRParser.RULE_REF);
elementTokenTypes.add(ANTLRParser.STRING_LITERAL);
elementTokenTypes.add(ANTLRParser.LABEL);
return elementTokenTypes;
}
// public IntervalSet getRewriteElementTokenTypeSet() {
// IntervalSet elementTokenTypes = new IntervalSet();
// elementTokenTypes.add(ANTLRParser.TOKEN_REF); // might be imaginary
// elementTokenTypes.add(ANTLRParser.RULE_REF);
// elementTokenTypes.add(ANTLRParser.STRING_LITERAL);
// elementTokenTypes.add(ANTLRParser.LABEL);
// return elementTokenTypes;
// }
}

View File

@ -45,7 +45,7 @@ public class ParserASTExtension extends CodeGeneratorExtension {
@Override
public CodeBlockForAlt alternative(CodeBlockForAlt blk) {
Alternative alt = factory.getCurrentAlt();
if ( !alt.hasRewrite() ) blk.addLocalDecl( new RootDecl(factory) );
if ( !alt.hasRewrite() ) blk.addLocalDecl( new RootDecl(factory, 0) );
return blk;
}

View File

@ -36,6 +36,7 @@ import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.semantics.UseDefAnalyzer;
import org.antlr.v4.tool.*;
import java.util.List;
@ -179,23 +180,53 @@ public class ParserFactory extends DefaultOutputModelFactory {
@Override
public TreeRewrite treeRewrite(GrammarAST ast) {
return new TreeRewrite(this, getTreeLevel(), getCodeBlockLevel());
TreeRewrite tr = new TreeRewrite(this, getTreeLevel(), getCodeBlockLevel());
tr.addLocalDecl(new RootDecl(this, 0));
List<GrammarAST> refs =
UseDefAnalyzer.getElementReferencesShallowInOuterAlt(getGrammar(), ast);
refs = UseDefAnalyzer.filterForRuleAndTokenRefs(getCurrentAlt(), refs);
if ( refs!=null ) {
for (GrammarAST ref : refs) {
RewriteIteratorDecl d = new RewriteIteratorDecl(this, ref, getCodeBlockLevel());
tr.addLocalDecl(d);
RewriteIteratorInit init = new RewriteIteratorInit(this, d);
tr.addPreambleOp(init);
}
}
return tr;
}
@Override
public RewriteTreeOptional rewrite_optional(GrammarAST ast) {
List<GrammarAST> refs = controller.getElementReferencesDeep(ast);
return new RewriteTreeOptional(this, ast);
RewriteTreeOptional o =
new RewriteTreeOptional(this, ast, getTreeLevel(), getCodeBlockLevel());
List<GrammarAST> refs = UseDefAnalyzer.getElementReferencesInEBNF(getGrammar(),
ast,
true);
refs = UseDefAnalyzer.filterForRuleAndTokenRefs(getCurrentAlt(), refs);
if ( refs!=null ) {
for (GrammarAST ref : refs) {
RewriteIteratorDecl d = new RewriteIteratorDecl(this, ref, getCodeBlockLevel());
o.addLocalDecl(d);
o.conditionalDecls.add(d);
RewriteIteratorInit init = new RewriteIteratorInit(this, d);
o.addPreambleOp(init);
}
}
return o;
}
@Override
public RewriteTreeClosure rewrite_closure(GrammarAST ast) {
RewriteTreeClosure c =
new RewriteTreeClosure(this, ast, getTreeLevel(), getCodeBlockLevel());
List<GrammarAST> refs = controller.getElementReferencesShallow(ast);
List<GrammarAST> refs = UseDefAnalyzer.getElementReferencesInEBNF(getGrammar(),
ast,
false);
refs = UseDefAnalyzer.filterForRuleAndTokenRefs(getCurrentAlt(), refs);
if ( refs!=null ) {
for (GrammarAST ref : refs) {
RewriteIteratorDecl d = new RewriteIteratorDecl(this, ref);
RewriteIteratorDecl d = new RewriteIteratorDecl(this, ref, getCodeBlockLevel());
c.addLocalDecl(d);
c.iteratorDecls.add(d);
RewriteIteratorInit init = new RewriteIteratorInit(this, d);
@ -207,24 +238,34 @@ public class ParserFactory extends DefaultOutputModelFactory {
@Override
public RewriteTreeStructure rewrite_tree(GrammarAST root) {
return new RewriteTreeStructure(this, root, getTreeLevel(), getCodeBlockLevel());
RewriteTreeStructure t = new RewriteTreeStructure(this, root, getTreeLevel(), getCodeBlockLevel());
t.addLocalDecl( new RootDecl(this, getTreeLevel()) );
return t;
}
public List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot) {
RewriteIteratorDecl d = new RewriteIteratorDecl(this, ID);
String rootName = gen.target.getRootName(getTreeLevel());
RewriteRuleRef ruleRef;
if ( isRoot ) ruleRef = new RewriteRuleRefIsRoot(this, ID, d);
else ruleRef = new RewriteRuleRef(this, ID, d);
String iterName = gen.target.getRewriteIteratorName(ID, getCodeBlockLevel());
if ( isRoot ) ruleRef = new RewriteRuleRefIsRoot(this, ID, rootName, iterName);
else ruleRef = new RewriteRuleRef(this, ID, rootName, iterName);
return list(ruleRef);
}
public List<SrcOp> rewrite_tokenRef(GrammarAST ID, boolean isRoot) {
String itName = gen.target.getRewriteIteratorName(ID, getCodeBlockLevel());
Alternative alt = getCurrentAlt();
String rootName = gen.target.getRootName(getTreeLevel());
RewriteIteratorDecl d = (RewriteIteratorDecl)getCurrentDeclForName(itName);
String iterName = gen.target.getRewriteIteratorName(ID, getCodeBlockLevel());
if ( alt.tokenRefs.get(ID.getText())==null ) { // not ref'd on left hand side; imaginary
RewriteImagTokenRef tokenRef;
if ( isRoot ) tokenRef = new RewriteImagTokenRefIsRoot(this, ID, rootName);
else tokenRef = new RewriteImagTokenRef(this, ID, rootName);
return list(tokenRef);
}
// must be token ref on left of ->
RewriteTokenRef tokenRef;
if ( isRoot ) tokenRef = new RewriteTokenRefIsRoot(this, ID, rootName, d);
else tokenRef = new RewriteTokenRef(this, ID, rootName, d);
if ( isRoot ) tokenRef = new RewriteTokenRefIsRoot(this, ID, rootName, iterName);
else tokenRef = new RewriteTokenRef(this, ID, rootName, iterName);
return list(tokenRef);
}

View File

@ -269,12 +269,12 @@ rewriteTreeEbnf returns [CodeBlock op]
rewriteTree returns [List<SrcOp> omos]
: {
codeBlockLevel++;
// codeBlockLevel++;
treeLevel++;
List<SrcOp> elems = new ArrayList<SrcOp>();
RewriteTreeStructure t = factory.rewrite_tree($start);
CodeBlock save = factory.getCurrentBlock();
factory.setCurrentBlock(t);
// CodeBlock save = factory.getCurrentBlock();
// factory.setCurrentBlock(t);
}
^( TREE_BEGIN
rewriteTreeAtom[true] {elems.addAll($rewriteTreeAtom.omos);}
@ -283,9 +283,9 @@ rewriteTree returns [List<SrcOp> omos]
{
t.ops = elems;
$omos = DefaultOutputModelFactory.list(t);
factory.setCurrentBlock(save);
// factory.setCurrentBlock(save);
treeLevel--;
codeBlockLevel--;
// codeBlockLevel--;
}
;

View File

@ -32,6 +32,7 @@ package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.CodeBlock;
/** Either an ST or Tree rewrite */
public class Rewrite extends CodeBlock {
public Rewrite(OutputModelFactory factory, int treeLevel, int codeBlockLevel) {
super(factory, treeLevel, codeBlockLevel);

View File

@ -0,0 +1,46 @@
/*
[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.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.tool.GrammarAST;
public class RewriteImagTokenRef extends SrcOp {
public String rootName;
public RewriteImagTokenRef(OutputModelFactory factory,
GrammarAST ast,
String rootName)
{
super(factory, ast);
this.rootName = rootName;
}
}

View File

@ -0,0 +1,42 @@
/*
[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.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.GrammarAST;
public class RewriteImagTokenRefIsRoot extends RewriteImagTokenRef {
public RewriteImagTokenRefIsRoot(OutputModelFactory factory,
GrammarAST ast,
String rootName)
{
super(factory, ast, rootName);
}
}

View File

@ -31,14 +31,17 @@ package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.codegen.model.decl.RewriteIteratorDecl;
import org.antlr.v4.tool.GrammarAST;
public class RewriteRuleRef extends SrcOp {
/** Which iterator decl are we associated with? */
public RewriteIteratorDecl decl;
public RewriteRuleRef(OutputModelFactory factory, GrammarAST ast, RewriteIteratorDecl decl) {
public String rootName;
public String iterName;
public RewriteRuleRef(OutputModelFactory factory, GrammarAST ast,
String rootName, String iterName)
{
super(factory, ast);
this.decl = decl;
this.rootName = rootName;
this.iterName = iterName;
}
}

View File

@ -30,11 +30,12 @@
package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.RewriteIteratorDecl;
import org.antlr.v4.tool.GrammarAST;
public class RewriteRuleRefIsRoot extends RewriteRuleRef {
public RewriteRuleRefIsRoot(OutputModelFactory factory, GrammarAST ast, RewriteIteratorDecl decl) {
super(factory, ast, decl);
public RewriteRuleRefIsRoot(OutputModelFactory factory, GrammarAST ast,
String rootName, String iterName)
{
super(factory, ast, rootName, iterName);
}
}

View File

@ -31,18 +31,16 @@ package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.codegen.model.decl.RewriteIteratorDecl;
import org.antlr.v4.tool.GrammarAST;
public class RewriteTokenRef extends SrcOp {
/** Which iterator decl are we associated with? */
public RewriteIteratorDecl decl;
public String rootName;
public String iterName;
public RewriteTokenRef(OutputModelFactory factory, GrammarAST ast,
String rootName, RewriteIteratorDecl decl)
String rootName, String iterName)
{
super(factory, ast);
this.rootName = rootName;
this.decl = decl;
this.iterName = iterName;
}
}

View File

@ -30,13 +30,12 @@
package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.RewriteIteratorDecl;
import org.antlr.v4.tool.GrammarAST;
public class RewriteTokenRefIsRoot extends RewriteTokenRef {
public RewriteTokenRefIsRoot(OutputModelFactory factory, GrammarAST ast,
String rootName, RewriteIteratorDecl decl)
String rootName, String iterName)
{
super(factory, ast, rootName, decl);
super(factory, ast, rootName, iterName);
}
}

View File

@ -36,10 +36,11 @@ import org.antlr.v4.tool.GrammarAST;
import java.util.*;
public class RewriteTreeOptional extends CodeBlock {
public List<Decl> iteratorDecls = new ArrayList<Decl>();
public List<Decl> conditionalDecls = new ArrayList<Decl>();
public RewriteTreeOptional(OutputModelFactory factory, GrammarAST ast) {
super(factory);
public RewriteTreeOptional(OutputModelFactory factory, GrammarAST ast,
int treeLevel, int codeBlockLevel) {
super(factory, treeLevel, codeBlockLevel);
this.ast = ast;
}
}

View File

@ -30,18 +30,37 @@
package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.GrammarAST;
import java.util.List;
/** ^(A B C) */
public class RewriteTreeStructure extends TreeRewrite {
public class RewriteTreeStructure extends SrcOp {
public int treeLevel;
public int codeBlockLevel;
@ModelElement public List<SrcOp> ops;
@ModelElement public OrderedHashSet<Decl> locals;
public RewriteTreeStructure(OutputModelFactory factory,
GrammarAST ast,
int treeLevel,
int codeBlockLevel)
{
super(factory, treeLevel, codeBlockLevel);
super(factory, ast);
this.treeLevel = treeLevel;
this.codeBlockLevel = codeBlockLevel;
}
/** Add local var decl */
public void addLocalDecl(Decl d) {
if ( locals==null ) locals = new OrderedHashSet<Decl>();
locals.add(d);
d.isLocal = true;
}
public int getEnclosingTreeLevel() { return treeLevel - 1; }
}

View File

@ -31,14 +31,9 @@ package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.Rewrite;
import org.antlr.v4.codegen.model.decl.RootDecl;
public class TreeRewrite extends Rewrite {
public RootDecl rootDecl;
public TreeRewrite(OutputModelFactory factory, int treeLevel, int codeBlockLevel) {
super(factory, treeLevel, codeBlockLevel);
rootDecl = new RootDecl(factory);
addLocalDecl(rootDecl);
}
}

View File

@ -35,10 +35,11 @@ import org.antlr.v4.tool.GrammarAST;
public class RewriteIteratorDecl extends Decl {
public String listName;
public RewriteIteratorDecl(OutputModelFactory factory,
GrammarAST elem)
GrammarAST elem,
int codeBlockLevel)
{
super(factory, factory.getGenerator().target
.getRewriteIteratorName(elem, factory.getCodeBlockLevel()));
.getRewriteIteratorName(elem, codeBlockLevel));
listName = factory.getGenerator().target.getElementListName(elem);
}
}

View File

@ -32,8 +32,7 @@ package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
public class RootDecl extends Decl {
public RootDecl(OutputModelFactory factory) {
super(factory,
factory.getGenerator().target.getRootName(factory.getCodeBlockLevel()));
public RootDecl(OutputModelFactory factory, int treeLevel) {
super(factory, factory.getGenerator().target.getRootName(treeLevel));
}
}

View File

@ -884,7 +884,12 @@ rewriteTreeEbnf
$rewriteTreeEbnf.tree.getToken().setLine(firstToken.getLine());
$rewriteTreeEbnf.tree.getToken().setCharPositionInLine(firstToken.getCharPositionInLine());
}
: lp=LPAREN rewriteTreeAlt RPAREN ebnfSuffix -> ^(ebnfSuffix ^(REWRITE_BLOCK[$lp] rewriteTreeAlt))
: lp=LPAREN rewriteTreeAlt RPAREN rewriteEbnfSuffix -> ^(rewriteEbnfSuffix ^(REWRITE_BLOCK[$lp] rewriteTreeAlt))
;
rewriteEbnfSuffix
: OPTIONAL
| CLOSURE
;
rewriteTree

View File

@ -0,0 +1,87 @@
tree grammar Refs;
options {
language = Java;
tokenVocab = ANTLRParser;
ASTLabelType = GrammarAST;
}
@header {
package org.antlr.v4.semantics;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.tool.*;
import java.util.List;
import java.util.ArrayList;
}
@members {
List<GrammarAST> shallow = new ArrayList<GrammarAST>();
List<GrammarAST> deep = new ArrayList<GrammarAST>();
public int desiredShallowLevel;
public Refs(TreeNodeStream input, int desiredShallowLevel) {
this(input);
this.desiredShallowLevel = desiredShallowLevel;
}
public void track(GrammarAST t, int level) {
deep.add(t);
if ( level==desiredShallowLevel ) shallow.add(t);
}
// TODO: visitor would be better here
}
/*
rewrite
: predicatedRewrite* nakedRewrite
;
predicatedRewrite
: ^(RESULT SEMPRED rewriteAlt)
;
nakedRewrite
: ^(RESULT rewriteAlt)
;
*/
start
: ^(RESULT rewriteAlt)
| rewriteTreeEbnf[0]
;
rewriteAlt
: rewriteTreeAlt[0]
| ETC
| EPSILON
;
rewriteTreeAlt[int level]
: ^(ALT rewriteTreeElement[level]+)
;
rewriteTreeElement[int level]
: rewriteTreeAtom[level]
| rewriteTree[level]
| rewriteTreeEbnf[level]
;
rewriteTreeAtom[int level]
: ^(TOKEN_REF . .) {track($start, level);}
| ^(TOKEN_REF .) {track($start, level);}
| TOKEN_REF {track($start, level);}
| RULE_REF {track($start, level);}
| ^(STRING_LITERAL .) {track($start, level);}
| STRING_LITERAL {track($start, level);}
| LABEL {track($start, level);}
| ACTION
;
rewriteTreeEbnf[int level]
: ^((OPTIONAL | CLOSURE) ^(REWRITE_BLOCK rewriteTreeAlt[level+1]))
;
rewriteTree[int level]
: ^(TREE_BEGIN rewriteTreeAtom[level] rewriteTreeElement[level]* )
;

View File

@ -29,6 +29,7 @@
package org.antlr.v4.semantics;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.tool.*;
@ -42,11 +43,12 @@ public class UseDefAnalyzer {
for (int a=1; a<=r.numberOfAlts; a++) {
Alternative alt = r.alt[a];
for (GrammarAST e : alt.rewriteElements) {
if ( !(alt.ruleRefs.containsKey(e.getText()) ||
g.getTokenType(e.getText())!= Token.INVALID_TYPE ||
alt.labelDefs.containsKey(e.getText()) ||
e.getText().equals(r.name)) ) // $r ok in rule r
{
boolean ok =
alt.ruleRefs.containsKey(e.getText()) ||
g.getTokenType(e.getText()) != Token.INVALID_TYPE ||
alt.labelDefs.containsKey(e.getText()) ||
e.getText().equals(r.name);
if ( !ok ) { // $r ok in rule r
g.tool.errMgr.grammarError(ErrorType.REWRITE_ELEMENT_NOT_PRESENT_ON_LHS,
g.fileName, e.token, e.getText());
}
@ -68,6 +70,61 @@ public class UseDefAnalyzer {
}
}
/** Given -> (ALT ...), return list of element refs at
* top level
*/
public static List<GrammarAST> getElementReferencesShallowInOuterAlt(Grammar g,
GrammarAST altAST)
{
return UseDefAnalyzer.getRewriteElementRefs(g, altAST, 0, false);
}
/** Given (('?'|'*') (REWRITE_BLOCK (ALT ...))) return list of element refs at
* top level of REWRITE_BLOCK. Must see into (nested) tree structures if
* optional but not if closure (that might lead to inf loop when building tree).
*/
public static List<GrammarAST> getElementReferencesInEBNF(Grammar g,
GrammarAST ebnfRoot,
boolean deep)
{
return UseDefAnalyzer.getRewriteElementRefs(g, ebnfRoot, 1, deep);
}
public static List<GrammarAST> filterForRuleAndTokenRefs(Alternative alt,
List<GrammarAST> refs)
{
List<GrammarAST> elems = new ArrayList<GrammarAST>();
if ( refs!=null ) {
for (GrammarAST ref : refs) {
boolean imaginary = ref.getType()== ANTLRParser.TOKEN_REF &&
!alt.tokenRefs.containsKey(ref.getText());
if ( !imaginary ) elems.add(ref);
}
}
return elems;
}
public static List<GrammarAST> getRewriteElementRefs(Grammar g,
GrammarAST root,
int desiredShallowLevel,
boolean deep)
{
CommonTreeNodeStream nodes = new CommonTreeNodeStream(root);
Refs collector = new Refs(nodes, desiredShallowLevel);
try {
collector.start();
}
catch (org.antlr.runtime.RecognitionException re) {
g.tool.errMgr.grammarError(ErrorType.INTERNAL_ERROR,
g.fileName, re.token, re);
}
// System.out.println("from "+root.toStringTree());
// System.out.println("shallow: "+collector.shallow);
// System.out.println("deep: "+collector.deep);
return deep ? collector.deep : collector.shallow;
}
/** Find all rules reachable from r directly or indirectly for all r in g */
public static Map<Rule, Set<Rule>> getRuleDependencies(Grammar g) {
return getRuleDependencies(g, g.rules.values());