genparser.java

来自「有关编译器的编译器.」· Java 代码 · 共 894 行 · 第 1/2 页

JAVA
894
字号
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This file is part of SableCC.                             * * See the file "LICENSE" for copyright information and the  * * terms and conditions for copying, distribution and        * * modification of SableCC.                                  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */package org.sablecc.sablecc;import java.util.*;import org.sablecc.sablecc.analysis.*;import org.sablecc.sablecc.node.*;import java.io.*;import org.sablecc.sablecc.Grammar;import java.util.Vector;import java.util.Enumeration;public class GenParser extends DepthFirstAdapter{  private MacroExpander macros;  private ResolveIds ids;  private File pkgDir;  private String pkgName;  private String currentProd;  private int currentAlt;  private boolean hasProductions;  static final int NONE = 0;  static final int STAR = 1;  static final int QMARK = 2;  static final int PLUS = 3;  int count;  int elem;  Map alts = new TypedTreeMap(               StringComparator.instance,               StringCast.instance,               NodeCast.instance);  public GenParser(ResolveIds ids)  {    this.ids = ids;    try    {      macros = new MacroExpander(                 new InputStreamReader(                   getClass().getResourceAsStream("parser.txt")));    }    catch(IOException e)    {      throw new RuntimeException("unable to open parser.txt.");    }    pkgDir = new File(ids.pkgDir, "parser");    pkgName = ids.pkgName.equals("") ? "parser" : ids.pkgName + ".parser";    if(!pkgDir.exists())    {      if(!pkgDir.mkdir())      {        throw new RuntimeException("Unable to create " + pkgDir.getAbsolutePath());      }    }  }  public void caseStart(Start tree)  {    tree.apply(new DepthFirstAdapter()               {                 private boolean hasAlternative;                 public void caseATokenDef(ATokenDef node)                 {                   String name = (String) ids.names.get(node);                   String errorName = (String) ids.errorNames.get(node);                   if(!ids.ignTokens.containsKey(name))                   {                     Grammar.addTerminal(name, errorName);                   }                 }                 public void inAProd(AProd node)                 {                   hasAlternative = false;                 }                 public void inAParsedAlt(AParsedAlt node)                 {                   hasAlternative = true;                 }                 public void outAProd(AProd node)                 {                   if(hasAlternative)                   {                     Grammar.addNonterminal((String) ids.names.get(node));                   }                 }               }              );    tree.getPGrammar().apply(this);    if(!hasProductions)    {      return;    }    Grammar.computeLALR();    createParser();    createParserException();    createState();    createTokenIndex();  }  public void inAProd(AProd node)  {    hasProductions = true;    currentProd = (String) ids.names.get(node);  }  public void caseAParsedAlt(AParsedAlt node)  {    count = 1;    node.apply(new DepthFirstAdapter()               {                 public void inAElem(AElem node)                 {                   GenParser.this.setOut(node, new Integer(NONE));                 }                 public void caseAStarUnOp(AStarUnOp node)                 {                   count *= 2;                   GenParser.this.setOut(node.parent(), new Integer(STAR));                 }                 public void caseAQMarkUnOp(AQMarkUnOp node)                 {                   count *= 2;                   GenParser.this.setOut(node.parent(), new Integer(QMARK));                 }                 public void caseAPlusUnOp(APlusUnOp node)                 {                   GenParser.this.setOut(node.parent(), new Integer(PLUS));                 }               }              );    if(count == 1)    {      alts.put(ids.names.get(node), node);      currentAlt = Grammar.addProduction(currentProd, (String) ids.names.get(node));      {        Object temp[] = node.getElems().toArray();        for(int i = 0; i < temp.length; i++)        {          ((PElem) temp[i]).apply(this);        }      }    }    else    {      int max = count;      for(count = 0; count < max; count++)      {        elem = 0;        alts.put(          "X" + (count + 1) + (String) ids.names.get(node),          node);        currentAlt = Grammar.addProduction(currentProd,                                           "X" + (count + 1) + (String) ids.names.get(node));        {          Object temp[] = node.getElems().toArray();          for(int i = 0; i < temp.length; i++)          {            ((PElem) temp[i]).apply(this);          }        }      }    }  }  public void caseAElem(AElem node)  {    int op = ((Integer) getOut(node)).intValue();    String name = (String) ids.elemTypes.get(node);    switch(op)    {    case NONE:      {        Grammar.addSymbolToProduction(name, currentAlt);      }      break;    case STAR:      {        //                System.out.println("Star:" + count + ", " + (1 << elem));        if((count & (1 << elem)) != 0)        {          //                    System.out.println("yes");          try          {            Grammar.addNonterminal("X" + name);            int alt = Grammar.addProduction("X" + name, "X1" + name);            Grammar.addSymbolToProduction("X" + name, alt);            Grammar.addSymbolToProduction(name, alt);            alt = Grammar.addProduction("X" + name, "X2" + name);            Grammar.addSymbolToProduction(name, alt);          }          catch(Exception e)          {}          Grammar.addSymbolToProduction("X" + name, currentAlt);        }        elem++;      }      break;    case QMARK:      {        if((count & (1 << elem)) != 0)        {          Grammar.addSymbolToProduction(name, currentAlt);        }        elem++;      }      break;    case PLUS:      {        try        {          Grammar.addNonterminal("X" + name);          int alt = Grammar.addProduction("X" + name, "X1" + name);          Grammar.addSymbolToProduction("X" + name, alt);          Grammar.addSymbolToProduction(name, alt);          alt = Grammar.addProduction("X" + name, "X2" + name);          Grammar.addSymbolToProduction(name, alt);        }        catch(Exception e)        {}        Grammar.addSymbolToProduction("X" + name, currentAlt);      }      break;    }  }  public void caseAIgnoredAlt(AIgnoredAlt node)  {}  private void createParser()  {    BufferedWriter file;    try    {      file = new BufferedWriter(               new FileWriter(                 new File(pkgDir, "Parser.java")));    }    catch(IOException e)    {      throw new RuntimeException("Unable to create " + new File(pkgDir, "Parser.java").getAbsolutePath());    }    try    {      Symbol[] terminals = Symbol.terminals();      Symbol[] nonterminals = Symbol.nonterminals();      Production[] productions = Production.productions();      macros.apply(file, "ParserHeader", new String[] {pkgName,                   ids.pkgName.equals("") ? "lexer" : ids.pkgName + ".lexer",                   ids.pkgName.equals("") ? "node" : ids.pkgName + ".node",                   ids.pkgName.equals("") ? "analysis" : ids.pkgName + ".analysis"});      for(int i = 0; i < (productions.length - 1); i++)      {        Node node = (Node) alts.get(productions[i].name);        if(node == null)        {          macros.apply(file, "ParserReduceNoFilter", new String[] {                         "" + productions[i].index,                         "" + productions[i].leftside});        }        else        {          macros.apply(file, "ParserReduceFilter", new String[] {                         "" + productions[i].index,                         "" + productions[i].leftside});        }      }      {        Symbol[] rightside = productions[productions.length - 1].rightside();        macros.apply(file, "ParserParseTail", new String[] {rightside[0].name});      }      for(int i = 0; i < (productions.length - 1); i++)      {        macros.apply(file, "ParserNewHeader",                     new String[] {"" + productions[i].index});        Node node = (Node) alts.get(productions[i].name);        if(node == null)        {          Symbol[] rightside = productions[i].rightside();          for(int k = rightside.length - 1; k >= 0; k--)          {            macros.apply(file, "ParserNewBodyDecl",                         new String[] {rightside[k].name, "" + (k + 1)});          }          macros.apply(file, "ParserNewBodyNew",                       new String[] {productions[i].name});          for(int k = 0; k < rightside.length; k++)          {            macros.apply(file, "ParserNewBodyParams",                         new String[] {(k == 0) ? "" : ", ",                                       (k + 1) + ""});          }          macros.apply(file, "ParserNewTail", new String[] { "" + productions[i].leftside});        }        else        {          count = count(productions[i].name) - 1;          elem = 0;          final BufferedWriter finalFile = file;          final LinkedList stack = new LinkedList();          node.apply(new DepthFirstAdapter()                     {                       private int current;                       public void caseAElem(AElem node)                       {                         int op = ((Integer) GenParser.this.getOut(node)).intValue();                         String name = (String) ids.elemTypes.get(node);                         current++;                         switch(op)                         {                         case NONE:                           {                             stack.addFirst(new Element("ParserNewBodyDecl",                                                        new String[] {name, "" + current}));                           }                           break;                         case STAR:                           {                             if((count & (1 << elem)) != 0)                             {                               stack.addFirst(new Element("ParserNewBodyDecl",                                                          new String[] {"X" + name, "" + current}));                             }                             else                             {                               stack.addFirst(new Element("ParserNewBodyDeclNull",                                                          new String[] {"X" + name, "" + current}));                             }                             elem++;                           }                           break;                         case QMARK:                           {                             if((count & (1 << elem)) != 0)                             {                               stack.addFirst(new Element("ParserNewBodyDecl",                                                          new String[] {name, "" + current}));                             }                             else                             {                               stack.addFirst(new Element("ParserNewBodyDeclNull",                                                          new String[] {name, "" + current}));                             }                             elem++;                           }                           break;                         case PLUS:                           {                             stack.addFirst(new Element("ParserNewBodyDecl",                                                        new String[] {"X" + name, "" + current}));                           }                           break;                         }                       }                     }                    );          try          {            for(Iterator it = stack.iterator(); it.hasNext();)            {              Element e = (Element) it.next();              macros.apply(file, e.macro, e.arguments);            }          }          catch(IOException e)          {            throw new RuntimeException("An error occured while writing to " +                                       new File(pkgDir, "Parser.java").getAbsolutePath());          }          macros.apply(file, "ParserNewBodyNew",                       new String[] {                         (node == null) ? productions[i].name : name(productions[i].name)});          node.apply(new DepthFirstAdapter()                     {                       private int current;                       public void caseAElem(AElem node)                       {                         try                         {                           String name = (String) ids.elemTypes.get(node);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?