/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 org.sablecc.sablecc.analysis.*; import org.sablecc.sablecc.node.*; import java.util.Set; import java.util.TreeSet; @SuppressWarnings({"rawtypes", "unchecked"}) public class ConstructNFA extends DepthFirstAdapter { private ResolveIds ids; private String stateName; // private int i; ConstructNFA(ResolveIds ids, String stateName) { this.ids = ids; this.stateName = stateName; } @Override public void outStart(Start node) { setOut(node, getOut(node.getPGrammar())); // free memory if (getOut(node.getPGrammar()) != null) setOut(node.getPGrammar(), null); } @Override public void outAGrammar(AGrammar node) { setOut(node, getOut(node.getTokens())); // free memory if (getOut(node.getTokens()) != null) setOut(node.getTokens(), null); } @Override public void outAHelperDef(AHelperDef node) { setOut(node, getOut(node.getRegExp())); // free memory if (getOut(node.getRegExp()) != null) setOut(node.getRegExp(), null); } @Override public void outATokens(ATokens node) { ATokenDef[] tokenDefs = (ATokenDef[]) node.getTokenDefs().toArray(new ATokenDef[0]); NFA result = null; for (int i = tokenDefs.length - 1; i >= 0; i--) { NFA nfa = (NFA) getOut(tokenDefs[i]); if (nfa != null) { if (result == null) { result = nfa; } else { result = nfa.merge(result); } // free memory if (getOut(tokenDefs[i]) != null) setOut(tokenDefs[i], null); } } if (result != null) setOut(node, result); } @Override public void outATokenDef(ATokenDef node) { Set set = (Set) getOut(node.getStateList()); Object o1 = getOut(node.getRegExp()); if ((set == null) || (set.size() == 0) || set.contains(stateName)) { //System.out.print("*"); NFA n1 = (o1 instanceof NFA) ? (NFA) o1 : new NFA((CharSet) o1); String name = (String) ids.names.get(node); n1.states[n1.states.length - 1].accept = name; setOut(node, n1); } else { //System.out.print("-"); } // free memory if (getOut(node.getStateList()) != null) setOut(node.getStateList(), null); if (getOut(node.getRegExp()) != null) setOut(node.getRegExp(), null); } @Override public void outAStateList(AStateList node) { Set set = new TreeSet(); AStateListTail[] stateListTails = (AStateListTail[]) node.getStateLists().toArray(new AStateListTail[0]); for (int i = stateListTails.length - 1; i >= 0; i--) { String str = stateListTails[i].getId().getText().toUpperCase(); set.add(str); } set.add(node.getId().getText().toUpperCase()); setOut(node, set ); } @Override public void outARegExp(ARegExp node) { AConcat[] concats = (AConcat[]) node.getConcats().toArray(new AConcat[0]); NFA result = null; if (concats.length > 1) { for (int i = concats.length - 1; i >= 0; i--) { Object o = getOut(concats[i]); NFA nfa = (o instanceof NFA) ? (NFA) o : new NFA((CharSet) o); if (result == null) { result = nfa; } else { result = nfa.alternate(result); } // free memory if (getOut(concats[i]) != null) setOut(concats[i], null); } setOut(node, result); } else if (concats.length == 1) { setOut(node, getOut(concats[0])); // free memory if (getOut(concats[0]) != null) setOut(concats[0], null); } } @Override public void outAConcat(AConcat node) { AUnExp[] unExps = (AUnExp[]) node.getUnExps().toArray(new AUnExp[0]); if (unExps.length == 0) { setOut(node, new NFA()); } else if (unExps.length == 1) { setOut(node, getOut(unExps[0])); // free memory if (getOut(unExps[0]) != null) setOut(unExps[0], null); } else { NFA result = null; for (int i = unExps.length - 1; i >= 0; i--) { Object o = getOut(unExps[i]); NFA nfa = (o instanceof NFA) ? (NFA) o : new NFA((CharSet) o); if (result == null) { result = nfa; } else { result = nfa.concatenate(result); } // free memory if (getOut(unExps[i]) != null) setOut(unExps[i], null); } setOut(node, result); } } @Override public void outAUnExp(AUnExp node) { Object o = getOut(node.getBasic()); char c = ' '; if (node.getUnOp() != null) c = ((Character) getOut(node.getUnOp())).charValue(); switch (c) { case '*': { NFA n = (o instanceof NFA) ? (NFA) o : new NFA((CharSet) o); setOut(node, n.zeroOrMore()); } break; case '?': { NFA n = (o instanceof NFA) ? (NFA) o : new NFA((CharSet) o); setOut(node, n.zeroOrOne()); } break; case '+': { NFA n = (o instanceof NFA) ? (NFA) o : new NFA((CharSet) o); setOut(node, n.oneOrMore()); } break; default: { setOut(node, o); } break; } // free memory if (getOut(node.getBasic()) != null) setOut(node.getBasic(), null); if (getOut(node.getUnOp()) != null) setOut(node.getUnOp(), null); } @Override public void outACharBasic(ACharBasic node) { char c = ((Character) getOut(node.getChar())).charValue(); setOut(node, new CharSet(c)); // free memory if (getOut(node.getChar()) != null) setOut(node.getChar(), null); } @Override public void outASetBasic(ASetBasic node) { setOut(node, getOut(node.getSet())); // free memory if (getOut(node.getSet()) != null) setOut(node.getSet(), null); } @Override public void outAStringBasic(AStringBasic node) { String s = node.getString().getText(); s = s.substring(1, s.length() - 1); setOut(node, new NFA(s)); } @Override public void outAIdBasic(AIdBasic node) { Object o = getOut((Node) ids.helpers.get(node.getId().getText())); if (o instanceof NFA) { setOut(node, ((NFA) o).clone()); } else { setOut(node, ((CharSet) o).clone()); } } @Override public void outARegExpBasic(ARegExpBasic node) { setOut(node, getOut(node.getRegExp())); // free memory if (getOut(node.getRegExp()) != null) setOut(node.getRegExp(), null); } @Override public void outACharChar(ACharChar node) { setOut(node, new Character(node.getChar().getText().charAt(1))); } @Override public void outADecChar(ADecChar node) { setOut(node, new Character((char) Integer.parseInt(node.getDecChar().getText()))); } @Override public void outAHexChar(AHexChar node) { setOut(node, new Character((char) Integer.parseInt(node.getHexChar().getText().substring(2), 16))); } @Override public void outAOperationSet(AOperationSet node) { try { CharSet cs1 = (CharSet) getOut(node.getLeft()); CharSet cs2 = (CharSet) getOut(node.getRight()); char binop = ((Character) getOut(node.getBinOp())).charValue(); switch (binop) { case '+': { setOut(node, cs1.union(cs2)); } break; case '-': { setOut(node, cs1.diff(cs2)); } break; } } catch (Exception e) { throw new RuntimeException(node + " is invalid."); } // free memory if (getOut(node.getLeft()) != null) setOut(node.getLeft(), null); if (getOut(node.getBinOp()) != null) setOut(node.getBinOp(), null); if (getOut(node.getRight()) != null) setOut(node.getRight(), null); } @Override public void outAIntervalSet(AIntervalSet node) { char c1 = ((Character) getOut(node.getLeft())).charValue(); char c2 = ((Character) getOut(node.getRight())).charValue(); if (c1 > c2) { throw new RuntimeException(node + " is invalid."); } setOut(node, new CharSet(c1, c2)); // free memory if (getOut(node.getLeft()) != null) setOut(node.getLeft(), null); if (getOut(node.getRight()) != null) setOut(node.getRight(), null); } @Override public void outAStarUnOp(AStarUnOp node) { setOut(node, new Character('*')); } @Override public void outAQMarkUnOp(AQMarkUnOp node) { setOut(node, new Character('?')); } @Override public void outAPlusUnOp(APlusUnOp node) { setOut(node, new Character('+')); } @Override public void outAPlusBinOp(APlusBinOp node) { setOut(node, new Character('+')); } @Override public void outAMinusBinOp(AMinusBinOp node) { setOut(node, new Character('-')); } @Override public Object getOut(Node node) { if (node == null) { return null; } return super.getOut(node); } @Override public void setOut(Node node, Object out) { if (node == null) { throw new NullPointerException(); } super.setOut(node, out); } }