]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/parser/generator/java/GenerateParser.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/parser/generator/java/GenerateParser.java
new file mode 100644 (file)
index 0000000..1b7df54
--- /dev/null
@@ -0,0 +1,182 @@
+package org.simantics.scl.compiler.parser.generator.java;
+
+import gnu.trove.set.hash.THashSet;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.simantics.scl.compiler.parser.generator.compression.CompressedParseTable;
+import org.simantics.scl.compiler.parser.generator.grammar.AnaGrammar;
+import org.simantics.scl.compiler.parser.generator.grammar.Prod;
+
+public class GenerateParser {
+
+    String packageName;
+    String className;
+    String exceptionName;
+    AnaGrammar grammar;
+    CompressedParseTable table;
+    
+    public GenerateParser(String packageName, String className,
+            AnaGrammar grammar, String exceptionName, CompressedParseTable table) {
+        this.packageName = packageName;
+        this.className = className;
+        this.grammar = grammar;
+        this.exceptionName = exceptionName;
+        this.table = table;
+    }
+
+    private String readTemplate() throws IOException {
+        InputStream stream = getClass().getResourceAsStream("Parser.java.template");
+        byte[] buffer = new byte[10000];
+        int pos = 0;
+        while(true) {
+            int c = stream.read(buffer, pos, buffer.length-pos);
+            if(c <= 0)
+                break;
+            pos += c;
+            if(pos == buffer.length)
+                buffer = Arrays.copyOf(buffer, buffer.length*2);
+        }
+        return new String(buffer, 0, pos, "UTF-8");
+    }
+    
+    private static final Pattern PATTERN = Pattern.compile("\\$[A-Za-z0-9]+\\$");
+    
+    public void generate(File file) throws IOException {
+        PrintStream out = new PrintStream(file, "UTF-8");
+        
+        int aPos = 0;
+        String template = readTemplate();
+        Matcher matcher = PATTERN.matcher(template);
+        while(matcher.find()) {
+            int start = matcher.start();
+            int end = matcher.end();
+            out.print(template.substring(aPos, start));
+            String varName = template.substring(start+1, end-1);
+            generateVar(out, varName);
+            aPos = end;
+        }
+        out.print(template.substring(aPos));
+        
+        out.close();
+    }
+    
+    private void generateVar(PrintStream out, String varName) {
+        if("package".equals(varName)) {
+            out.print(packageName);
+        }
+        else if("class".equals(varName)) {
+            out.print(className);
+        }
+        else if("terminalCount".equals(varName)) {
+            out.print(grammar.terminalNames.length);
+        }
+        else if("nonterminalCount".equals(varName)) {
+            out.print(grammar.nonterminalNames.length);
+        }
+        else if("productCount".equals(varName)) {
+            out.print(grammar.prods.size());
+        }
+        else if("stateCount".equals(varName)) {
+            out.print(table.actionTable.rowIndex.length);
+        }
+        else if("parseMethods".equals(varName)) {
+            for(int i=0;i<grammar.initialNonterminals.length;++i) {
+                String ntName = grammar.getName(grammar.initialNonterminals[i]);
+                ntName = ntName.substring(0, 1).toUpperCase() + ntName.substring(1);
+                out.println("    public Object parse" + ntName + "() {");
+                out.println("        return parse(" + table.initialStates[i] + ");");
+                out.println("    }");
+            }
+        }
+        else if("terminalNames".equals(varName)) {
+            for(int i=0;i<grammar.terminalNames.length;++i) {
+                if(i > 0)
+                    out.println(",");
+                out.print("        \"" + grammar.terminalNames[i] + "\"");
+            }
+        }
+        else if("nonterminalNames".equals(varName)) {
+            for(int i=0;i<grammar.nonterminalNames.length;++i) {
+                if(i > 0)
+                    out.println(",");
+                out.print("        \"" + grammar.nonterminalNames[i] + "\"");
+            }
+        }
+        else if("stateDescriptions".equals(varName)) {
+            for(int i=0;i<table.stateDescriptions.length;++i) {
+                if(i > 0)
+                    out.println(",");
+                out.print("        \"" + table.stateDescriptions[i].replace("\n", "\\n") + "\"");
+            }
+        }
+        else if("reduceCases".equals(varName)) {
+            for(int i=0;i<grammar.prods.size();++i) {
+                Prod prod = grammar.prods.get(i);
+                if(grammar.nonterminalNames[prod.lhs].startsWith("init$"))
+                    continue;
+                out.println("        case " + i + ":");
+                out.println("            return reduce" + prod.name + "();");
+            }
+        }    
+        else if("reduceDelegates".equals(varName)) {
+            for(int i=0;i<grammar.prods.size();++i) {
+                Prod prod = grammar.prods.get(i);
+                if(grammar.nonterminalNames[prod.lhs].startsWith("init$"))
+                    out.println("        null,");
+                else {
+                    out.println("        new ReduceDelegate() {");
+                    out.println("            public Object reduce(" + className + " parser) {");
+                    out.println("                return parser.reduce" + prod.name + "();");
+                    out.println("            }");
+                    out.println("        },");
+                }
+            }
+        }  
+        else if("reduceMethods".equals(varName)) {
+            THashSet<String> usedNames = new THashSet<String>();
+            for(int i=0;i<grammar.prods.size();++i) {
+                Prod prod = grammar.prods.get(i);
+                if(grammar.nonterminalNames[prod.lhs].startsWith("init$"))
+                    continue;
+                if(usedNames.add(prod.name)) {
+                    out.println("    /**");
+                    out.println("     * " + prod.toString(grammar).replace("*", "&#42;"));
+                    out.println("     */");
+                    out.println("    protected abstract Object reduce" + prod.name + "();");
+                }
+            }
+        }
+        else if("Token".equals(varName)) {
+            out.print("Token");
+        }
+        else if("Symbol".equals(varName)) {
+            out.print("Object");
+        }
+        else if("tokenId".equals(varName)) {
+            out.print("id");
+        }
+        else if("imports".equals(varName)) {
+            out.println("import org.simantics.scl.compiler.internal.parsing.Token;");
+        }
+        else if("actionTableLength".equals(varName)) {
+            out.print(table.actionTable.table.length);
+        }
+        else if("gotoTableLength".equals(varName)) {
+            out.print(table.gotoTable.table.length);
+        }
+        else if("errorTableLength".equals(varName)) {
+            out.print(table.errorTable.length);
+        }
+        else if("Exception".equals(varName)) {
+            out.print(exceptionName);
+        }
+    }
+
+}