1 package org.simantics.scl.compiler.parser.generator.java;
3 import gnu.trove.set.hash.THashSet;
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;
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;
17 public class GenerateParser {
23 CompressedParseTable table;
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;
34 private String readTemplate() throws IOException {
35 InputStream stream = getClass().getResourceAsStream("Parser.java.template");
36 byte[] buffer = new byte[10000];
39 int c = stream.read(buffer, pos, buffer.length-pos);
43 if(pos == buffer.length)
44 buffer = Arrays.copyOf(buffer, buffer.length*2);
46 return new String(buffer, 0, pos, "UTF-8");
49 private static final Pattern PATTERN = Pattern.compile("\\$[A-Za-z0-9]+\\$");
51 public void generate(File file) throws IOException {
52 PrintStream out = new PrintStream(file, "UTF-8");
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);
65 out.print(template.substring(aPos));
70 private void generateVar(PrintStream out, String varName) {
71 if("package".equals(varName)) {
72 out.print(packageName);
74 else if("class".equals(varName)) {
77 else if("terminalCount".equals(varName)) {
78 out.print(grammar.terminalNames.length);
80 else if("nonterminalCount".equals(varName)) {
81 out.print(grammar.nonterminalNames.length);
83 else if("productCount".equals(varName)) {
84 out.print(grammar.prods.size());
86 else if("stateCount".equals(varName)) {
87 out.print(table.actionTable.rowIndex.length);
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] + ");");
98 else if("terminalNames".equals(varName)) {
99 for(int i=0;i<grammar.terminalNames.length;++i) {
102 out.print(" \"" + grammar.terminalNames[i] + "\"");
105 else if("nonterminalNames".equals(varName)) {
106 for(int i=0;i<grammar.nonterminalNames.length;++i) {
109 out.print(" \"" + grammar.nonterminalNames[i] + "\"");
112 else if("stateDescriptions".equals(varName)) {
113 for(int i=0;i<table.stateDescriptions.length;++i) {
116 out.print(" \"" + table.stateDescriptions[i].replace("\n", "\\n") + "\"");
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$"))
124 out.println(" case " + i + ":");
125 out.println(" return reduce" + prod.name + "();");
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,");
134 out.println(" new ReduceDelegate() {");
135 out.println(" public Object reduce(" + className + " parser) {");
136 out.println(" return parser.reduce" + prod.name + "();");
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$"))
148 if(usedNames.add(prod.name)) {
150 out.println(" * " + prod.toString(grammar).replace("*", "*"));
152 out.println(" protected abstract Object reduce" + prod.name + "();");
156 else if("Token".equals(varName)) {
159 else if("Symbol".equals(varName)) {
162 else if("tokenId".equals(varName)) {
165 else if("imports".equals(varName)) {
166 out.println("import org.simantics.scl.compiler.internal.parsing.Token;");
168 else if("actionTableLength".equals(varName)) {
169 out.print(table.actionTable.table.length);
171 else if("gotoTableLength".equals(varName)) {
172 out.print(table.gotoTable.table.length);
174 else if("errorTableLength".equals(varName)) {
175 out.print(table.errorTable.length);
177 else if("Exception".equals(varName)) {
178 out.print(exceptionName);