Source Code Cross Referenced for Parser.java in  » Scripting » FScript » murlen » util » fscript » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » FScript » murlen.util.fscript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package murlen.util.fscript;
0002:
0003:        import java.io.*;
0004:        import java.util.HashMap;
0005:        import java.util.ArrayList;
0006:
0007:        /**
0008:         * <b>Parser - Does the parsing - i.e it's the brains of the code.</b>
0009:         * <p>
0010:         * <I>Copyright (C) 2000-2003 murlen.</I></p>
0011:         * <p>
0012:         * This library is free software; you can redistribute it and/or
0013:         * modify it under the terms of the GNU Library General Public
0014:         * License as published by the Free Software Foundation; either
0015:         * version 2 of the License, or (at your option) any later version.</p>
0016:         * <p>
0017:         * This library is distributed in the hope that it will be useful,
0018:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0019:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0020:         * Library General Public License for more details.</p>
0021:         *
0022:         * <p>You should have received a copy of the GNU Library General Public
0023:         * License along with this library; if not, write to the Free
0024:         * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA </p>
0025:         * @author murlen
0026:         * @author Joachim Van der Auwera
0027:         * @version 1.12
0028:         *
0029:         * modifications by Joachim Van der Auwera
0030:         * 14.08.2001 added support for indexed variables
0031:         * 20.08.2001 -clean handling of setVar with null value
0032:         *   - cleaner handling of if with null condition
0033:         *   - make sure running empty script does nothing
0034:         *   - extra info when throwing an exception (with surrounding lines)
0035:         *   - changed operator prioritues for && and ||
0036:         *   - fixed bug in parseIf with handling of nesting of if clauses with else
0037:         *   - check for missing endif or endwhile (caused infinit loops)
0038:         *   - check for a null to prevernt excepion in parseExpr
0039:         * 28.08.2001
0040:         *   - call to host.getVar() replaced by host.F() (and added
0041:         *     proper exception handling, in that case)
0042:         * 31.08.2001
0043:         *   - test on if condition being of correct type re-introduced
0044:         * 10.09.2001
0045:         *   - added < <= > >= on strings
0046:         * 23.11.2001
0047:         *   - allow adding strings with anything
0048:         * 04.12.2001
0049:         *   - allow add/subtract/multiply/divide int with double
0050:         * 24.04.2002
0051:         *   - fixed a bug in parsing of nested if clause when one of the nested items contains a
0052:         *     "then" token with the statements on the next line(s) (test for TT_EOL instead of TT_EOF)
0053:         * 30.04.2002
0054:         *   - handle all exceptions on all getVarEntry, setVarEntry and callFunctionEntry calls
0055:         * 06.05.2002
0056:         *   - error messages now unique
0057:         *   - TT_EOF handled better in some cases
0058:         * 05-06.08.2002
0059:         *   - removed some redundant code
0060:         *   - introduced parseFunctionEnd to catch functions without return (it worked before, so...)
0061:         * 21.10.2002
0062:         *   - added == for FSObject instances
0063:         * 30.10.2002 object now allowed as function parameter
0064:         * 07.11.2002 better error handling when parsing an expression
0065:         * 20.11.2002 make != work for objects
0066:         * 15.03.2003 getContext() added JVDA
0067:         * 17.09.2003 removed checking for mismatched quotes and brackets, and moved to LineLoader
0068:         * 23.11.2003 recycle LexAnn objects (saves object allocation/release) JVDA
0069:         * 24.11.2003 some extra (smallish) speed improvements (also to reduce garbage a little bit)
0070:         * 25.02.2004
0071:         * - proper evaluation of FSObject with contained boolean/integer for if/while
0072:         * - more powerful compare for FSObject instance with something else
0073:         * 14.04.2004 elsif opperator support
0074:         */
0075:        final class Parser {
0076:            public static final Integer FS_TRUE = new Integer(1);
0077:            public static final Integer FS_FALSE = new Integer(0);
0078:
0079:            //simple data class used internally to store function defs
0080:            class FuncEntry {
0081:                int startLine; //start line of function
0082:                int endLine; //end line of function
0083:                ArrayList paramNames; //list of parameter names
0084:                HashMap params; //hashmap of parameters
0085:
0086:                FuncEntry() {
0087:                    startLine = 0;
0088:                    endLine = 0;
0089:                    paramNames = new ArrayList(4);
0090:                    params = new HashMap();
0091:                }
0092:
0093:                public String toString() {
0094:                    String s;
0095:
0096:                    s = startLine + " ";
0097:                    s = s + endLine + " ";
0098:                    s = s + paramNames + " ";
0099:                    s = s + params;
0100:
0101:                    return s;
0102:                }
0103:            }
0104:
0105:            //exception that occurs when someone calls return
0106:            class RetException extends Exception {
0107:            }
0108:
0109:            private LineLoader code; //the code
0110:            private LexAnn tok; //tokenizer
0111:
0112:            private int maxLine;
0113:            private HashMap vars; //function local variables
0114:            private HashMap gVars; //global variables
0115:            private static HashMap opPrio; //operator priority table
0116:            private FScript host; //link to hosting FScript object
0117:            private HashMap funcs; //function map
0118:            private Object retVal; //return value
0119:
0120:            private Parser subParser; //nested parser, for callback routines in FSParserExtension
0121:
0122:            private String error[];
0123:
0124:            /** Public constructor
0125:             * @param h a reference to the FScript object
0126:             */
0127:            Parser(FScript h) {
0128:                vars = new HashMap();
0129:                gVars = null;
0130:                funcs = new HashMap();
0131:                host = h;
0132:
0133:                setPrio();
0134:            }
0135:
0136:            //only used for function calls - note it is private
0137:            private Parser(FScript h, HashMap l, HashMap g, HashMap f) {
0138:                vars = l;
0139:                gVars = g;
0140:                funcs = f;
0141:                host = h;
0142:            }
0143:
0144:            /**
0145:             * Sets the LineLoader clas to be used for input
0146:             * @param in - the class
0147:             */
0148:            void setCode(LineLoader in) {
0149:                code = in;
0150:            }
0151:
0152:            /**
0153:             *The main parsing function
0154:             *@param from - the start line number
0155:             *@param to - the end line number
0156:             *returns an Object (currently a Integer or String) depending
0157:             *on the return value of the code parsed, or null if none.
0158:             */
0159:            Object parse(int from, int to) throws IOException, FSException {
0160:
0161:                // nothing to do when starting beond the code end
0162:                if (code.lineCount() <= from)
0163:                    return null;
0164:
0165:                maxLine = to;
0166:                code.setCurLine(from);
0167:                tok = new LexAnn(code.getLine());
0168:                getNextToken();
0169:                while (tok.ttype != LexAnn.TT_EOF) {
0170:
0171:                    //a script must always start with a word...
0172:
0173:                    try {
0174:                        parseStmt();
0175:                    } catch (RetException e) {
0176:                        return retVal;
0177:                    }
0178:
0179:                    getNextToken();
0180:                }
0181:
0182:                return null;
0183:
0184:            }
0185:
0186:            /**
0187:             * The main parsing function
0188:             * @param line - the line to be parsed
0189:             * @return an Object depending on the return value of the code parsed, or null if none.
0190:             */
0191:            Object parse(String line) throws IOException, FSException {
0192:                int oldLine = code.curLine;
0193:                try {
0194:                    code.curLine = -1;
0195:                    code.forError = line;
0196:                    char[] chars = line.toCharArray();
0197:                    LineLoader.checkLine(chars);
0198:                    tok = new LexAnn(chars);
0199:                    tok.nextToken();
0200:                    // a script must always start with a word...
0201:                    try {
0202:                        parseStmt();
0203:                    } catch (RetException e) {
0204:                        return retVal;
0205:                    }
0206:                } finally {
0207:                    code.curLine = oldLine;
0208:                }
0209:                return null;
0210:            }
0211:
0212:            /**
0213:             * Resets the parser state.
0214:             */
0215:            void reset() {
0216:                if (vars != null) {
0217:                    vars.clear();
0218:                }
0219:                if (gVars != null) {
0220:                    gVars.clear();
0221:                }
0222:            }
0223:
0224:            //builds the operator priority table
0225:            private void setPrio() {
0226:                if (opPrio == null) {
0227:                    opPrio = new HashMap();
0228:                    //from low to high
0229:                    Integer prio;
0230:                    prio = new Integer(1);
0231:                    opPrio.put(new Integer(LexAnn.TT_LOR), prio);
0232:                    prio = new Integer(2);
0233:                    opPrio.put(new Integer(LexAnn.TT_LAND), prio);
0234:                    prio = new Integer(5);
0235:                    opPrio.put(new Integer(LexAnn.TT_LEQ), prio);
0236:                    opPrio.put(new Integer(LexAnn.TT_LNEQ), prio);
0237:                    opPrio.put(new Integer(LexAnn.TT_LGR), prio);
0238:                    opPrio.put(new Integer(LexAnn.TT_LGRE), prio);
0239:                    opPrio.put(new Integer(LexAnn.TT_LLS), prio);
0240:                    opPrio.put(new Integer(LexAnn.TT_LLSE), prio);
0241:                    prio = new Integer(10);
0242:                    opPrio.put(new Integer(LexAnn.TT_PLUS), prio);
0243:                    opPrio.put(new Integer(LexAnn.TT_MINUS), prio);
0244:                    prio = new Integer(20);
0245:                    opPrio.put(new Integer(LexAnn.TT_MULT), prio);
0246:                    opPrio.put(new Integer(LexAnn.TT_DIV), prio);
0247:                    opPrio.put(new Integer(LexAnn.TT_MOD), prio);
0248:                }
0249:            }
0250:
0251:            //statement - top level thing
0252:            private void parseStmt() throws IOException, FSException,
0253:                    RetException {
0254:
0255:                switch (tok.ttype) {
0256:
0257:                case LexAnn.TT_DEFINT:
0258:                case LexAnn.TT_DEFSTRING:
0259:                case LexAnn.TT_DEFDOUBLE:
0260:                case LexAnn.TT_DEFOBJECT: {
0261:                    parseVarDef();
0262:                    break;
0263:                }
0264:
0265:                case LexAnn.TT_IF: {
0266:                    parseIf();
0267:                    break;
0268:                }
0269:                case LexAnn.TT_WHILE: {
0270:                    parseWhile();
0271:                    break;
0272:                }
0273:                case LexAnn.TT_RETURN: {
0274:                    parseReturn();
0275:                    break;
0276:                }
0277:                case LexAnn.TT_DEFFUNC: {
0278:                    parseFunctionDef();
0279:                    break;
0280:                }
0281:                case LexAnn.TT_EDEFFUNC: {
0282:                    parseFunctionEnd();
0283:                    break;
0284:                }
0285:                case LexAnn.TT_EIF:
0286:                    throw new FSException("unexpected endif");
0287:                case LexAnn.TT_EWHILE:
0288:                    throw new FSException("unexpected endwhile");
0289:
0290:                case LexAnn.TT_FUNC: {
0291:                    parseFunc();
0292:                    break;
0293:                }
0294:                case LexAnn.TT_ARRAY: {
0295:                    parseArrayAssign();
0296:                    break;
0297:                }
0298:                case LexAnn.TT_WORD: {
0299:                    parseAssign();
0300:                    break;
0301:                }
0302:                case LexAnn.TT_EOL: {
0303:                    tok.nextToken();
0304:                    break;
0305:                }
0306:                case LexAnn.TT_EOF: {
0307:                    // all done
0308:                    break;
0309:                }
0310:                default: {
0311:                    parseError("Expected identifier " + tok);
0312:
0313:                }
0314:                }
0315:
0316:            }
0317:
0318:            private void parseFunc() throws IOException, FSException {
0319:                String name;
0320:
0321:                name = (String) tok.value;
0322:
0323:                //should be a '('
0324:                getNextToken();
0325:
0326:                parseCallFunc(name);
0327:                getNextToken();
0328:            }
0329:
0330:            private void parseArrayAssign() throws IOException, FSException {
0331:                String name;
0332:                Object index;
0333:                Object val;
0334:
0335:                name = (String) tok.value;
0336:                getNextToken(); // should be a '['
0337:                getNextToken(); // should be the index
0338:                index = parseExpr();
0339:                getNextToken(); // should be a ']'
0340:
0341:                //getNextToken();
0342:                if (tok.ttype != LexAnn.TT_EQ) {
0343:                    parseError("Expected '='");
0344:                } else {
0345:                    getNextToken();
0346:                    val = parseExpr();
0347:                    try {
0348:                        host.setVarEntry(name, index, val);
0349:                    } catch (Exception e) {
0350:                        parseError(e.getMessage());
0351:                    }
0352:                }
0353:            }
0354:
0355:            //handles 'return' statements
0356:            private void parseReturn() throws IOException, FSException,
0357:                    RetException {
0358:
0359:                getNextToken();
0360:
0361:                retVal = parseExpr();
0362:                throw new RetException();
0363:            }
0364:
0365:            // handle endif without return, just return 1 (or true)
0366:            private void parseFunctionEnd() throws RetException {
0367:                retVal = FS_TRUE;
0368:                throw new RetException();
0369:            }
0370:
0371:            //Asignment parser
0372:            private void parseAssign() throws IOException, FSException {
0373:                String name;
0374:                Object val;
0375:
0376:                name = (String) tok.value;
0377:                getNextToken();
0378:
0379:                if (tok.ttype != LexAnn.TT_EQ) {
0380:                    parseError("Expected '='");
0381:                } else {
0382:
0383:                    getNextToken();
0384:                    val = parseExpr();
0385:
0386:                    if (hasVar(name)) {
0387:                        setVar(name, val);
0388:                    } else {
0389:                        try {
0390:                            host.setVarEntry(name, null, val);
0391:                        } catch (Exception e) {
0392:                            parseError(e.getMessage());
0393:                        }
0394:                    }
0395:                }
0396:            }
0397:
0398:            Object callFunction(String name, ArrayList params)
0399:                    throws IOException, FSException {
0400:
0401:                FuncEntry fDef;
0402:                int n;
0403:                int oldLine;
0404:                Parser oldSubParser;
0405:                Object val;
0406:
0407:                val = null;
0408:
0409:                //Check we have a definition for the function
0410:                if (funcs.containsKey(name)) {
0411:
0412:                    fDef = (FuncEntry) funcs.get(name);
0413:
0414:                    //Check params and def match
0415:                    if (fDef.paramNames.size() != params.size()) {
0416:                        parseError("Expected " + fDef.paramNames.size()
0417:                                + " parameters, Found " + params.size());
0418:                    }
0419:
0420:                    //Create a new parser instance to handle call
0421:                    Parser p;
0422:                    HashMap locals = new HashMap();
0423:
0424:                    //Push the params into the local scope
0425:                    for (n = 0; n < fDef.paramNames.size(); n++) {
0426:                        locals.put(fDef.paramNames.get(n), params.get(n));
0427:                    }
0428:                    //watch for recursive calls
0429:                    if (gVars == null) {
0430:                        p = new Parser(host, locals, vars, funcs);
0431:                    } else {
0432:                        p = new Parser(host, locals, gVars, funcs);
0433:                    }
0434:                    //cache the current execution point
0435:                    oldLine = code.getCurLine();
0436:                    p.setCode(code);
0437:                    oldSubParser = subParser;
0438:                    subParser = p;
0439:
0440:                    //let it rip
0441:                    val = p.parse(fDef.startLine + 1, fDef.endLine - 1);
0442:
0443:                    //reset execution point
0444:                    subParser = oldSubParser;
0445:                    code.setCurLine(oldLine);
0446:
0447:                } else {//calls into super class  code...}
0448:                    try {
0449:                        val = host.callFunctionEntry(name, params);
0450:                    } catch (Exception e) {
0451:                        parseError(e.getMessage());
0452:                    }
0453:                }
0454:
0455:                return val;
0456:
0457:            }
0458:
0459:            //Handle calls to a function
0460:            private Object parseCallFunc(String name) throws IOException,
0461:                    FSException {
0462:
0463:                ArrayList params = new ArrayList(4);
0464:
0465:                //Set up the parameters
0466:                do {
0467:                    getNextToken();
0468:                    if (tok.ttype == ',') {
0469:                        getNextToken();
0470:                    } else if (tok.ttype == ')') {
0471:                        break;
0472:                    }
0473:                    params.add(parseExpr());
0474:                } while (tok.ttype == ',');
0475:
0476:                return callFunction(name, params);
0477:
0478:            }
0479:
0480:            //handles function definitions
0481:            private void parseFunctionDef() throws IOException, FSException {
0482:
0483:                FuncEntry fDef = new FuncEntry();
0484:                Object val;
0485:                String name, fName;
0486:
0487:                fDef.startLine = code.getCurLine();
0488:
0489:                getNextToken();
0490:
0491:                //should be the function name
0492:                if (tok.ttype != LexAnn.TT_FUNC) {
0493:                    parseError("Expected function start identifier");
0494:                }
0495:                fName = (String) tok.value;
0496:                getNextToken();
0497:
0498:                //should be a '('
0499:                if (tok.ttype != '(') {
0500:                    parseError("Expected (");
0501:                }
0502:
0503:                getNextToken();
0504:                //parse the header...
0505:                while (tok.ttype != ')') {
0506:                    val = null; //keep the compiler happy..
0507:
0508:                    if (tok.ttype == LexAnn.TT_DEFINT) {
0509:                        val = FS_FALSE;
0510:                    } else if (tok.ttype == LexAnn.TT_DEFSTRING) {
0511:                        val = new String("");
0512:                    } else if (tok.ttype == LexAnn.TT_DEFOBJECT) {
0513:                        val = new FSObject();
0514:                    } else {
0515:                        parseError("Expected type name");
0516:                    }
0517:
0518:                    getNextToken();
0519:
0520:                    if (tok.ttype != LexAnn.TT_WORD) {
0521:                        parseError("Expected function parameter name identifier");
0522:                    }
0523:
0524:                    name = (String) tok.value;
0525:
0526:                    fDef.paramNames.add(name);
0527:                    fDef.params.put(name, val);
0528:
0529:                    getNextToken();
0530:                    if (tok.ttype == ',')
0531:                        getNextToken();
0532:                }
0533:
0534:                //now we just skip to the endfunction
0535:
0536:                while ((tok.ttype != LexAnn.TT_EDEFFUNC)
0537:                        && (tok.ttype != LexAnn.TT_EOF)) {
0538:                    getNextToken();
0539:                    if (tok.ttype == LexAnn.TT_DEFFUNC)
0540:                        parseError("Nested functions are illegal");
0541:                }
0542:
0543:                fDef.endLine = code.getCurLine();
0544:                getNextToken();
0545:
0546:                funcs.put(fName, fDef);
0547:
0548:            }
0549:
0550:            //Really process tthe expressions (internal recursive calls only), all
0551:            //external calls call parseExpr()
0552:            private Object parseExpr() throws IOException, FSException {
0553:
0554:                ETreeNode curNode = null;
0555:                boolean end = false;
0556:                Object val;
0557:                boolean negate = false; //flag for unary minus
0558:                boolean not = false;//flag for unary not.
0559:                boolean prevOp = true;//flag - true if previous value was an operator
0560:
0561:                while (!end) {
0562:
0563:                    switch (tok.ttype) {
0564:
0565:                    //the various possible 'values'
0566:                    case LexAnn.TT_INTEGER:
0567:                    case LexAnn.TT_DOUBLE:
0568:                    case LexAnn.TT_STRING:
0569:                    case LexAnn.TT_WORD:
0570:                    case LexAnn.TT_FUNC:
0571:                    case LexAnn.TT_NULL:
0572:                    case LexAnn.TT_ARRAY: {
0573:
0574:                        if (!prevOp) {
0575:                            parseError("Expected Operator");
0576:                        } else {
0577:
0578:                            val = null;
0579:                            ETreeNode node = new ETreeNode();
0580:                            node.type = ETreeNode.E_VAL;
0581:
0582:                            switch (tok.ttype) {
0583:                            //numbers - just get them
0584:                            case LexAnn.TT_INTEGER: {
0585:                                val = tok.value;
0586:                                break;
0587:                            }
0588:                            case LexAnn.TT_DOUBLE: {
0589:                                val = tok.value;
0590:                                break;
0591:                            }
0592:                                //functions - evaluate them
0593:                            case LexAnn.TT_FUNC: {
0594:                                String name = (String) tok.value;
0595:                                getNextToken();
0596:                                val = parseCallFunc(name);
0597:                                break;
0598:                            }
0599:                                //arrays - evaluate them
0600:                            case LexAnn.TT_ARRAY: {
0601:                                String name = (String) tok.value;
0602:                                getNextToken(); //should be a '['
0603:                                getNextToken(); //should be the index
0604:                                Object index = parseExpr();
0605:                                try {
0606:                                    val = host.getVarEntry(name, index);
0607:                                } catch (Exception e) {
0608:                                    parseError(e.getMessage());
0609:                                }
0610:                                break;
0611:                            }
0612:                                //variables - resolve them
0613:                            case LexAnn.TT_WORD: {
0614:                                if (hasVar((String) tok.value)) {
0615:                                    val = getVar((String) tok.value);
0616:                                } else {
0617:                                    try {
0618:                                        val = host.getVarEntry(
0619:                                                (String) tok.value, null);
0620:                                    } catch (Exception e) {
0621:                                        parseError(e.getMessage());
0622:                                    }
0623:                                }
0624:                                break;
0625:                            }
0626:                                //strings - just get again
0627:                            case LexAnn.TT_STRING: {
0628:                                val = tok.value;
0629:                                break;
0630:                            }
0631:                                //null
0632:                            case LexAnn.TT_NULL: {
0633:                                val = new FSObject(null);
0634:                                break;
0635:                            }
0636:                            }
0637:
0638:                            //unary not
0639:                            if (not) {
0640:                                if (val instanceof  Integer) {
0641:                                    if (((Integer) val).intValue() == 0) {
0642:                                        val = FS_TRUE;
0643:                                    } else {
0644:                                        val = FS_FALSE;
0645:                                    }
0646:                                    not = false;
0647:                                } else if (val instanceof  FSObject
0648:                                        && ((FSObject) val).getObject() instanceof  Boolean) {
0649:                                    if (((FSObject) val).getObject().equals(
0650:                                            Boolean.FALSE)) {
0651:                                        val = FS_TRUE;
0652:                                    } else {
0653:                                        val = FS_FALSE;
0654:                                    }
0655:                                } else if (val instanceof  FSObject
0656:                                        && ((FSObject) val).getObject() instanceof  Integer) {
0657:                                    if (((Integer) ((FSObject) val).getObject())
0658:                                            .intValue() == 0) {
0659:                                        val = FS_TRUE;
0660:                                    } else {
0661:                                        val = FS_FALSE;
0662:                                    }
0663:                                } else {
0664:                                    String msg = val.getClass().getName();
0665:                                    if (val instanceof  FSObject)
0666:                                        msg = "FSObject with "
0667:                                                + ((FSObject) val)
0668:                                                        .getNullClass()
0669:                                                        .getName();
0670:                                    parseError("Type mismatch for ! " + msg);
0671:                                }
0672:                            }
0673:
0674:                            //unary minus
0675:                            if (negate) {
0676:                                if (val instanceof  Integer) {
0677:                                    val = new Integer(-((Integer) val)
0678:                                            .intValue());
0679:                                } else if (val instanceof  Double) {
0680:                                    val = new Double(-((Double) val)
0681:                                            .doubleValue());
0682:                                } else {
0683:                                    parseError("Type mistmatch for unary -");
0684:                                }
0685:                            }
0686:
0687:                            node.value = val;
0688:
0689:                            if (curNode != null) {
0690:                                if (curNode.left == null) {
0691:                                    curNode.left = node;
0692:                                    node.parent = curNode;
0693:                                    curNode = node;
0694:
0695:                                } else if (curNode.right == null) {
0696:                                    curNode.right = node;
0697:                                    node.parent = curNode;
0698:                                    curNode = node;
0699:
0700:                                }
0701:                            } else {
0702:                                curNode = node;
0703:                            }
0704:
0705:                            prevOp = false;
0706:                        }
0707:                        break;
0708:                    }
0709:                        /*operators - have to be more carefull with these.
0710:                        We build an expression tree - inserting the nodes at the right
0711:                        points to get a reasonable approximation to correct operator
0712:                        precidence*/
0713:                    case LexAnn.TT_LEQ:
0714:                    case LexAnn.TT_LNEQ:
0715:                    case LexAnn.TT_MULT:
0716:                    case LexAnn.TT_DIV:
0717:                    case LexAnn.TT_MOD:
0718:                    case LexAnn.TT_PLUS:
0719:                    case LexAnn.TT_MINUS:
0720:                    case LexAnn.TT_LGR:
0721:                    case LexAnn.TT_LGRE:
0722:                    case LexAnn.TT_LLSE:
0723:                    case LexAnn.TT_LLS:
0724:                    case LexAnn.TT_NOT:
0725:                    case LexAnn.TT_LAND:
0726:                    case LexAnn.TT_LOR: {
0727:                        if (prevOp) {
0728:                            if (tok.ttype == LexAnn.TT_MINUS) {
0729:                                negate = true;
0730:                            } else if (tok.ttype == LexAnn.TT_NOT) {
0731:                                not = true;
0732:                            } else {
0733:                                parseError("Expected Expression");
0734:                            }
0735:                        } else {
0736:
0737:                            ETreeNode node = new ETreeNode();
0738:
0739:                            node.type = ETreeNode.E_OP;
0740:                            node.value = new Integer(tok.ttype);
0741:
0742:                            if (curNode.parent != null) {
0743:
0744:                                int curPrio = getPrio(tok.ttype);
0745:                                int parPrio = getPrio(((Integer) curNode.parent.value)
0746:                                        .intValue());
0747:
0748:                                if (curPrio <= parPrio) {
0749:                                    //this nodes parent is the current nodes grandparent
0750:                                    node.parent = curNode.parent.parent;
0751:                                    //our nodes left leg is now linked into the current nodes
0752:                                    //parent
0753:                                    node.left = curNode.parent;
0754:                                    //hook into grandparent
0755:                                    if (curNode.parent.parent != null) {
0756:                                        curNode.parent.parent.right = node;
0757:                                    }
0758:
0759:                                    //the current nodes parent is now us (because of above)
0760:                                    curNode.parent = node;
0761:                                    //set the current node.
0762:                                    curNode = node;
0763:                                } else {
0764:                                    //current node's parent's right is now us.
0765:                                    curNode.parent.right = node;
0766:                                    //our nodes left is the current node.
0767:                                    node.left = curNode;
0768:                                    //our nodes parent is the current node's parent.
0769:                                    node.parent = curNode.parent;
0770:                                    //curent nodes parent is now us.
0771:                                    curNode.parent = node;
0772:                                    //set the current node.
0773:                                    curNode = node;
0774:                                }
0775:                            } else {
0776:                                //our node's left is the current node
0777:                                node.left = curNode;
0778:                                //current node's parent is us now
0779:                                //we don't have to set our parent, as it is null.
0780:                                curNode.parent = node;
0781:                                //set current node
0782:                                curNode = node;
0783:                            }
0784:                            prevOp = true;
0785:                        }
0786:                        break;
0787:                    }
0788:                    case '(':
0789:                        //start of an bracketed expression, recursively call ourself
0790:                        //to get a value
0791:                    {
0792:                        getNextToken();
0793:                        val = parseExpr();
0794:
0795:                        if (negate) {
0796:                            if (val instanceof  Integer) {
0797:                                val = new Integer(-((Integer) val).intValue());
0798:                            } else if (val instanceof  Double) {
0799:                                val = new Double(-((Double) val).doubleValue());
0800:                            } else {
0801:                                parseError("Type mistmatch for unary -");
0802:                            }
0803:                        }
0804:
0805:                        ETreeNode node = new ETreeNode();
0806:                        node.value = val;
0807:                        node.type = ETreeNode.E_VAL;
0808:
0809:                        if (curNode != null) {
0810:                            if (curNode.left == null) {
0811:                                curNode.left = node;
0812:                                node.parent = curNode;
0813:                                curNode = node;
0814:
0815:                            } else if (curNode.right == null) {
0816:                                curNode.right = node;
0817:                                node.parent = curNode;
0818:                                curNode = node;
0819:
0820:                            }
0821:                        } else {
0822:                            curNode = node;
0823:                        }
0824:                        prevOp = false;
0825:                        break;
0826:                    }
0827:
0828:                    default: {
0829:                        end = true;
0830:                    }
0831:
0832:                    }
0833:                    if (!end) {
0834:                        tok.nextToken();
0835:                    }
0836:                }
0837:
0838:                //find the top of the tree we just built.
0839:                if (curNode == null)
0840:                    parseError("Missing Expression");
0841:                while (curNode.parent != null) {
0842:                    curNode = curNode.parent;
0843:                }
0844:
0845:                return evalETree(curNode);
0846:
0847:            }
0848:
0849:            //convenience function to get operator priority
0850:            private int getPrio(int op) {
0851:                return ((Integer) opPrio.get(new Integer(op))).intValue();
0852:            }
0853:
0854:            //evaluates the expression tree recursively
0855:            private Object evalETree(ETreeNode node) throws FSException {
0856:                Object lVal, rVal;
0857:
0858:                if (node == null) {
0859:                    parseError("Malformed expression");
0860:                    // this is never reached, just for readability
0861:                    return null;
0862:                }
0863:
0864:                if (node.type == ETreeNode.E_VAL) {
0865:                    return node.value;
0866:                }
0867:                lVal = evalETree(node.left);
0868:                rVal = evalETree(node.right);
0869:
0870:                switch (((Integer) node.value).intValue()) {
0871:                //call the various eval functions
0872:                case LexAnn.TT_PLUS: {
0873:                    return evalPlus(lVal, rVal);
0874:                }
0875:                case LexAnn.TT_MINUS: {
0876:                    return evalMinus(lVal, rVal);
0877:                }
0878:                case LexAnn.TT_MULT: {
0879:                    return evalMult(lVal, rVal);
0880:                }
0881:                case LexAnn.TT_DIV: {
0882:                    return evalDiv(lVal, rVal);
0883:                }
0884:                case LexAnn.TT_LEQ: {
0885:                    return evalEq(lVal, rVal);
0886:                }
0887:                case LexAnn.TT_LNEQ: {
0888:                    return evalNEq(lVal, rVal);
0889:                }
0890:                case LexAnn.TT_LLS: {
0891:                    return evalLs(lVal, rVal);
0892:                }
0893:                case LexAnn.TT_LLSE: {
0894:                    return evalLse(lVal, rVal);
0895:                }
0896:                case LexAnn.TT_LGR: {
0897:                    return evalGr(lVal, rVal);
0898:                }
0899:                case LexAnn.TT_LGRE: {
0900:                    return evalGre(lVal, rVal);
0901:                }
0902:                case LexAnn.TT_MOD: {
0903:                    return evalMod(lVal, rVal);
0904:                }
0905:                case LexAnn.TT_LAND: {
0906:                    return evalAnd(lVal, rVal);
0907:                }
0908:                case LexAnn.TT_LOR: {
0909:                    return evalOr(lVal, rVal);
0910:                }
0911:                }
0912:
0913:                return null;
0914:            }
0915:
0916:            //addition
0917:            private Object evalPlus(Object lVal, Object rVal)
0918:                    throws FSException {
0919:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
0920:                    return new Integer(((Integer) lVal).intValue()
0921:                            + ((Integer) rVal).intValue());
0922:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
0923:                    return new Double(((Double) lVal).doubleValue()
0924:                            + ((Double) rVal).doubleValue());
0925:                } else if (lVal instanceof  String || rVal instanceof  String) {
0926:                    return new String(lVal.toString() + rVal.toString());
0927:                } else if (lVal instanceof  Double && rVal instanceof  Integer) {
0928:                    return new Double(((Double) lVal).doubleValue()
0929:                            + ((Integer) rVal).intValue());
0930:                } else if (lVal instanceof  Integer && rVal instanceof  Double) {
0931:                    return new Double(((Integer) lVal).intValue()
0932:                            + ((Double) rVal).doubleValue());
0933:                } else {
0934:                    parseError("Type Mismatch for operator +");
0935:                }
0936:
0937:                return null;
0938:            }
0939:
0940:            //subtraction
0941:            private Object evalMinus(Object lVal, Object rVal)
0942:                    throws FSException {
0943:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
0944:                    return new Integer(((Integer) lVal).intValue()
0945:                            - ((Integer) rVal).intValue());
0946:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
0947:                    return new Double(((Double) lVal).doubleValue()
0948:                            - ((Double) rVal).doubleValue());
0949:                } else if (lVal instanceof  Double && rVal instanceof  Integer) {
0950:                    return new Double(((Double) lVal).doubleValue()
0951:                            - ((Integer) rVal).intValue());
0952:                } else if (lVal instanceof  Integer && rVal instanceof  Double) {
0953:                    return new Double(((Integer) lVal).intValue()
0954:                            - ((Double) rVal).doubleValue());
0955:                } else {
0956:                    parseError("Type Mismatch for operator -");
0957:                }
0958:
0959:                return null;
0960:            }
0961:
0962:            //multiplication
0963:            private Object evalMult(Object lVal, Object rVal)
0964:                    throws FSException {
0965:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
0966:                    return new Integer(((Integer) lVal).intValue()
0967:                            * ((Integer) rVal).intValue());
0968:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
0969:                    return new Double(((Double) lVal).doubleValue()
0970:                            * ((Double) rVal).doubleValue());
0971:                } else if (lVal instanceof  Double && rVal instanceof  Integer) {
0972:                    return new Double(((Double) lVal).doubleValue()
0973:                            * ((Integer) rVal).intValue());
0974:                } else if (lVal instanceof  Integer && rVal instanceof  Double) {
0975:                    return new Double(((Integer) lVal).intValue()
0976:                            * ((Double) rVal).doubleValue());
0977:                } else {
0978:                    parseError("Type Mismatch for operator *");
0979:                }
0980:
0981:                return null;
0982:            }
0983:
0984:            //modulus
0985:            private Object evalMod(Object lVal, Object rVal) throws FSException {
0986:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
0987:                    return new Integer(((Integer) lVal).intValue()
0988:                            % ((Integer) rVal).intValue());
0989:                } else {
0990:                    parseError("Type Mismatch for operator %");
0991:                }
0992:
0993:                return null;
0994:            }
0995:
0996:            //Logical AND
0997:            private Object evalAnd(Object lVal, Object rVal) throws FSException {
0998:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
0999:                    boolean b1, b2;
1000:                    b1 = ((Integer) lVal).intValue() != 0;
1001:                    b2 = ((Integer) rVal).intValue() != 0;
1002:                    if (b1 && b2) {
1003:                        return FS_TRUE;
1004:                    } else {
1005:                        return FS_FALSE;
1006:                    }
1007:                } else {
1008:                    parseError("Type Mismatch for operator &&");
1009:                }
1010:
1011:                return null;
1012:            }
1013:
1014:            //Logical Or
1015:            private Object evalOr(Object lVal, Object rVal) throws FSException {
1016:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
1017:                    boolean b1, b2;
1018:                    b1 = ((Integer) lVal).intValue() != 0;
1019:                    b2 = ((Integer) rVal).intValue() != 0;
1020:                    if (b1 || b2) {
1021:                        return FS_TRUE;
1022:                    } else {
1023:                        return FS_FALSE;
1024:                    }
1025:                } else {
1026:                    parseError("Type Mismatch for operator ||");
1027:                }
1028:
1029:                return null;
1030:            }
1031:
1032:            //division
1033:            private Object evalDiv(Object lVal, Object rVal) throws FSException {
1034:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
1035:                    return new Integer(((Integer) lVal).intValue()
1036:                            / ((Integer) rVal).intValue());
1037:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
1038:                    return new Double(((Double) lVal).doubleValue()
1039:                            / ((Double) rVal).doubleValue());
1040:                } else if (lVal instanceof  Double && rVal instanceof  Integer) {
1041:                    return new Double(((Double) lVal).doubleValue()
1042:                            / ((Integer) rVal).intValue());
1043:                } else if (lVal instanceof  Integer && rVal instanceof  Double) {
1044:                    return new Double(((Integer) lVal).intValue()
1045:                            / ((Double) rVal).doubleValue());
1046:                } else {
1047:                    parseError("Type Mismatch for operator /");
1048:                }
1049:
1050:                return null;
1051:            }
1052:
1053:            //logical equal
1054:            private Object evalEq(Object lVal, Object rVal) throws FSException {
1055:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
1056:                    if (lVal.equals(rVal)) {
1057:                        return FS_TRUE;
1058:                    } else {
1059:                        return FS_FALSE;
1060:                    }
1061:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
1062:                    if (lVal.equals(rVal)) {
1063:                        return FS_TRUE;
1064:                    } else {
1065:                        return FS_FALSE;
1066:                    }
1067:                } else if (lVal instanceof  String && rVal instanceof  String) {
1068:                    if (lVal.equals(rVal)) {
1069:                        return FS_TRUE;
1070:                    } else {
1071:                        return FS_FALSE;
1072:                    }
1073:                } else if (lVal instanceof  FSObject) {
1074:                    if (lVal.equals(rVal)) {
1075:                        return FS_TRUE;
1076:                    } else {
1077:                        return FS_FALSE;
1078:                    }
1079:                } else if (rVal instanceof  FSObject) {
1080:                    if (rVal.equals(lVal)) {
1081:                        return FS_TRUE;
1082:                    } else {
1083:                        return FS_FALSE;
1084:                    }
1085:                } else {
1086:                    parseError("Type Mismatch for operator ==");
1087:                }
1088:
1089:                return null;
1090:            }
1091:
1092:            //<
1093:            private Object evalLs(Object lVal, Object rVal) throws FSException {
1094:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
1095:                    if (((Integer) lVal).intValue() < ((Integer) rVal)
1096:                            .intValue()) {
1097:                        return FS_TRUE;
1098:                    } else {
1099:                        return FS_FALSE;
1100:                    }
1101:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
1102:                    if (((Double) lVal).doubleValue() < ((Double) rVal)
1103:                            .doubleValue()) {
1104:                        return FS_TRUE;
1105:                    } else {
1106:                        return FS_FALSE;
1107:                    }
1108:                } else if (lVal instanceof  String && rVal instanceof  String) {
1109:                    if (((String) lVal).compareTo((String) rVal) < 0) {
1110:                        return FS_TRUE;
1111:                    } else {
1112:                        return FS_FALSE;
1113:                    }
1114:                } else {
1115:                    parseError("Type Mismatch for operator <");
1116:                }
1117:                return null;
1118:            }
1119:
1120:            //<=
1121:            private Object evalLse(Object lVal, Object rVal) throws FSException {
1122:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
1123:                    if (((Integer) lVal).intValue() <= ((Integer) rVal)
1124:                            .intValue()) {
1125:                        return FS_TRUE;
1126:                    } else {
1127:                        return FS_FALSE;
1128:                    }
1129:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
1130:                    if (((Double) lVal).doubleValue() <= ((Double) rVal)
1131:                            .doubleValue()) {
1132:                        return FS_TRUE;
1133:                    } else {
1134:                        return FS_FALSE;
1135:                    }
1136:                } else if (lVal instanceof  String && rVal instanceof  String) {
1137:                    if (((String) lVal).compareTo((String) rVal) <= 0) {
1138:                        return FS_TRUE;
1139:                    } else {
1140:                        return FS_FALSE;
1141:                    }
1142:                } else {
1143:                    parseError("Type Mismatch for operator <=");
1144:                }
1145:                return null;
1146:            }
1147:
1148:            //>
1149:            private Object evalGr(Object lVal, Object rVal) throws FSException {
1150:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
1151:                    if (((Integer) lVal).intValue() > ((Integer) rVal)
1152:                            .intValue()) {
1153:                        return FS_TRUE;
1154:                    } else {
1155:                        return FS_FALSE;
1156:                    }
1157:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
1158:                    if (((Double) lVal).doubleValue() > ((Double) rVal)
1159:                            .doubleValue()) {
1160:                        return FS_TRUE;
1161:                    } else {
1162:                        return FS_FALSE;
1163:                    }
1164:                } else if (lVal instanceof  String && rVal instanceof  String) {
1165:                    if (((String) lVal).compareTo((String) rVal) > 0) {
1166:                        return FS_TRUE;
1167:                    } else {
1168:                        return FS_FALSE;
1169:                    }
1170:                } else {
1171:                    parseError("Type Mismatch for operator >");
1172:                }
1173:                return null;
1174:            }
1175:
1176:            //>=
1177:            private Object evalGre(Object lVal, Object rVal) throws FSException {
1178:                if (lVal instanceof  Integer && rVal instanceof  Integer) {
1179:                    if (((Integer) lVal).intValue() >= ((Integer) rVal)
1180:                            .intValue()) {
1181:                        return FS_TRUE;
1182:                    } else {
1183:                        return FS_FALSE;
1184:                    }
1185:                } else if (lVal instanceof  Double && rVal instanceof  Double) {
1186:                    if (((Double) lVal).doubleValue() >= ((Double) rVal)
1187:                            .doubleValue()) {
1188:                        return FS_TRUE;
1189:                    } else {
1190:                        return FS_FALSE;
1191:                    }
1192:                } else if (lVal instanceof  String && rVal instanceof  String) {
1193:                    if (((String) lVal).compareTo((String) rVal) >= 0) {
1194:                        return FS_TRUE;
1195:                    } else {
1196:                        return FS_FALSE;
1197:                    }
1198:                } else {
1199:                    parseError("Type Mismatch for operator >=");
1200:                }
1201:                return null;
1202:            }
1203:
1204:            //logical inequallity
1205:            private Object evalNEq(Object lVal, Object rVal) throws FSException {
1206:                if (evalEq(lVal, rVal) == FS_TRUE) {
1207:                    return FS_FALSE;
1208:                } else {
1209:                    return FS_TRUE;
1210:                }
1211:            }
1212:
1213:            /*    private void printWTree(ETreeNode node){
1214:             while(node.parent!=null){
1215:             node=node.parent;
1216:             }
1217:             printETree(node);
1218:             } */
1219:
1220:            /*    private void printETree(ETreeNode node){
1221:
1222:             System.out.println(node);
1223:             if (node.left!=null){
1224:             System.out.print("Left");
1225:             printETree(node.left);
1226:             }
1227:             if (node.right!=null){
1228:             System.out.print("Right");
1229:             printETree(node.right);
1230:             }
1231:             } */
1232:
1233:            private void parseIf() throws IOException, FSException,
1234:                    RetException {
1235:                Integer val;
1236:                int depth;
1237:                boolean then = false;
1238:
1239:                getNextToken();
1240:                Object obj = parseExpr();
1241:                if (obj instanceof  Integer)
1242:                    val = (Integer) obj;
1243:                else {
1244:                    if (obj instanceof  FSObject)
1245:                        obj = ((FSObject) obj).getObject();
1246:                    if (obj instanceof  Boolean)
1247:                        val = ((Boolean) obj).booleanValue() ? FS_TRUE
1248:                                : FS_FALSE;
1249:                    else if (obj instanceof  Integer) {
1250:                        // test needed a second time 'cause it may have been an FSObject before
1251:                        val = (Integer) obj;
1252:                    } else {
1253:                        parseError("If condition needs to be Integer");
1254:                        return; // just to make sure the compiler doesn't complain
1255:                        // as we know parseError throws an exception (stupid compiler)
1256:                    }
1257:                }
1258:
1259:                //handle the one line if-then construct
1260:                if (tok.ttype == LexAnn.TT_THEN) {
1261:                    getNextToken();
1262:                    //is this a single line then (or just a optional then)
1263:                    if (tok.ttype != LexAnn.TT_EOL) {
1264:                        //single line if then construct - run separately
1265:                        //tok.pushBack();
1266:                        if (val.intValue() != 0) {
1267:                            parseStmt();
1268:                        } else {
1269:                            //consume to EOL
1270:                            while (tok.ttype != LexAnn.TT_EOL) {
1271:                                getNextToken();
1272:                            }
1273:                        }
1274:                        then = true;
1275:                    }
1276:                }
1277:
1278:                if (!then) {
1279:                    if (val.intValue() != 0) {
1280:                        getNextToken();
1281:                        while ((tok.ttype != LexAnn.TT_EIF)
1282:                                && (tok.ttype != LexAnn.TT_ELSE)
1283:                                && (tok.ttype != LexAnn.TT_EOF)
1284:                                && (tok.ttype != LexAnn.TT_ELSIF)) {
1285:                            //run the body of the if
1286:                            parseStmt();
1287:                            getNextToken();
1288:                        }
1289:                        if (tok.ttype == LexAnn.TT_ELSE
1290:                                || tok.ttype == LexAnn.TT_ELSIF) {
1291:                            //skip else clause -
1292:                            //have to do this taking into acount nesting
1293:                            depth = 1;
1294:                            do {
1295:                                getNextToken();
1296:                                if (tok.ttype == LexAnn.TT_IF)
1297:                                    depth++;
1298:                                if (tok.ttype == LexAnn.TT_EOF)
1299:                                    parseError("can't find endif");
1300:                                if (tok.ttype == LexAnn.TT_EIF)
1301:                                    depth--;
1302:
1303:                                //A then could indicate a one line
1304:                                //if - then construct, then we don't increment
1305:                                //depth
1306:                                if (tok.ttype == LexAnn.TT_THEN) {
1307:
1308:                                    getNextToken();
1309:                                    if (tok.ttype != LexAnn.TT_EOL) {
1310:                                        depth--;
1311:                                    }
1312:                                    tok.pushBack();
1313:                                }
1314:
1315:                            } while (depth > 0);
1316:                            getNextToken();
1317:                        } else {
1318:                            getNextToken();
1319:                        }
1320:
1321:                    } else {
1322:                        //skip to else clause
1323:                        depth = 1;
1324:                        do {
1325:                            getNextToken();
1326:                            if (tok.ttype == LexAnn.TT_IF)
1327:                                depth++;
1328:                            if (tok.ttype == LexAnn.TT_EOF)
1329:                                parseError("can't find endif");
1330:                            if ((tok.ttype == LexAnn.TT_EIF))
1331:                                depth--;
1332:                            if ((tok.ttype == LexAnn.TT_ELSE || tok.ttype == LexAnn.TT_ELSIF)
1333:                                    && depth == 1)
1334:                                depth--;
1335:                            //A then could indicate a one line
1336:                            //if - then construct, then we don't increment
1337:                            //depth
1338:                            if (tok.ttype == LexAnn.TT_THEN) {
1339:
1340:                                getNextToken();
1341:                                if (tok.ttype != LexAnn.TT_EOL) {
1342:                                    depth--;
1343:                                }
1344:                                tok.pushBack();
1345:                            }
1346:
1347:                        } while (depth > 0);
1348:
1349:                        if (tok.ttype == LexAnn.TT_ELSE) {
1350:                            getNextToken();
1351:                            getNextToken();
1352:                            //run else clause
1353:
1354:                            while (tok.ttype != LexAnn.TT_EIF) {
1355:                                parseStmt();
1356:                                getNextToken();
1357:                            }
1358:                            getNextToken();
1359:                        } else if (tok.ttype == LexAnn.TT_ELSIF) {
1360:                            parseIf();
1361:                        } else {
1362:                            getNextToken();
1363:                        }
1364:                    }
1365:                }
1366:
1367:            }
1368:
1369:            private void parseWhile() throws IOException, FSException,
1370:                    RetException {
1371:                //parses the while statement
1372:
1373:                Integer val;
1374:                boolean looping = true;
1375:                int startLine;
1376:                //int endPos;
1377:                int depth;
1378:
1379:                startLine = code.getCurLine();
1380:
1381:                while (looping) {
1382:                    getNextToken(); // a 'while' you would imagine
1383:                    Object obj = parseExpr();
1384:                    if (obj instanceof  Integer)
1385:                        val = (Integer) obj;
1386:                    else {
1387:                        if (obj instanceof  FSObject)
1388:                            obj = ((FSObject) obj).getObject();
1389:                        if (obj instanceof  Boolean)
1390:                            val = ((Boolean) obj).booleanValue() ? FS_TRUE
1391:                                    : FS_FALSE;
1392:                        else if (obj instanceof  Integer) {
1393:                            // test needed a second time 'cause it may have been an FSObject before
1394:                            val = (Integer) obj;
1395:                        } else {
1396:                            parseError("While condition needs to be Integer");
1397:                            return; // just to make sure the compiler doesn't complain
1398:                            // as we know parseError throws an exception (stupid compiler)
1399:                        }
1400:                    }
1401:                    getNextToken();
1402:
1403:                    if (val.intValue() == 0) {
1404:                        looping = false;
1405:                    } else {
1406:                        while ((tok.ttype != LexAnn.TT_EWHILE)
1407:                                && (tok.ttype != LexAnn.TT_EOF)) {
1408:                            parseStmt();
1409:                            getNextToken();
1410:                        }
1411:
1412:                        //reset to start of while loop....
1413:                        code.setCurLine(startLine);
1414:                        resetTokens();
1415:                    }
1416:                }
1417:                //skip to endwhile
1418:                depth = 1;
1419:                do {
1420:                    getNextToken();
1421:                    if (tok.ttype == LexAnn.TT_WHILE)
1422:                        depth++;
1423:                    if (tok.ttype == LexAnn.TT_EWHILE)
1424:                        depth--;
1425:                    if (tok.ttype == LexAnn.TT_EOF)
1426:                        parseError("can't find endwhile");
1427:                } while (depth > 0);
1428:
1429:                getNextToken();
1430:            }
1431:
1432:            private void parseVarDef() throws IOException, FSException {
1433:
1434:                String name;
1435:                int type = tok.ttype;
1436:
1437:                do {
1438:                    getNextToken();
1439:                    if (tok.ttype != LexAnn.TT_WORD) {
1440:                        parseError("Expected variable name identifier,");
1441:                    }
1442:
1443:                    name = (String) tok.value;
1444:
1445:                    switch (type) {
1446:                    case LexAnn.TT_DEFINT: {
1447:                        addVar(name, FS_FALSE);
1448:                        break;
1449:                    }
1450:                    case LexAnn.TT_DEFSTRING: {
1451:                        addVar(name, new String(""));
1452:                        break;
1453:                    }
1454:                    case LexAnn.TT_DEFDOUBLE: {
1455:                        addVar(name, new Double(0));
1456:                        break;
1457:                    }
1458:                    case LexAnn.TT_DEFOBJECT: {
1459:                        addVar(name, new FSObject());
1460:                        break;
1461:                    }
1462:                    }
1463:
1464:                    getNextToken();
1465:                    if (tok.ttype == LexAnn.TT_EQ) {
1466:                        getNextToken();
1467:                        setVar(name, parseExpr());
1468:                    } else if (tok.ttype != ',' && tok.ttype != LexAnn.TT_EOL) {
1469:                        parseError("Expected ','");
1470:                    }
1471:
1472:                } while (tok.ttype != LexAnn.TT_EOL);
1473:
1474:            }
1475:
1476:            //format an error message and throw FSException
1477:            private void parseError(String s) throws FSException {
1478:
1479:                // set up our error block
1480:                error = new String[6];
1481:                error[0] = s;
1482:                error[1] = (new Integer(code.getCurLine())).toString();
1483:                error[2] = code.getLineAsString();
1484:                error[3] = tok.toString();
1485:                ;
1486:                error[4] = vars.toString();
1487:                if (gVars != null)
1488:                    error[5] = (gVars == null) ? "" : gVars.toString();
1489:
1490:                // build the display string
1491:                s = "\n\t" + s + "\n" + getContext();
1492:
1493:                throw new FSException(s);
1494:            }
1495:
1496:            /**
1497:             * get the current context (executed line, variables etc)
1498:             * @return
1499:             */
1500:            public String getContext() {
1501:                int l = code.getCurLine();
1502:                String s = "\t\t at line:" + l + " ";
1503:                if (l > -1) {
1504:                    s += "\n\t\t\t  " + code.getLineAsString(l - 2);
1505:                    s += "\n\t\t\t  " + code.getLineAsString(l - 1);
1506:                    s += "\n\t\t\t> " + code.getLineAsString(l) + " <";
1507:                    s += "\n\t\t\t  " + code.getLineAsString(l + 1);
1508:                    s += "\n\t\t\t  " + code.getLineAsString(l + 2);
1509:                    s = s + "\n\t\t current token:" + tok.toString();
1510:                    ;
1511:                    s = s + "\n\t\t Variable dump:" + vars;
1512:                    if (gVars != null) {
1513:                        s = s + "\n\t\t Globals:" + gVars;
1514:                    }
1515:                } else
1516:                    s += "\n\t\t\t> " + tok.getLine() + " <";
1517:
1518:                return s;
1519:            }
1520:
1521:            //return the error block
1522:            String[] getError() {
1523:                return error;
1524:            }
1525:
1526:            // Other non SM related routines
1527:
1528:            //misc token access routines
1529:            private void getNextToken() throws IOException {
1530:                if (tok.ttype == LexAnn.TT_EOL) {
1531:                    if (code.getCurLine() < maxLine) {
1532:                        code.setCurLine(code.getCurLine() + 1);
1533:                        tok.setString(code.getLine());
1534:                        tok.nextToken();
1535:                    } else {
1536:                        tok.ttype = LexAnn.TT_EOF; //the only place this gets set
1537:                    }
1538:                } else {
1539:                    tok.nextToken();
1540:                }
1541:            }
1542:
1543:            private void resetTokens() throws IOException {
1544:                tok.setString(code.getLine());
1545:                tok.nextToken();
1546:            }
1547:
1548:            //variable access routines
1549:            void addVar(String name, Object value) throws FSException {
1550:
1551:                if (vars.containsKey(name)) {
1552:                    parseError("Already defined in this scope: " + name);
1553:                }
1554:                vars.put(name, value);
1555:            }
1556:
1557:            public Object getVar(String name) {
1558:                if (subParser != null)
1559:                    return subParser.getVar(name);
1560:                if (vars.containsKey(name)) {
1561:                    return vars.get(name);
1562:                } else {
1563:                    if (gVars != null) {
1564:                        if (gVars.containsKey(name)) {
1565:                            return gVars.get(name);
1566:                        }
1567:                    }
1568:                }
1569:
1570:                // variable not found, try extensions
1571:                try {
1572:                    return host.getVarEntry(name, null);
1573:                } catch (Exception e) {
1574:                }
1575:
1576:                return null; //shouldn't get here
1577:            }
1578:
1579:            // setVar allows assigning objects only when the objects are of the same type
1580:            // OR you can assign a String, Integer or Double to an FSObject if the contained object already
1581:            // has the same type. Note that you can change the type of the embedded object for "object" variables.
1582:            public void setVar(String name, Object val) throws FSException {
1583:
1584:                Object obj;
1585:
1586:                if (val == null)
1587:                    parseError("set variable " + name + " with null value");
1588:
1589:                if (subParser != null) {
1590:                    subParser.setVar(name, val);
1591:                    return;
1592:                }
1593:
1594:                if ((obj = vars.get(name)) != null) {
1595:                    if (val.getClass() != obj.getClass()) {
1596:                        //special case for FSObject allow asignment of either same
1597:                        //class or _any_ class if FSObject is already null
1598:                        //also allow assignment of null to any FSObject
1599:                        if (obj instanceof  FSObject) {
1600:                            if (((FSObject) obj).getObject() == null) {
1601:                                val = new FSObject(val);
1602:                            } else if (((FSObject) obj).getObject().getClass() == val
1603:                                    .getClass()) {
1604:                                val = new FSObject(val);
1605:                            } else {
1606:                                parseError("Incompatible types");
1607:                            }
1608:                        } else {
1609:                            parseError("Incompatible types");
1610:                        }
1611:                    }
1612:                    vars.remove(name);
1613:                    vars.put(name, val);
1614:                } else if ((obj = gVars.get(name)) != null) {
1615:                    if (val.getClass() != obj.getClass()) {
1616:                        parseError("Incompatible types");
1617:                    }
1618:                    gVars.remove(name);
1619:                    gVars.put(name, val);
1620:                }
1621:
1622:            }
1623:
1624:            public boolean hasVar(String name) {
1625:                if (subParser != null)
1626:                    return subParser.hasVar(name);
1627:                if (gVars == null) {
1628:                    return vars.containsKey(name);
1629:                } else {
1630:                    return vars.containsKey(name) || gVars.containsKey(name);
1631:                }
1632:            }
1633:
1634:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.