5 public abstract class Grammar extends JS {
7 public JS action = null;
10 // means we call()ed a Grammar that hasn't been bound to a scope yet
11 public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
12 throw new Error("this should never happen");
15 private static Object NULL = new Object();
17 public abstract int match(String s, int start, Hash v, JSScope scope) throws JSExn;
18 public int matchAndWrite(final String s, final int start, Hash v, JSScope scope, String key) throws JSExn {
19 final Hash v2 = new Hash();
20 final int ret = match(s, start, v2, scope);
21 Object result = ret == -1 ? NULL : action == null ?
22 s.substring(start, ret) :
23 JS.cloneWithNewParentScope(action, new JSScope(scope) {
24 public Object get(Object key) throws JSExn {
25 Object val = v2.get(key);
26 if (val == NULL) return null;
27 if (val != null) return val;
28 if (key.equals("whole")) return s.substring(start, ret);
29 return super.get(key);
31 }).call(null, null, null, null, 0);
33 Object old = v.get(key);
34 if (old == null || old == NULL) { }
35 else if (old instanceof JSArray) { if (result != NULL) { ((JSArray)old).addElement(result); result = old; } }
36 else if (result != NULL) { JSArray j = new JSArray(); j.addElement(old); j.addElement(result); result = j; }
42 public static class Alternative extends Grammar {
43 private Grammar r1, r2;
44 public Alternative(Grammar r1, Grammar r2) { this.r1 = r1; this.r2 = r2; }
45 public int match(String s, int start, Hash v, JSScope r) throws JSExn {
46 int s1 = r1.match(s, start, v, r);
47 if (s1 != -1) return s1;
48 int s2 = r2.match(s, start, v, r);
49 if (s2 != -1) return s2;
54 public static class Juxtaposition extends Grammar {
55 private Grammar r1, r2;
56 public Juxtaposition(Grammar r1, Grammar r2) { this.r1 = r1; this.r2 = r2; }
57 public int match(String s, int start, Hash v, JSScope r) throws JSExn {
58 int s1 = r1.match(s, start, v, r);
59 if (s1 == -1) return -1;
60 int s2 = r2.match(s, s1, v, r);
61 if (s2 == -1) return -1;
66 public static class Repetition extends Grammar {
69 public Repetition(Grammar r1, int min, int max) { this.r1 = r1; this.min = min; this.max = max; }
70 public int match(String s, int start, Hash v, JSScope r) throws JSExn {
72 for(i=0; i<max; i++) {
73 start = r1.match(s, start, v, r);
74 if (start == -1) return -1;
76 if (i < min) return -1;
81 public static class Literal extends Grammar {
83 public Literal(String str) { this.str = str; }
84 public int match(String s, int start, Hash v, JSScope r) {
85 if (!s.regionMatches(start, str, 0, str.length())) return -1;
86 return start + str.length();
90 public static class Range extends Grammar {
92 public Range(char min, char max) { this.min = min; this.max = max; }
93 public int match(String s, int start, Hash v, JSScope r) throws JSExn {
94 if (!(s.charAt(start) >= min && s.charAt(start) <= max)) return -1;
99 public static class Reference extends Grammar {
101 public Reference(String key) { this.key = key; }
102 public int match(String s, int start, Hash v, JSScope scope) throws JSExn {
103 return ((Grammar)scope.get(key)).matchAndWrite(s, start, v, scope, key);