]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/parser/generator/java/GenerateParser.java
Moved SCL parser generator to platform repository.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / parser / generator / java / GenerateParser.java
1 package org.simantics.scl.compiler.parser.generator.java;
2
3 import gnu.trove.set.hash.THashSet;
4
5 import java.io.File;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.PrintStream;
9 import java.util.Arrays;
10 import java.util.regex.Matcher;
11 import java.util.regex.Pattern;
12
13 import org.simantics.scl.compiler.parser.generator.compression.CompressedParseTable;
14 import org.simantics.scl.compiler.parser.generator.grammar.AnaGrammar;
15 import org.simantics.scl.compiler.parser.generator.grammar.Prod;
16
17 public class GenerateParser {
18
19     String packageName;
20     String className;
21     String exceptionName;
22     AnaGrammar grammar;
23     CompressedParseTable table;
24     
25     public GenerateParser(String packageName, String className,
26             AnaGrammar grammar, String exceptionName, CompressedParseTable table) {
27         this.packageName = packageName;
28         this.className = className;
29         this.grammar = grammar;
30         this.exceptionName = exceptionName;
31         this.table = table;
32     }
33
34     private String readTemplate() throws IOException {
35         InputStream stream = getClass().getResourceAsStream("Parser.java.template");
36         byte[] buffer = new byte[10000];
37         int pos = 0;
38         while(true) {
39             int c = stream.read(buffer, pos, buffer.length-pos);
40             if(c <= 0)
41                 break;
42             pos += c;
43             if(pos == buffer.length)
44                 buffer = Arrays.copyOf(buffer, buffer.length*2);
45         }
46         return new String(buffer, 0, pos, "UTF-8");
47     }
48     
49     private static final Pattern PATTERN = Pattern.compile("\\$[A-Za-z0-9]+\\$");
50     
51     public void generate(File file) throws IOException {
52         PrintStream out = new PrintStream(file, "UTF-8");
53         
54         int aPos = 0;
55         String template = readTemplate();
56         Matcher matcher = PATTERN.matcher(template);
57         while(matcher.find()) {
58             int start = matcher.start();
59             int end = matcher.end();
60             out.print(template.substring(aPos, start));
61             String varName = template.substring(start+1, end-1);
62             generateVar(out, varName);
63             aPos = end;
64         }
65         out.print(template.substring(aPos));
66         
67         out.close();
68     }
69     
70     private void generateVar(PrintStream out, String varName) {
71         if("package".equals(varName)) {
72             out.print(packageName);
73         }
74         else if("class".equals(varName)) {
75             out.print(className);
76         }
77         else if("terminalCount".equals(varName)) {
78             out.print(grammar.terminalNames.length);
79         }
80         else if("nonterminalCount".equals(varName)) {
81             out.print(grammar.nonterminalNames.length);
82         }
83         else if("productCount".equals(varName)) {
84             out.print(grammar.prods.size());
85         }
86         else if("stateCount".equals(varName)) {
87             out.print(table.actionTable.rowIndex.length);
88         }
89         else if("parseMethods".equals(varName)) {
90             for(int i=0;i<grammar.initialNonterminals.length;++i) {
91                 String ntName = grammar.getName(grammar.initialNonterminals[i]);
92                 ntName = ntName.substring(0, 1).toUpperCase() + ntName.substring(1);
93                 out.println("    public Object parse" + ntName + "() {");
94                 out.println("        return parse(" + table.initialStates[i] + ");");
95                 out.println("    }");
96             }
97         }
98         else if("terminalNames".equals(varName)) {
99             for(int i=0;i<grammar.terminalNames.length;++i) {
100                 if(i > 0)
101                     out.println(",");
102                 out.print("        \"" + grammar.terminalNames[i] + "\"");
103             }
104         }
105         else if("nonterminalNames".equals(varName)) {
106             for(int i=0;i<grammar.nonterminalNames.length;++i) {
107                 if(i > 0)
108                     out.println(",");
109                 out.print("        \"" + grammar.nonterminalNames[i] + "\"");
110             }
111         }
112         else if("stateDescriptions".equals(varName)) {
113             for(int i=0;i<table.stateDescriptions.length;++i) {
114                 if(i > 0)
115                     out.println(",");
116                 out.print("        \"" + table.stateDescriptions[i].replace("\n", "\\n") + "\"");
117             }
118         }
119         else if("reduceCases".equals(varName)) {
120             for(int i=0;i<grammar.prods.size();++i) {
121                 Prod prod = grammar.prods.get(i);
122                 if(grammar.nonterminalNames[prod.lhs].startsWith("init$"))
123                     continue;
124                 out.println("        case " + i + ":");
125                 out.println("            return reduce" + prod.name + "();");
126             }
127         }    
128         else if("reduceDelegates".equals(varName)) {
129             for(int i=0;i<grammar.prods.size();++i) {
130                 Prod prod = grammar.prods.get(i);
131                 if(grammar.nonterminalNames[prod.lhs].startsWith("init$"))
132                     out.println("        null,");
133                 else {
134                     out.println("        new ReduceDelegate() {");
135                     out.println("            public Object reduce(" + className + " parser) {");
136                     out.println("                return parser.reduce" + prod.name + "();");
137                     out.println("            }");
138                     out.println("        },");
139                 }
140             }
141         }  
142         else if("reduceMethods".equals(varName)) {
143             THashSet<String> usedNames = new THashSet<String>();
144             for(int i=0;i<grammar.prods.size();++i) {
145                 Prod prod = grammar.prods.get(i);
146                 if(grammar.nonterminalNames[prod.lhs].startsWith("init$"))
147                     continue;
148                 if(usedNames.add(prod.name)) {
149                     out.println("    /**");
150                     out.println("     * " + prod.toString(grammar).replace("*", "&#42;"));
151                     out.println("     */");
152                     out.println("    protected abstract Object reduce" + prod.name + "();");
153                 }
154             }
155         }
156         else if("Token".equals(varName)) {
157             out.print("Token");
158         }
159         else if("Symbol".equals(varName)) {
160             out.print("Object");
161         }
162         else if("tokenId".equals(varName)) {
163             out.print("id");
164         }
165         else if("imports".equals(varName)) {
166             out.println("import org.simantics.scl.compiler.internal.parsing.Token;");
167         }
168         else if("actionTableLength".equals(varName)) {
169             out.print(table.actionTable.table.length);
170         }
171         else if("gotoTableLength".equals(varName)) {
172             out.print(table.gotoTable.table.length);
173         }
174         else if("errorTableLength".equals(varName)) {
175             out.print(table.errorTable.length);
176         }
177         else if("Exception".equals(varName)) {
178             out.print(exceptionName);
179         }
180     }
181
182 }