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("\u005c"") && s.endsWith("\u005c"") : 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      /** Generated Token Manager. */
203      public WirthParserTokenManager token_source;
204      SimpleCharStream jj_input_stream;
205      /** Current token. */
206      public Token token;
207      /** Next token. */
208      public Token jj_nt;
209      private int jj_ntk;
210      private int jj_gen;
211      final private int[] jj_la1 = new int[4];
212      static private int[] jj_la1_0;
213      static {
214          jj_la1_init_0();
215       }
216       private static void jj_la1_init_0() {
217          jj_la1_0 = new int[] {0x4,0x2000,0x2a6,0x2a6,};
218       }
219    
220      /** Constructor with InputStream. */
221      public WirthParser(java.io.InputStream stream) {
222         this(stream, null);
223      }
224      /** Constructor with InputStream and supplied encoding */
225      public WirthParser(java.io.InputStream stream, String encoding) {
226        try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
227        token_source = new WirthParserTokenManager(jj_input_stream);
228        token = new Token();
229        jj_ntk = -1;
230        jj_gen = 0;
231        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
232      }
233    
234      /** Reinitialise. */
235      public void ReInit(java.io.InputStream stream) {
236         ReInit(stream, null);
237      }
238      /** Reinitialise. */
239      public void ReInit(java.io.InputStream stream, String encoding) {
240        try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
241        token_source.ReInit(jj_input_stream);
242        token = new Token();
243        jj_ntk = -1;
244        jj_gen = 0;
245        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
246      }
247    
248      /** Constructor. */
249      public WirthParser(java.io.Reader stream) {
250        jj_input_stream = new SimpleCharStream(stream, 1, 1);
251        token_source = new WirthParserTokenManager(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      /** Reinitialise. */
259      public void ReInit(java.io.Reader stream) {
260        jj_input_stream.ReInit(stream, 1, 1);
261        token_source.ReInit(jj_input_stream);
262        token = new Token();
263        jj_ntk = -1;
264        jj_gen = 0;
265        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
266      }
267    
268      /** Constructor with generated Token Manager. */
269      public WirthParser(WirthParserTokenManager tm) {
270        token_source = tm;
271        token = new Token();
272        jj_ntk = -1;
273        jj_gen = 0;
274        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
275      }
276    
277      /** Reinitialise. */
278      public void ReInit(WirthParserTokenManager tm) {
279        token_source = tm;
280        token = new Token();
281        jj_ntk = -1;
282        jj_gen = 0;
283        for (int i = 0; i < 4; i++) jj_la1[i] = -1;
284      }
285    
286      private Token jj_consume_token(int kind) throws ParseException {
287        Token oldToken;
288        if ((oldToken = token).next != null) token = token.next;
289        else token = token.next = token_source.getNextToken();
290        jj_ntk = -1;
291        if (token.kind == kind) {
292          jj_gen++;
293          return token;
294        }
295        token = oldToken;
296        jj_kind = kind;
297        throw generateParseException();
298      }
299    
300    
301    /** Get the next Token. */
302      final public Token getNextToken() {
303        if (token.next != null) token = token.next;
304        else token = token.next = token_source.getNextToken();
305        jj_ntk = -1;
306        jj_gen++;
307        return token;
308      }
309    
310    /** Get the specific Token. */
311      final public Token getToken(int index) {
312        Token t = token;
313        for (int i = 0; i < index; i++) {
314          if (t.next != null) t = t.next;
315          else t = t.next = token_source.getNextToken();
316        }
317        return t;
318      }
319    
320      private int jj_ntk() {
321        if ((jj_nt=token.next) == null)
322          return (jj_ntk = (token.next=token_source.getNextToken()).kind);
323        else
324          return (jj_ntk = jj_nt.kind);
325      }
326    
327      private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
328      private int[] jj_expentry;
329      private int jj_kind = -1;
330    
331      /** Generate ParseException. */
332      public ParseException generateParseException() {
333        jj_expentries.clear();
334        boolean[] la1tokens = new boolean[20];
335        if (jj_kind >= 0) {
336          la1tokens[jj_kind] = true;
337          jj_kind = -1;
338        }
339        for (int i = 0; i < 4; i++) {
340          if (jj_la1[i] == jj_gen) {
341            for (int j = 0; j < 32; j++) {
342              if ((jj_la1_0[i] & (1<<j)) != 0) {
343                la1tokens[j] = true;
344              }
345            }
346          }
347        }
348        for (int i = 0; i < 20; i++) {
349          if (la1tokens[i]) {
350            jj_expentry = new int[1];
351            jj_expentry[0] = i;
352            jj_expentries.add(jj_expentry);
353          }
354        }
355        int[][] exptokseq = new int[jj_expentries.size()][];
356        for (int i = 0; i < jj_expentries.size(); i++) {
357          exptokseq[i] = jj_expentries.get(i);
358        }
359        return new ParseException(token, exptokseq, tokenImage);
360      }
361    
362      /** Enable tracing. */
363      final public void enable_tracing() {
364      }
365    
366      /** Disable tracing. */
367      final public void disable_tracing() {
368      }
369    
370    }