Commit 6bd4cd59 authored by petter's avatar petter

basic fragments of xpath functionality and generic visitor support on XMLElement trees

git-svn-id: https://www2.in.tum.de/repos/cup/develop@69 f8377d4f-c7f8-0310-b030-a31f13008fac
parent f6f9792c
<project name="emugen" default ="dist" basedir=".">
<project name="cup" default ="dist" basedir=".">
<property name="etc" location="etc" />
<property name="bin" location="bin" />
<property name="lib" location="lib" />
......@@ -69,7 +69,7 @@
token="+ version_str"
value='+ "v0.11b ${cupversion} (SVN rev ${svnversion})"'>
</replace>
<javac srcdir="${java}" destdir="${classes}" verbose="off" listfiles="off" debug="on" source="1.5" target="1.5">
<javac srcdir="${java}" destdir="${classes}" verbose="off" listfiles="off" debug="on" source="1.8" target="1.8">
<classpath refid="libraries"/>
</javac>
</target>
......
CUP version 0.11b 20151001 is a feature release.
Implemented a generic pre-/post DFS search with visitor support
Also added fragments of XPath 1.0 query support on parse trees
Fixed the visibility of children and the variant attribute of XMLElement
M. Petter
Technische Universität München
2015/10/01
------------------------------------------------------------------------
CUP version 0.11b 20150326 is a bugfix release.
Fixed an issue with empty productions having non-empty location information
......
package java_cup.runtime;
import java.util.HashMap;
import java.util.List;
public class SyntaxTreeDFS {
public static interface ElementHandler {
public void handle(XMLElement parent, List<XMLElement> children);
}
public static abstract class AbstractVisitor implements Visitor {
private HashMap<String, ElementHandler> preMap = new HashMap<>();
private HashMap<String, ElementHandler> postMap = new HashMap<>();
public abstract void defaultPre(XMLElement element, List<XMLElement> children);
public abstract void defaultPost(XMLElement element,List<XMLElement> children);
@Override
public void preVisit(XMLElement element) {
ElementHandler handler = preMap.get(element.tagname);
if (handler==null) {
defaultPre(element,element.getChildren());
} else
handler.handle(element, element.getChildren());
}
@Override
public void postVisit(XMLElement element) {
ElementHandler handler = postMap.get(element.tagname);
if (handler==null) {
defaultPost(element,element.getChildren());
} else
handler.handle(element, element.getChildren());
}
public void registerPreVisit(String s,ElementHandler h){
preMap.put(s, h);
}
public void registerPostVisit(String s, ElementHandler h){
postMap.put(s, h);
}
}
public static interface Visitor {
public void preVisit(XMLElement element);
public void postVisit(XMLElement element);
}
public static void dfs(XMLElement element, Visitor visitor){
visitor.preVisit(element);
for (XMLElement el :element.getChildren()){
dfs(el,visitor);
}
visitor.postVisit(element);
}
}
package java_cup.runtime;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class SyntaxTreeXPath {
public static List<XMLElement> query(String query, XMLElement element){
if (query.startsWith("/")) query=query.substring(1);
return query0(new LinkedList<String>(Arrays.asList( query.split("/"))),0,element,0);
}
private static List<XMLElement> query0(List<String> q,int idx, XMLElement element,int seq){
if (q.get(idx).isEmpty()) { // match deeper descendant q[1]
return matchDeeperDescendant(q,idx+1 ,element,seq);
}
List<XMLElement> l = new LinkedList<XMLElement>();
if (!match(q.get(idx),element,seq)) return new LinkedList();
if (q.size()-1==idx) return singleton(element);
List<XMLElement> children = element.getChildren();
for (int i=0; i< children.size();i++){
XMLElement child= children.get(i);
l.addAll(query0(q,idx+1,child,i));
}
return l;
}
private static List<XMLElement> matchDeeperDescendant(List<String> query,int idx, XMLElement element, int seq){
if (query.size()<=idx) return singleton(element);
boolean matches = match(query.get(idx),element,seq);
List<XMLElement> l = new LinkedList<XMLElement>();
List<XMLElement> children = element.getChildren();
if (matches) return query0(query,idx,element,seq);
for (int i=0; i< children.size();i++){
XMLElement child= children.get(i);
l.addAll(matchDeeperDescendant(query, idx, child,i));
}
return l;
}
private static boolean match(String m,XMLElement elem,int seq){
// System.out.println("Matching "+elem.tagname+" with "+m);
boolean result = true;
String[] name = m.split("\\[");
String[] tag = name[0].split("\\*");
if (tag[0].isEmpty()) { // start is wildcard
if (tag.length>2)
result &= elem.tagname.contains(tag[1]);
else
if (tag.length==2)
result &= elem.tagname.endsWith(tag[1]);
else
result &= false;
} else { // match with start
if (tag.length==2)
result &=elem.tagname.startsWith(tag[1]);
else
result = elem.tagname.equals(tag[0]);
}
for (int i=1; i<name.length; i++) {
String predicate= name[i];
if (!predicate.endsWith("]")) return false;
predicate=predicate.substring(0, predicate.length()-1);
if (predicate.startsWith("@")){
if (predicate.substring(1).startsWith("variant"))
if ((elem instanceof XMLElement.NonTerminal)&& Integer.parseInt(predicate.substring(9))==((XMLElement.NonTerminal)elem).getVariant())
result&=true;
else
return false;
else return false;
} else
if (predicate.matches("\\d+")){
result &= Integer.parseInt(predicate)==seq;
}
else
return false; // submatch
}
return result;
}
private static List<XMLElement> singleton(XMLElement elem){
LinkedList<XMLElement> l = new LinkedList<XMLElement>();
l.add(elem);
return l;
}
}
......@@ -76,8 +76,8 @@ public abstract class XMLElement {
public abstract Location right();
public abstract Location left();
protected abstract void dump(XMLStreamWriter writer) throws XMLStreamException;
public abstract List<XMLElement> getChildren();
public abstract boolean hasChildren();
public List<XMLElement> getChildren() {return new LinkedList<XMLElement>(); };
public boolean hasChildren() { return false; };
public static class NonTerminal extends XMLElement {
public boolean hasChildren() { return !list.isEmpty(); }
public List<XMLElement> getChildren() { return list; }
......@@ -147,7 +147,6 @@ public abstract class XMLElement {
public static class Error extends XMLElement {
public boolean hasChildren() { return false; }
public List<XMLElement> getChildren() { return null; }
@Override
public List<XMLElement> selectById(String s) {
return new LinkedList<XMLElement>();
......@@ -174,7 +173,6 @@ public abstract class XMLElement {
public static class Terminal extends XMLElement {
public boolean hasChildren() { return false; }
public List<XMLElement> getChildren() { return null; }
public List<XMLElement> selectById(String s) {
List<XMLElement> ret = new LinkedList<XMLElement>();
if (tagname.equals(s)) { ret.add(this); }
......
import java_cup.runtime.SyntaxTreeDFS.AbstractVisitor;
import java_cup.runtime.SyntaxTreeDFS;
import java_cup.runtime.XMLElement;
import java.util.List;
public class TestVisitor extends AbstractVisitor {
public TestVisitor(){
registerPreVisit("stmt",this::preVisitStatement);
}
public void preVisitStatement(XMLElement element, List<XMLElement> children){
System.out.println("Found a statement");
SyntaxTreeDFS.dfs(element,new TerminalFilter());
}
public void defaultPre(XMLElement elem, List<XMLElement> children) {}
public void defaultPost(XMLElement elem, List<XMLElement> children) {}
}
class TerminalFilter extends AbstractVisitor {
public void defaultPre(XMLElement elem, List<XMLElement> children) {
if (elem instanceof XMLElement.Terminal)
System.out.println(""+elem);
}
public void defaultPost(XMLElement elem, List<XMLElement> children) {}
}
......@@ -3,5 +3,5 @@ rm *.class
jflex minijava.jflex
java -jar ../../dist/java-cup-11b.jar -locations -interface -parser Parser -xmlactions minijava.cup
javac -cp ../../dist/java-cup-11b-runtime.jar:. *.java
java -cp ../../dist/java-cup-11b-runtime.jar:. Parser simple.minijava simple.xml
java -cp ../../dist/java-cup-11b-runtime.jar:. Parser simple.minijava simple.xml /
basex codegen.sq output.xml > simple.minijvm
/* Minijava Grammar */
import java_cup.runtime.*;
import java_cup.runtime.ComplexSymbolFactory;
import java_cup.runtime.ScannerBuffer;
import java_cup.runtime.XMLElement;
......@@ -21,6 +22,15 @@ parser code {:
// start parsing
Parser p = new Parser(lexer,csf);
XMLElement e = (XMLElement)p.parse().value;
for (XMLElement el: SyntaxTreeXPath.query(args[2],e)){
System.out.println(el.getTagname());
}
TestVisitor t = new TestVisitor();
SyntaxTreeDFS.dfs(e,t);
// create XML output file
XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
XMLStreamWriter sw = outFactory.createXMLStreamWriter(new FileOutputStream(args[1]));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment