mass rename and rebranding from xwt to ibex - fixed to use ixt files
[org.ibex.core.git] / src / org / ibex / util / Grammar.java
1 package org.ibex.util;
2
3 import org.ibex.js.*;
4
5 public abstract class Grammar extends JS {
6
7     public JS action = null;
8     public Grammar() { }
9
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");
13     }
14
15     private static Object NULL = new Object();
16     
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);
30                     }
31                 }).call(null, null, null, null, 0);
32         if (key != null) {
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; }
37             v.put(key, result);
38         }
39         return ret;
40     }
41
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;
50             return -1;
51         }
52     }
53
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;
62             return s2;
63         }
64     }
65
66     public static class Repetition extends Grammar {
67         private Grammar r1;
68         private int min, max;
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 {
71             int i;
72             for(i=0; i<max; i++) {
73                 start = r1.match(s, start, v, r);
74                 if (start == -1) return -1;
75             }
76             if (i < min) return -1;
77             return start;
78         }
79     }
80
81     public static class Literal extends Grammar {
82         String str;
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();
87         }
88     }
89
90     public static class Range extends Grammar {
91         char min, max;
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;
95             return start + 1;
96         }
97     }
98
99     public static class Reference extends Grammar {
100         String key;
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);
104         }
105     }
106 }