📄 codeexpression.java
字号:
tokenizer = new StreamTokenizer(reader); tokenizer.parseNumbers(); tokenizer.ordinaryChar('('); tokenizer.ordinaryChar(')'); tokenizer.ordinaryChar('*'); tokenizer.ordinaryChar('/'); tokenizer.ordinaryChar('+'); tokenizer.ordinaryChar('-'); tokenizer.ordinaryChar('<'); tokenizer.ordinaryChar('='); tokenizer.ordinaryChar('>'); tokenizer.ordinaryChar('!'); tokenizer.ordinaryChar('?'); tokenizer.ordinaryChar(':'); tokenizer.ordinaryChar('@'); tokenizer.quoteChar('"'); tokenizer.wordChars('_', '_'); } private Expr parse() throws EvalSpice.ParseException { try { nextToken(); Expr expr = evalEq(); assert op == null; switch (tokenizer.ttype) { case StreamTokenizer.TT_EOF: return expr; case StreamTokenizer.TT_EOL: throw new EvalSpice.ParseException("Multiline expression"); case StreamTokenizer.TT_NUMBER: case StreamTokenizer.TT_WORD: case '(': throw new EvalSpice.ParseException("Two operands with no operator"); default: throw new EvalSpice.ParseException("Unexpected character " + (char)tokenizer.ttype); } } catch (IOException e) { throw new EvalSpice.ParseException(e.getMessage()); } catch (EvalSpice.ParseException e) { try { long left = reader.skip(Long.MAX_VALUE); int pos = expr.length() - (int)left; throw new EvalSpice.ParseException(expr.substring(0, pos) + "<" + e.getMessage() + ">" + expr.substring(pos)); } catch (IOException e2) {} } throw new AssertionError(); } private Expr evalEq() throws IOException, EvalSpice.ParseException { return evalEq(Expr.MAX_PRECEDENCE); } /** * Evaluate an expression * @return the evaluated expression * @throws IOException * @throws ParseException */ private Expr evalEq(int outerPrecedence) throws IOException, EvalSpice.ParseException { boolean unaryMinus = false; if (op == EvalSpice.Op.MINUS) { unaryMinus = true; nextToken(); } Expr e; if (tokenizer.ttype == '(') { nextToken(); e = evalEq(); expect(')'); } else if (tokenizer.ttype == StreamTokenizer.TT_NUMBER) { e = parseNumber(); } else if (tokenizer.ttype == StreamTokenizer.TT_WORD) { e = parseWord(); } else if (tokenizer.ttype == '@') { if (nextToken() != StreamTokenizer.TT_WORD) throw new EvalSpice.ParseException("Bad name after @"); e = new VarExpr(Variable.newKey("ATTR_" + tokenizer.sval)); nextToken(); } else if (op != null) { throw new EvalSpice.ParseException("Operator "+op+" with no left hand operand"); } else { throw new EvalSpice.ParseException("Expected identifier"); } if (unaryMinus) e = new UnaryOpExpr(e); for (;;) { if (op == null || outerPrecedence < op.precedence) return e; if (op == EvalSpice.Op.COND) { nextToken(); Expr thenE = evalEq(Expr.MAX_PRECEDENCE - 1); expect(':'); Expr elseE = evalEq(); return new IfThenElseExpr(e, thenE, elseE); } EvalSpice.Op myOp = op; assert outerPrecedence >= myOp.precedence; nextToken(); Expr e2 = evalEq(myOp.precedence - 1); e = new BinaryOpExpr(e, myOp, e2); } } /** * Parse a number. A number may have the format: * <P> * number[g|meg|k|m|u|n|p|f] * <p> * number(e)[-]number * @return * @throws IOException * @throws ParseException */ private ConstExpr parseNumber() throws IOException, EvalSpice.ParseException { assert tokenizer.ttype == StreamTokenizer.TT_NUMBER; double val = tokenizer.nval; // peek ahead to check if exponential, or multiplier tokenizer.ordinaryChar('e'); tokenizer.ordinaryChar('E'); int tt = tokenizer.nextToken(); if (tt == 'e' || tt == 'E') { tt = tokenizer.nextToken(); boolean minus = false; if (tt == '-') { minus = true; tt = tokenizer.nextToken(); } if (tt == StreamTokenizer.TT_NUMBER) { double exp = tokenizer.nval; if (minus) exp = -1.0 * exp; val = val * Math.pow(10, exp); } else { throw new EvalSpice.ParseException("Invalid token"); } } else if (tt == StreamTokenizer.TT_WORD) { if (tokenizer.sval.equalsIgnoreCase("g")) { val = val * 1e9; } else if (tokenizer.sval.equalsIgnoreCase("meg")) { val = val * 1e6; } else if (tokenizer.sval.equalsIgnoreCase("k")) { val = val * 1e3; } else if (tokenizer.sval.equalsIgnoreCase("m")) { val = val * 1e-3; } else if (tokenizer.sval.equalsIgnoreCase("u")) { val = val * 1e-6; } else if (tokenizer.sval.equalsIgnoreCase("n")) { val = val * 1e-9; } else if (tokenizer.sval.equalsIgnoreCase("p")) { val = val * 1e-12; } else if (tokenizer.sval.equalsIgnoreCase("f")) { val = val * 1e-15; } else throw new EvalSpice.ParseException("Invalid token"); } else { tokenizer.pushBack(); } tokenizer.wordChars('e', 'e'); tokenizer.wordChars('E', 'E'); nextToken(); return new ConstExpr(new Double(val)); } private Expr parseWord() throws IOException, EvalSpice.ParseException { assert tokenizer.ttype == StreamTokenizer.TT_WORD; String id = tokenizer.sval; for (UnaryFunExpr.Fun fun : UnaryFunExpr.Fun.class.getEnumConstants()) { if (!id.equalsIgnoreCase(fun.toString()) && !id.equals("Math." + fun.toString())) continue; nextToken(); expect('('); Expr arg = evalEq(); expect(')'); return new UnaryFunExpr(fun, arg); } for (BinaryFunExpr.Fun fun : BinaryFunExpr.Fun.class.getEnumConstants()) { if (!id.equalsIgnoreCase(fun.toString()) && !id.equals("Math." + fun.toString())) continue; nextToken(); expect('('); Expr arg1 = evalEq(); expect(','); Expr arg2 = evalEq(); expect(')'); return new BinaryFunExpr(fun, arg1, arg2); } if (/*isJava &&*/ id.equals("P")) { nextToken(); expect('('); if (tokenizer.ttype != '"') throw new EvalSpice.ParseException("Bad name after @"); Variable.Key varKey = Variable.newKey(tokenizer.sval); nextToken(); expect(')'); return new VarExpr(varKey); } if (isJava && id.equals("LE.getdrive")) { nextToken(); expect('('); expect(')'); return new GetDriveExpr(); } if (isJava && id.equals("LE.subdrive")) { nextToken(); expect('('); if (tokenizer.ttype != '"') throw new EvalSpice.ParseException("Bad name after subdrive"); String instName = tokenizer.sval; nextToken(); expect(','); if (tokenizer.ttype != '"') throw new EvalSpice.ParseException("Bad name after subdrive"); String varName = tokenizer.sval; nextToken(); expect(')'); return new SubDriveExpr(instName, varName); } Variable.Key attrKey = Variable.newKey("ATTR_" + tokenizer.sval); nextToken(); return new VarExpr(attrKey); } private void expect(int token) throws IOException, EvalSpice.ParseException { if (tokenizer.ttype != token) throw new EvalSpice.ParseException("Expected token "+(char)token); nextToken(); } private int nextToken() throws IOException, EvalSpice.ParseException { switch (tokenizer.nextToken()) { case '*': op = EvalSpice.Op.MULT; break; case '/': op = EvalSpice.Op.DIV; break; case '+': op = EvalSpice.Op.PLUS; break; case '-': op = EvalSpice.Op.MINUS; break; case '<': op = EvalSpice.Op.LT; if (tokenizer.nextToken() == '=') op = EvalSpice.Op.LTOE; else tokenizer.pushBack(); break; case '>': op = EvalSpice.Op.GT; if (tokenizer.nextToken() == '=') op = EvalSpice.Op.GTOE; else tokenizer.pushBack(); break; case '=': op = EvalSpice.Op.EQ; if (tokenizer.nextToken() != '=') throw new EvalSpice.ParseException("Expected token =="); break; case '!': op = EvalSpice.Op.NE; if (tokenizer.nextToken() != '=') throw new EvalSpice.ParseException("Expected token !="); break; case '?': op = EvalSpice.Op.COND; break; case StreamTokenizer.TT_EOL: throw new EvalSpice.ParseException("Multiline expression"); case ':': case '(': case ')': case ',': case '@': case '"': case StreamTokenizer.TT_NUMBER: case StreamTokenizer.TT_WORD: case StreamTokenizer.TT_EOF: op = null; break; default: throw new EvalSpice.ParseException("Illegal character " + (char)tokenizer.ttype); } return tokenizer.ttype; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -