A B+ -> ^(A B)* works! fixed ant build
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8838]
This commit is contained in:
parent
df80cb7622
commit
f8abf5d40b
31
build.xml
31
build.xml
|
@ -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}">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) ::= <<
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]* )
|
||||
;
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue