📄 parser.java
字号:
package murlen.util.fscriptME;import java.util.Hashtable;import java.util.Vector;import java.lang.*;/** * <b>Parser - Does the parsing - i.e it's the brains of the code.</b> * <p> * <I>Copyright (C) 2002 murlen.</I></p> * <p> * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version.</p> * <p> * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details.</p> * <p> * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc.,59 Temple Place, Suite 330, Boston MA 0211-1307 USA * </p> * @author murlen * @version 0.5 * ** modifications by Joachim Van der Auwera * 14.08.2001 added support for indexed variables * 20.08.2001 -clean handling of setVar with null value * - cleaner handling of if with null condition * - make sure running empty script does nothing * - extra info when throwing an exception (with surrounding lines) * - changed operator prioritues for && and || * - fixed bug in parseIf with handling of nesting of if clauses with else * - check for missing endif or endwhile (caused infinit loops) * - check for a null to prevernt excepion in parseExpr * 28.08.2001 * - call to host.getVar() replaced by host.getVarEntry() (and added * proper exception handling, in that case) * 31.08.2001 * - test on if condition being of correct type re-introduced * 10.09.2001 * - added < <= > >= on strings */class Parser { //simple data class used internally to store function defs class FuncEntry { int startLine; //start line of function int endLine; //end line of function Vector paramNames; //list of parameter names Hashtable params; //Hashtable of parameters public FuncEntry() { startLine=0; endLine=0; paramNames=new Vector(4); params=new Hashtable(); } public String toString() { String s=new String(); s=startLine + " " ; s=s+endLine + " "; s=s+paramNames + " "; s=s+params; return s; } } //exception that occurs when someone calls return class RetException extends Exception {} private LineLoader code; //the code private LexAnn tok; //tokenizer private int maxLine; private Hashtable vars; //function local variables private Hashtable gVars; //global variables private static Hashtable opPrio; //operator priority table private FScript host; //link to hosting FScript object private Hashtable funcs; //function map private Object retVal; //return value private String error[]; /** Public constructor * @param h a reference to the FScript object */ Parser(FScript h) { vars=new Hashtable(); gVars=null; funcs=new Hashtable(); host=h; setPrio(); } //only used for function calls - note it is private private Parser(FScript h,Hashtable l,Hashtable g, Hashtable f) { vars=l; gVars=g; funcs=f; host=h; } /** * Sets the LineLoader clas to be used for input * @param in - the class */ void setCode(LineLoader in) { code=in; } /** *The main parsing function *@param from - the start line number *@param to - the end line number *returns an Object (currently a Integer or String) depending *on the return value of the code parsed, or null if none. */ Object parse(int from,int to) throws FSException { // nothing to do when starting beond the code end if (code.lineCount()<=from) return null; maxLine=to; code.setCurLine(from); tok=new LexAnn(code.getLine()); checkLine(code.getLine()); getNextToken(); while (tok.ttype!=LexAnn.TT_EOF) { //a script must always start with a word... try { parseStmt(); } catch (RetException e) { return retVal; } getNextToken(); } return null; } /** * Resets the parser state. */ void reset(){ if (vars!=null){ vars.clear(); } if (gVars!=null){ gVars.clear(); } } //builds the operator priority table private void setPrio(){ if (opPrio==null){ opPrio=new Hashtable(); //from low to high opPrio.put(new Integer(LexAnn.TT_LOR),new Integer(1)); opPrio.put(new Integer(LexAnn.TT_LAND),new Integer(2)); opPrio.put(new Integer(LexAnn.TT_LEQ),new Integer(5)); opPrio.put(new Integer(LexAnn.TT_LNEQ),new Integer(5)); opPrio.put(new Integer(LexAnn.TT_LGR),new Integer(5)); opPrio.put(new Integer(LexAnn.TT_LGRE),new Integer(5)); opPrio.put(new Integer(LexAnn.TT_LLS),new Integer(5)); opPrio.put(new Integer(LexAnn.TT_LLSE),new Integer(5)); opPrio.put(new Integer(LexAnn.TT_PLUS),new Integer(10)); opPrio.put(new Integer(LexAnn.TT_MINUS),new Integer(10)); opPrio.put(new Integer(LexAnn.TT_MULT),new Integer(20)); opPrio.put(new Integer(LexAnn.TT_DIV),new Integer(20)); opPrio.put(new Integer(LexAnn.TT_MOD),new Integer(20)); } } //statement - top level thing private void parseStmt() throws FSException,RetException { switch(tok.ttype) { case LexAnn.TT_IF: case LexAnn.TT_EIF: case LexAnn.TT_WHILE: case LexAnn.TT_EWHILE: case LexAnn.TT_DEFINT: case LexAnn.TT_DEFSTRING: case LexAnn.TT_DEFFUNC: case LexAnn.TT_EDEFFUNC: case LexAnn.TT_RETURN: { parseKeyWord(); break; } case LexAnn.TT_FUNC: { parseFunc(); break; } case LexAnn.TT_ARRAY: { parseArrayAssign(); break; } case LexAnn.TT_WORD: { parseAssign(); break; } case LexAnn.TT_EOL: { tok.nextToken(); break; } case LexAnn.TT_EOF:{ //all done break; } default: { parseError("Expected identifier"); } } } private void parseFunc() throws FSException,RetException { String name; name=(String)tok.value; //should be a '(' getNextToken(); parseCallFunc(name); getNextToken(); } private void parseArrayAssign() throws FSException,RetException { String name; Object index; Object val; name=(String)tok.value; getNextToken(); // should be a '[' getNextToken(); // should be the index index=parseExpr(); getNextToken(); // should be a ']' //getNextToken(); if (tok.ttype!=LexAnn.TT_EQ) { parseError("Expected '='" ); } else { getNextToken(); val=parseExpr(); try { host.setVar(name,index,val); } catch (Exception e) { parseError(e.getMessage()); } } } private void parseKeyWord() throws FSException,RetException { switch (tok.ttype) { case LexAnn.TT_DEFINT: case LexAnn.TT_DEFSTRING: case LexAnn.TT_DEFDOUBLE: { parseVarDef(); break; } case LexAnn.TT_IF: { parseIf(); break; } case LexAnn.TT_WHILE: { parseWhile(); break; } case LexAnn.TT_RETURN: { parseReturn(); break; } case LexAnn.TT_DEFFUNC: { parseFunctionDef(); break; } default: { //we never get here parseError("Not a keyword"); } } } //handles 'return' statements private void parseReturn() throws FSException,RetException { getNextToken(); retVal=parseExpr(); throw new RetException(); } //Asignment parser private void parseAssign() throws FSException { String name; Object val; name=(String)tok.value; getNextToken(); if (tok.ttype!=LexAnn.TT_EQ) { parseError("Expected '='" ); } else { getNextToken(); val=parseExpr(); if (hasVar(name)) { setVar(name,val); } else { try { host.setVar(name,null,val); } catch (Exception e) { parseError(e.getMessage()); } } } } //Handles function execution Object callFunction(String name,Vector params) throws FSException{ FuncEntry fDef; int n; int oldLine; Object val; val=null; //Check we have a definition for the function if (funcs.containsKey(name)) { fDef=(FuncEntry)funcs.get(name); //Check params and def match
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -