blob: 80d31bd334c058771259f01e76f1a4b016b11527 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.mrql.gen;
import java.io.*;
import java.util.HashMap;
import java.util.Random;
final public class Meta extends Crypt {
final public static Tree mark = new LongLeaf(-1);
static int level = 0;
private static int name_counter = 0;
public static Tree new_name () {
return new VariableLeaf("N" + (name_counter++) + "_");
}
public static Tree escape ( Tree e ) {
if (Tree.parsed) {
Tree.line_number = e.line;
Tree.position_number = e.position;
};
return e;
}
public static void clear () {
name_counter = 0;
name_index = 0;
name_vars.clear();
package_name = "PatternNames_"+Math.abs(random.nextLong());
}
public static Tree escape ( String s ) { return new VariableLeaf(s); }
public static Tree escape ( long n ) { return new LongLeaf(n); }
public static Tree escape ( double n ) { return new DoubleLeaf(n); }
private static HashMap<String,Integer> name_vars = new HashMap<String,Integer>(1000);
private static int name_index = 0;
private final static Random random = new Random();
private static String package_name = "PatternNames_"+Math.abs(random.nextLong());
private static String name ( String s ) {
Integer ns = name_vars.get(s);
if (ns == null) {
ns = new Integer(name_index++);
name_vars.put(s,ns);
};
return package_name+".P_"+ns.intValue();
}
static void dump_names ( PrintStream out ) {
if (name_vars.isEmpty())
return;
out.println("abstract class "+package_name+" {");
for ( String s: name_vars.keySet() )
out.println(" final static String P_"+name_vars.get(s)+" = Tree.add("+s+");");
out.println("}");
}
public static Trees subst_list ( Tree term, Tree value, Trees es ) {
Trees res = Trees.nil;
for (Trees r = es; !r.is_empty(); r = r.tail)
res = res.cons(subst_expr(term,value,r.head));
return res.reverse();
}
public static Tree subst_expr ( Tree term, Tree value, Tree e ) {
if (e.equals(term))
return value;
else if (e instanceof Node)
return new Node(((Node)e).name,
subst_list(term,value,((Node)e).children));
else return e;
}
public static Tree substitute ( Trees path, Tree e, Tree value ) {
if (path.is_empty())
return value;
else {
Trees res = Trees.nil;
for (Trees r = ((Node)e).children; !r.is_empty(); r = r.tail)
if (r.head.equals(path.head))
res = res.cons(substitute(path.tail,r.head,value));
else res = res.cons(r.head);
return new Node(((Node)e).name,res.reverse());
}
}
public static String reify ( Tree e ) {
if (e instanceof LongLeaf)
return "new LongLeaf(" + e + ")";
else if (e instanceof DoubleLeaf)
return "new DoubleLeaf(" + e + ")";
else if (e instanceof VariableLeaf)
if (((VariableLeaf)e).value.equals("_any_"))
throw new Error("Gen: Cannot use \"_\" (any) in Tree Construction: "+e);
else return "new VariableLeaf(" + encrypt(((VariableLeaf)e).value) + ")";
else if (e instanceof StringLeaf)
return "new StringLeaf(" + e + ")";
else {
Node n = (Node) e;
if (n.name.equals("Node")) {
String s = "new Node(";
if (n.children.head instanceof VariableLeaf)
if (((VariableLeaf)n.children.head).value.equals("_any_"))
throw new Error("Gen: Cannot use \"_\" (any) in AST node name: "+e);
else s = s + encrypt(((VariableLeaf)n.children.head).value);
else {
Node m = (Node) n.children.head;
if (m.name.equals("Code"))
s = s + ((StringLeaf)m.children.head).value;
else if (m.name.equals("Escape"))
s = s + ((VariableLeaf)m.children.head).value;
};
s = s + ",Trees.nil";
for (Trees r= n.children.tail; !r.is_empty(); r = r.tail)
if (r.head instanceof Node && ((Node)r.head).name.equals("Dots")) {
Node m = (Node) r.head;
if (m.children.is_empty())
throw new Error("Gen: Cannot use \"...\" in Tree construction: "+e);
else if (m.children.head instanceof VariableLeaf)
s = s + ".append(" + ((VariableLeaf)m.children.head).value + ")";
else s = s + ".append(" + ((StringLeaf)m.children.head).value + ")";
} else s = s + ".append(" + reify(r.head) + ")";
return s + ")";
} else if (n.name.equals("Code"))
return "Meta.escape(" + ((StringLeaf)n.children.head).value + ")";
else if (n.name.equals("Escape"))
return "Meta.escape(" + ((VariableLeaf)n.children.head).value + ")";
else if (n.name.equals("Higher"))
return "Meta.substitute(" + ((VariableLeaf)n.children.head).value
+ ".tail," + ((VariableLeaf)n.children.head).value
+ ".head," + reify(n.children.tail.head) + ")";
else throw new Error("Gen: Wrong Tree construction: "+e);
}
}
public static Condition pattern_list ( Trees args, String v ) {
if (args.is_empty())
return new Condition("",v+".tail==null",0);
else if (args.head instanceof Node && ((Node)args.head).name.equals("Dots")) {
if (args.tail.is_empty()) {
Node m = (Node) args.head;
if (m.children.is_empty())
return new Condition("","true",0);
else if (m.children.head instanceof VariableLeaf)
return new Condition("Trees " + ((VariableLeaf)m.children.head).value + " = " + v + "; ",
"true",0);
else if (m.children.head instanceof StringLeaf)
new Condition("",v + ".head.equals(" + ((StringLeaf)m.children.head).value + ")",0);
return new Condition("","true",0);
} else {
Node m = (Node) args.head;
if (m.children.is_empty()) {
Condition rest = pattern_list(args.tail,"R_");
return new Condition("Trees R_ = " + v + "; for(; R_.tail!=null && !(" + rest.pred
+ "); R_=R_.tail) ; if (R_.tail!=null) { " + rest.stmt,
"true",rest.unmatched_brackets+1);
} else if (m.children.head instanceof VariableLeaf) {
String nm = ((VariableLeaf)m.children.head).value;
Condition rest = pattern_list(args.tail,nm+"_");
return new Condition("Trees " + nm + " = Trees.nil; Trees " + nm + "_=" + v + "; "
+ "for(; " + nm + "_.tail!=null && !(" + rest.pred + "); "
+ nm + "_=(FOUND_" + Meta.level + ")?" + nm + "_:" + nm + "_.tail) " + nm + " = " + nm + ".append("
+ nm + "_.head); " + "if (" + nm + "_.tail!=null) { " + rest.stmt,
"true",rest.unmatched_brackets+1);
} else if (m.children.head instanceof StringLeaf) {
Condition rest = pattern_list(args.tail,v);
return new Condition(rest.stmt,
v + ".equals(" + ((StringLeaf)m.children.head).value + ")" + rest.and(),
rest.unmatched_brackets);
};
return new Condition("","true",0);
}
} else {
Condition c = pattern(args.head,v+".head");
Condition rest = pattern_list(args.tail,v+".tail");
return new Condition(c.stmt + rest.stmt,
v + ".tail!=null" + c.and() + rest.and(),
c.unmatched_brackets+rest.unmatched_brackets);
}
}
public static Condition pattern ( Tree e, String v ) {
if (e instanceof LongLeaf)
return new Condition("", "(" + v + " instanceof LongLeaf) && ((LongLeaf)" + v + ").value==" + e,0);
else if (e instanceof DoubleLeaf)
return new Condition("","(" + v + " instanceof DoubleLeaf) && ((DoubleLeaf)" + v + ").value==" + e,0);
else if (e instanceof VariableLeaf)
if (((VariableLeaf)e).value.equals("_any_"))
return new Condition("","true",0);
else return new Condition("","(" + v + " instanceof VariableLeaf) && ((VariableLeaf)" + v
+ ").value==" + name(encrypt(((VariableLeaf)e).value)),0);
else if (e instanceof StringLeaf)
return new Condition("","(" + v + " instanceof StringLeaf) && ((StringLeaf)" + v + ").value.equals(" + e + ")",0);
else {
Node n = (Node) e;
if (n.name.equals("Node")) {
String p = "(" + v + " instanceof Node)";
String s = "";
if (n.children.head instanceof VariableLeaf) {
if (((VariableLeaf)n.children.head).value!="_any_")
p = p + " && ((Node)" + v + ").name=="
+ name(encrypt(((VariableLeaf)n.children.head).value));
} else if (n.children.head instanceof Node)
if (((Node)n.children.head).name.equals("Escape"))
s = "String " + ((VariableLeaf)((Node)n.children.head).children.head).value
+ " = ((Node)" + v + ").name; ";
else throw new Error("Gen: Wrong Tree pattern: "+e);
Condition c = pattern_list(n.children.tail,"((Node)" + v + ").children");
return new Condition(s+c.stmt,p+c.and(),c.unmatched_brackets);
} else if (n.name.equals("Escape"))
return new Condition("Tree " + ((VariableLeaf)n.children.head).value + " = " + v + "; ",
"true",0);
else if (n.name.equals("IS")) {
String nm = ((VariableLeaf)n.children.head).value;
Condition c = pattern(n.children.tail.head,nm);
return new Condition(c.stmt + "Tree " + nm + " = " + v + "; ",c.pred,0);
} else if (n.name.equals("Code"))
return new Condition("",v + ".equals(" + ((StringLeaf)n.children.head).value + ")",0);
else if (n.name.equals("Higher")) {
String nm = ((VariableLeaf)n.children.head).value;
Condition c = pattern(n.children.tail.head,nm+"__");
String s = reify(n.children.tail.head);
return new Condition("Tree " + nm + "_ = " + v + "; Trees " + nm + " = Trees.nil; Trees STACK_" + nm
+ "_ = new Trees(" + nm + "_); while (!FOUND_" + Meta.level + " && STACK_" + nm + "_.tail!=null) { Tree "
+ nm + "__ = STACK_" + nm + "_.head; STACK_" + nm + "_ = STACK_" + nm + "_.tail; " + nm
+ " = (" + nm + "__==Meta.mark) ? " + nm + ".tail : ((" + nm + "__ instanceof Node) ? "
+ nm + ".cons(" + nm + "__) : " + nm + "); if (" + nm + "__ instanceof Node) STACK_" + nm
+ "_ = ((Node)" + nm + "__).children.append(STACK_" + nm + "_.cons(Meta.mark)); if ("
+ nm + "__!=Meta.mark" + c.and() + ") { if (!(" + nm + "__ instanceof Node)) " + nm + "="
+ nm + ".cons(" + nm + "__); " + nm + " = " + nm + ".reverse(); " + c.stmt,"true",2);
} else throw new Error("Gen: Wrong Tree pattern: "+e);
}
}
}