1 package org.simantics.scl.compiler.parser.grammar.input;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.InputStreamReader;
7 import java.util.ArrayList;
9 import org.simantics.scl.compiler.parser.grammar.Grammar;
10 import org.simantics.scl.compiler.parser.grammar.Production;
11 import org.simantics.scl.compiler.parser.regexp.RAtom;
12 import org.simantics.scl.compiler.parser.regexp.Regexp;
14 import gnu.trove.list.array.TIntArrayList;
15 import gnu.trove.map.hash.TIntByteHashMap;
16 import gnu.trove.map.hash.TObjectIntHashMap;
18 public class GrammarParserImpl extends GrammarParser {
19 private final GrammarLexer lexer;
21 ArrayList<String> terminals = new ArrayList<String>();
22 ArrayList<String> nonterminals = new ArrayList<String>();
23 TObjectIntHashMap<String> symbols = new TObjectIntHashMap<String>();
24 ArrayList<Production> productions = new ArrayList<Production>();
25 TIntArrayList initials = new TIntArrayList();
27 public GrammarParserImpl(Reader reader) {
28 lexer = new GrammarLexer(reader);
31 private int getId(String symbol) {
32 if(symbols.contains(symbol))
33 return symbols.get(symbol);
35 if(Character.isUpperCase(symbol.charAt(0))) {
36 id = terminals.size();
37 terminals.add(symbol);
40 id = ~nonterminals.size();
41 nonterminals.add(symbol);
43 symbols.put(symbol, id);
48 protected Token nextToken() {
50 Token token = lexer.nextToken();
52 } catch(Exception e) {
53 if(e instanceof RuntimeException)
54 throw (RuntimeException)e;
56 throw new RuntimeException(e);
61 protected RuntimeException syntaxError(Token token, String description) {
62 return new RuntimeException(description);
66 protected Object reduceFile() {
71 protected Object reduceProduction() {
72 int lhs = getId(((Token)get(0)).text);
73 for(int i=2;i<length();i+=2) {
74 Production prod = (Production)get(i);
76 productions.add(prod);
82 protected Object reduceInitial() {
83 initials.add(getId(((Token)get(1)).text));
88 protected Object reduceTerminal() {
89 return new RAtom(getId(((Token)get(0)).text));
92 private static Regexp postOp(Regexp regexp, Token op) {
94 case GrammarTerminals.STAR: return Regexp.star(regexp);
95 case GrammarTerminals.PLUS: return Regexp.plus(regexp);
96 case GrammarTerminals.OPTIONAL: return Regexp.optional(regexp);
97 default: throw new IllegalStateException();
102 protected Object reduceConcatenation() {
103 ArrayList<Regexp> regexps = new ArrayList<Regexp>(length());
104 for(int i=0;i<length();++i) {
106 if(obj instanceof Regexp)
107 regexps.add((Regexp)obj);
109 Token token = (Token)obj;
110 Regexp regexp = regexps.remove(regexps.size()-1);
111 regexps.add(postOp(regexp, token));
114 return Regexp.seq(regexps.toArray(new Regexp[regexps.size()]));
118 protected Object reduceUnion() {
119 Regexp[] regexps = new Regexp[length()/2];
120 for(int i=1;i<length();i+=2)
121 regexps[i/2] = (Regexp)get(i);
122 return Regexp.or(regexps);
126 protected Object reduceProductionRhs() {
127 Regexp rhs = (Regexp)get(0);
128 String name = ((Token)get(2)).text;
129 TIntByteHashMap annotations = new TIntByteHashMap();
130 for(int i=4;i<length();i+=3) {
131 Token type = (Token)get(i);
132 int id = getId(((Token)get(i+1)).text);
133 annotations.put(id, (byte)(type.id == GrammarTerminals.SHIFT ? 0 : 1));
135 return new Production(name, 0, rhs, annotations);
138 public Grammar getGrammar() {
140 productions.toArray(new Production[productions.size()]),
141 terminals.toArray(new String[terminals.size()]),
142 nonterminals.toArray(new String[nonterminals.size()]),
147 public static Grammar read(InputStream inputStream) throws IOException {
148 GrammarParserImpl parser = new GrammarParserImpl(new InputStreamReader(inputStream, "UTF-8"));
150 return parser.getGrammar();