001    /* Generated By:JavaCC: Do not edit this line. WirthParser.java */
002    package net.hydromatic.clapham.parser.wirth;
003    
004    import java.util.*;
005    import net.hydromatic.clapham.parser.*;
006    
007    /**
008     * Parser for grammars in Wirth Syntax Notation.
009     *
010     * <p><a href="http://en.wikipedia.org/wiki/Wirth_syntax_notation">Wirth Syntax
011     * Notation</a> (WSN) is an alternative to Backus-Naur Form.
012     *
013     * @author Julian Hyde
014     * @version $Id: WirthParser.jj 3 2009-05-11 08:11:57Z jhyde $
015     */
016    public class WirthParser implements WirthParserConstants {
017        public static <E extends EbnfNode> void toString(
018            StringBuilder buf, String start, List<E> list, String end)
019        {
020            int i = 0;
021            buf.append(start);
022            for (E node : list) {
023                if (i++ > 0) {
024                    buf.append(", ");
025                }
026                node.toString(buf);
027            }
028            buf.append(end);
029        }
030    
031    /*
032    Example:
033    
034    Wirth's BNF:
035    
036    SYNTAX     = { PRODUCTION } .
037    PRODUCTION = IDENTIFIER "=" EXPRESSION "." .
038    EXPRESSION = TERM { "|" TERM } .
039    TERM       = FACTOR { FACTOR } .
040    FACTOR     = IDENTIFIER
041               | LITERAL
042               | "[" EXPRESSION "]"
043               | "(" EXPRESSION ")"
044               | "{" EXPRESSION "}" .
045    IDENTIFIER = letter { letter } .
046    LITERAL    = """" character { character } """" .
047    */
048    
049    /*****************************************
050     * Syntactical Descriptions              *
051     *****************************************/
052    
053    // SYNTAX     = { PRODUCTION } .
054      final public List<ProductionNode> Syntax() throws ParseException {
055        List<ProductionNode> list = new ArrayList<ProductionNode>();
056        ProductionNode p;
057        label_1:
058        while (true) {
059          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
060          case IDENTIFIER:
061            ;
062            break;
063          default:
064            jj_la1[0] = jj_gen;
065            break label_1;
066          }
067          p = Production();
068                list.add(p);
069        }
070            {if (true) return list;}
071        throw new Error("Missing return statement in function");
072      }
073    
074    // PRODUCTION = IDENTIFIER "=" EXPRESSION "." .
075      final public ProductionNode Production() throws ParseException {
076        IdentifierNode id;
077        EbnfNode expression;
078        id = Identifier();
079        jj_consume_token(EQ);
080        expression = Expression();
081        jj_consume_token(DOT);
082            {if (true) return new ProductionNode(id, expression);}
083        throw new Error("Missing return statement in function");
084      }
085    
086    // EXPRESSION = TERM { "|" TERM } .
087      final public EbnfNode Expression() throws ParseException {
088        List<EbnfNode> list = new ArrayList<EbnfNode>();
089        EbnfNode n;
090        n = Term();
091            list.add(n);
092        label_2:
093        while (true) {
094          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
095          case BAR:
096            ;
097            break;
098          default:
099            jj_la1[1] = jj_gen;
100            break label_2;
101          }
102          jj_consume_token(BAR);
103          n = Term();
104                list.add(n);
105        }
106            if (list.size() == 1) {
107                {if (true) return list.get(0);}
108            } else {
109                {if (true) return new AlternateNode(list);}
110            }
111        throw new Error("Missing return statement in function");
112      }
113    
114    // TERM       = FACTOR { FACTOR } .
115      final public EbnfNode Term() throws ParseException {
116        List<EbnfNode> list = new ArrayList<EbnfNode>();
117        EbnfNode n;
118        n = Factor();
119            list.add(n);
120        label_3:
121        while (true) {
122          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
123          case LITERAL:
124          case IDENTIFIER:
125          case LPAREN:
126          case LBRACE:
127          case LBRACKET:
128            ;
129            break;
130          default:
131            jj_la1[2] = jj_gen;
132            break label_3;
133          }
134          n = Factor();
135                list.add(n);
136        }
137            if (list.size() == 1) {
138                {if (true) return list.get(0);}
139            } else {
140                {if (true) return new SequenceNode(list);}
141            }
142        throw new Error("Missing return statement in function");
143      }
144    
145    // FACTOR     = IDENTIFIER
146    //            | LITERAL
147    //            | "[" EXPRESSION "]"
148    //            | "(" EXPRESSION ")"
149    //            | "{" EXPRESSION "}" .
150      final public EbnfNode Factor() throws ParseException {
151        EbnfNode n;
152        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
153        case IDENTIFIER:
154          n = Identifier();
155          break;
156        case LITERAL:
157          n = Literal();
158          break;
159        case LBRACKET:
160          jj_consume_token(LBRACKET);
161          n = Expression();
162          jj_consume_token(RBRACKET);
163                n = new OptionNode(n);
164          break;
165        case LPAREN:
166          jj_consume_token(LPAREN);
167          n = Expression();
168          jj_consume_token(RPAREN);
169          break;
170        case LBRACE:
171          jj_consume_token(LBRACE);
172          n = Expression();
173          jj_consume_token(RBRACE);
174                n = new RepeatNode(n);
175          break;
176        default:
177          jj_la1[3] = jj_gen;
178          jj_consume_token(-1);
179          throw new ParseException();
180        }
181            {if (true) return n;}
182        throw new Error("Missing return statement in function");
183      }
184    
185    // IDENTIFIER = letter { letter } .
186      final public IdentifierNode Identifier() throws ParseException {
187        String s;
188        s = jj_consume_token(IDENTIFIER).image;
189            {if (true) return new IdentifierNode(s);}
190        throw new Error("Missing return statement in function");
191      }
192    
193    // LITERAL    = """" character { character } """" .
194      final public LiteralNode Literal() throws ParseException {
195        String s;
196        s = jj_consume_token(LITERAL).image;
197            assert s.startsWith("\"") && s.endsWith("\"") : s;
198            {if (true) return new LiteralNode(s.substring(1, s.length() - 1));}
199        throw new Error("Missing return statement in function");
200      }
201    
202      public WirthParserTokenManager token_source;
203      SimpleCharStream jj_input_stream;
204      public Token token, jj_nt;
205      private int jj_ntk;
206      private int jj_gen;
207      final private int[] jj_la1 = new int[4];
208      static private int[] jj_la1_0;
209      static {
210          jj_la1_0();
211       }
212       private static void jj_la1_0() {
213          jj_la1_0 = new int[] {0x4,0x2000,0x2a6,0x2a6,};
214       }
215    
216      public WirthParser(java.io.InputStream stream) {
217         this(stream, null);
218      }
219      public WirthParser(java.io.InputStream stream, String encoding) {
220        try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
221        token_source = new WirthParserTokenManager(jj_input_stream);
222        token = new Token();
223        jj_ntk = -1;
224        jj_gen = 0;
225        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
226      }
227    
228      public void ReInit(java.io.InputStream stream) {
229         ReInit(stream, null);
230      }
231      public void ReInit(java.io.InputStream stream, String encoding) {
232        try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
233        token_source.ReInit(jj_input_stream);
234        token = new Token();
235        jj_ntk = -1;
236        jj_gen = 0;
237        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
238      }
239    
240      public WirthParser(java.io.Reader stream) {
241        jj_input_stream = new SimpleCharStream(stream, 1, 1);
242        token_source = new WirthParserTokenManager(jj_input_stream);
243        token = new Token();
244        jj_ntk = -1;
245        jj_gen = 0;
246        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
247      }
248    
249      public void ReInit(java.io.Reader stream) {
250        jj_input_stream.ReInit(stream, 1, 1);
251        token_source.ReInit(jj_input_stream);
252        token = new Token();
253        jj_ntk = -1;
254        jj_gen = 0;
255        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
256      }
257    
258      public WirthParser(WirthParserTokenManager tm) {
259        token_source = tm;
260        token = new Token();
261        jj_ntk = -1;
262        jj_gen = 0;
263        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
264      }
265    
266      public void ReInit(WirthParserTokenManager tm) {
267        token_source = tm;
268        token = new Token();
269        jj_ntk = -1;
270        jj_gen = 0;
271        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
272      }
273    
274      final private Token jj_consume_token(int kind) throws ParseException {
275        Token oldToken;
276        if ((oldToken = token).next != null) token = token.next;
277        else token = token.next = token_source.getNextToken();
278        jj_ntk = -1;
279        if (token.kind == kind) {
280          jj_gen++;
281          return token;
282        }
283        token = oldToken;
284        jj_kind = kind;
285        throw generateParseException();
286      }
287    
288      final public Token getNextToken() {
289        if (token.next != null) token = token.next;
290        else token = token.next = token_source.getNextToken();
291        jj_ntk = -1;
292        jj_gen++;
293        return token;
294      }
295    
296      final public Token getToken(int index) {
297        Token t = token;
298        for (int i = 0; i < index; i++) {
299          if (t.next != null) t = t.next;
300          else t = t.next = token_source.getNextToken();
301        }
302        return t;
303      }
304    
305      final private int jj_ntk() {
306        if ((jj_nt=token.next) == null)
307          return (jj_ntk = (token.next=token_source.getNextToken()).kind);
308        else
309          return (jj_ntk = jj_nt.kind);
310      }
311    
312      private java.util.Vector jj_expentries = new java.util.Vector();
313      private int[] jj_expentry;
314      private int jj_kind = -1;
315    
316      public ParseException generateParseException() {
317        jj_expentries.removeAllElements();
318        boolean[] la1tokens = new boolean[20];
319        for (int i = 0; i < 20; i++) {
320          la1tokens[i] = false;
321        }
322        if (jj_kind >= 0) {
323          la1tokens[jj_kind] = true;
324          jj_kind = -1;
325        }
326        for (int i = 0; i < 4; i++) {
327          if (jj_la1[i] == jj_gen) {
328            for (int j = 0; j < 32; j++) {
329              if ((jj_la1_0[i] & (1<<j)) != 0) {
330                la1tokens[j] = true;
331              }
332            }
333          }
334        }
335        for (int i = 0; i < 20; i++) {
336          if (la1tokens[i]) {
337            jj_expentry = new int[1];
338            jj_expentry[0] = i;
339            jj_expentries.addElement(jj_expentry);
340          }
341        }
342        int[][] exptokseq = new int[jj_expentries.size()][];
343        for (int i = 0; i < jj_expentries.size(); i++) {
344          exptokseq[i] = (int[])jj_expentries.elementAt(i);
345        }
346        return new ParseException(token, exptokseq, tokenImage);
347      }
348    
349      final public void enable_tracing() {
350      }
351    
352      final public void disable_tracing() {
353      }
354    
355    }