예제 #1
0
 private Type parseNumericalExpr(Context cntx) {
   Token leadingSign = null;
   if (cntx.peek() == Token.PLUS || cntx.peek() == Token.MINUS) leadingSign = cntx.next();
   Type type = parseNumericalTerm(cntx);
   if (leadingSign != null) {
     if (type == Type.BOOLEAN)
       error(cntx, "vmm.parser.OperatorRequiresNumerical", leadingSign == Token.PLUS ? "+" : "-");
     if (leadingSign == Token.MINUS)
       cntx.bldr.addStackOp(type == Type.REAL ? StackOp.UNARY_MINUS : StackOp.C_UNARY_MINUS);
   }
   while (cntx.peek() == Token.PLUS || cntx.peek() == Token.MINUS) {
     Token op = cntx.next();
     String opName = cntx.tokstr;
     if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     Type nextType = parseNumericalTerm(cntx);
     if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     if (type == Type.REAL && nextType == Type.COMPLEX) {
       cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX);
       type = Type.COMPLEX;
     } else if (type == Type.COMPLEX && nextType == Type.REAL)
       cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX);
     if (type == Type.REAL) cntx.bldr.addStackOp(op == Token.PLUS ? StackOp.PLUS : StackOp.MINUS);
     else cntx.bldr.addStackOp(op == Token.PLUS ? StackOp.C_PLUS : StackOp.C_MINUS);
   }
   return type;
 }
예제 #2
0
 private Type parseNumericalTerm(Context cntx) {
   Type type = parseNumericalFactor(cntx);
   while (canStartFactor.contains(cntx.peek())) {
     Token op;
     String opName;
     if (cntx.peek() == Token.TIMES || cntx.peek() == Token.DIVIDE) {
       op = cntx.next();
       opName = cntx.tokstr;
     } else {
       op = Token.TIMES;
       opName = "*";
     }
     if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     Type nextType = parseNumericalFactor(cntx);
     if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     if (type == Type.REAL && nextType == Type.COMPLEX) {
       cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX);
       type = Type.COMPLEX;
     } else if (type == Type.COMPLEX && nextType == Type.REAL)
       cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX);
     if (type == Type.REAL)
       cntx.bldr.addStackOp(op == Token.TIMES ? StackOp.TIMES : StackOp.DIVIDE);
     else cntx.bldr.addStackOp(op == Token.TIMES ? StackOp.C_TIMES : StackOp.C_DIVIDE);
   }
   return type;
 }
예제 #3
0
 private Type parseBTerm(Context cntx) {
   Type type = parseBFactor(cntx);
   while (cntx.peek() == Token.AND) {
     if (type != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "AND");
     cntx.next();
     Type nextType = parseBFactor(cntx);
     if (nextType != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "AND");
     cntx.bldr.addStackOp(StackOp.AND);
   }
   return type;
 }
예제 #4
0
 private Type parseRelation(Context cntx) {
   Type type = parseNumericalExpr(cntx);
   if (relationalOps.contains(cntx.peek())) {
     Token op = cntx.next();
     String opName = cntx.tokstr;
     if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     if (type == Type.COMPLEX && op != Token.EQUAL && op != Token.NOT_EQUAL)
       error(cntx, "vmm.parser.RelationNotDefinedForComplex", opName);
     Type nextType = parseNumericalExpr(cntx);
     if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     if (nextType == Type.COMPLEX && op != Token.EQUAL && op != Token.NOT_EQUAL)
       error(cntx, "vmm.parser.RelationNotDefinedForComplex", opName);
     if (type == Type.REAL && nextType == Type.COMPLEX) {
       cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX);
       type = Type.COMPLEX;
     }
     switch (op) {
       case EQUAL:
         cntx.bldr.addStackOp(type == Type.COMPLEX ? StackOp.C_EQ : StackOp.EQ);
         break;
       case NOT_EQUAL:
         cntx.bldr.addStackOp(type == Type.COMPLEX ? StackOp.C_NE : StackOp.NE);
         break;
       case GREATER:
         cntx.bldr.addStackOp(StackOp.GT);
         break;
       case LESS:
         cntx.bldr.addStackOp(StackOp.LT);
         break;
       case GREATER_EQUAL:
         cntx.bldr.addStackOp(StackOp.GE);
         break;
       case LESS_EQUAL:
         cntx.bldr.addStackOp(StackOp.LE);
         break;
     }
     if (relationalOps.contains(cntx.peek())) error(cntx, "vmm.parser.CantStringRelations");
     return Type.BOOLEAN;
   }
   return type;
 }
예제 #5
0
 private Type parseBFactor(Context cntx) {
   int notCount = 0;
   while (cntx.peek() == Token.NOT) {
     notCount++;
     cntx.next();
   }
   Type type = parseRelation(cntx);
   if (notCount > 0 && type != Type.BOOLEAN)
     error(cntx, "vmm.parser.OperatorRequriesBoolean", "NOT");
   if (notCount % 2 == 1) cntx.bldr.addStackOp(StackOp.NOT);
   return type;
 }
예제 #6
0
 private Type parseBExpr(Context cntx) {
   Type type = parseBTerm(cntx);
   while (cntx.peek() == Token.OR) {
     if (type != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "OR");
     cntx.next();
     Type nextType = parseBTerm(cntx);
     if (nextType != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "OR");
     cntx.bldr.addStackOp(StackOp.OR);
   }
   if (cntx.peek() == Token.QUESTION) {
     if (type != Type.BOOLEAN) error(cntx, "vmm.parser.ConditionalRequiresBoolean");
     cntx.next();
     int firstExpr = cntx.bldr.startSubProg();
     type = parseNumericalExpr(cntx);
     if (type == Type.BOOLEAN) error(cntx, "vmm.parser.ConditionalExpressionsMustBeNumerical");
     cntx.bldr.finishSubProg();
     int secondExpr = cntx.bldr.startSubProg();
     Type nextType;
     if (cntx.peek() != Token.COLON) {
       nextType = type;
       if (type == Type.REAL) cntx.bldr.addRealConstant(Double.NaN);
       else cntx.bldr.addComplexConstant(Double.NaN, Double.NaN);
     } else {
       cntx.next();
       nextType = parseBExpr(cntx);
       if (nextType == Type.BOOLEAN)
         error(cntx, "vmm.parser.ConditionalExpressionsMustBeNumerical");
       if (type == Type.COMPLEX && nextType == Type.REAL)
         cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX);
     }
     cntx.bldr.finishSubProg();
     if (type == Type.REAL && nextType == Type.COMPLEX) {
       cntx.bldr.addConditional(firstExpr, secondExpr, true);
       type = Type.COMPLEX;
     } else cntx.bldr.addConditional(firstExpr, secondExpr, false);
   }
   return type;
 }
예제 #7
0
 private Type parseNumericalFactor(Context cntx) {
   Type type = parseNumericalPrimary(cntx);
   while (cntx.peek() == Token.POWER) {
     cntx.next();
     String opName = cntx.tokstr;
     if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     Type nextType = parseNumericalPrimary(cntx);
     if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName);
     if (type == Type.REAL) {
       if (nextType == Type.COMPLEX) {
         cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX);
         type = Type.COMPLEX;
       } else if (cntx.complexOnly) {
         cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX);
         cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX);
         type = nextType = Type.COMPLEX;
       }
     }
     if (type == Type.COMPLEX && nextType == Type.REAL) cntx.bldr.addStackOp(StackOp.C_REAL_POWER);
     else if (type == Type.REAL) cntx.bldr.addStackOp(StackOp.POWER);
     else cntx.bldr.addStackOp(StackOp.C_POWER);
   }
   return type;
 }
예제 #8
0
 private Type parseNumericalPrimary(Context cntx) {
   Type type;
   Token tok = cntx.next();
   Token openingParen;
   switch (tok) {
     case NUMBER:
       cntx.bldr.addRealConstant(cntx.number);
       return Type.REAL;
     case VARIABLE:
       cntx.bldr.addVariableRef((Variable) cntx.symbol);
       return Type.REAL;
     case ARGUMENT:
       cntx.bldr.addArgumentReference(((Argument) cntx.symbol).argnum);
       return Type.REAL;
     case COMPLEX_VARIABLE:
       cntx.bldr.addComplexVariableRef((ComplexVariable) cntx.symbol);
       return Type.COMPLEX;
     case COMPLEX_ARGUMENT:
       cntx.bldr.addArgumentReference(((ComplexArgument) cntx.symbol).argnum);
       return Type.COMPLEX;
     case FUNCTION:
     case COMPLEX_FUNCTION:
     case STANDARD_FUNCTION:
     case FUNCTION_COMPLEX_TO_REAL:
       Token funcTok = tok;
       Object symbol = cntx.symbol;
       String funcName = cntx.tokstr;
       openingParen = cntx.next();
       if (openingParen != Token.LEFT_PAREN
           && openingParen != Token.LEFT_BRACE
           && openingParen != Token.LEFT_BRACKET)
         error(cntx, "vmm.parser.FunctionRequiresParen", funcName);
       int argCount = 0;
       int expectedArgs =
           funcTok == Token.FUNCTION
               ? ((Function) symbol).getArity()
               : funcTok == Token.COMPLEX_FUNCTION
                   ? ((ComplexFunction) symbol).getArity()
                   : funcTok == Token.STANDARD_FUNCTION ? 1 : 2;
       Type argType = null;
       while (true) {
         tok = cntx.peek();
         if (tok == Token.RIGHT_PAREN || tok == Token.RIGHT_BRACE || tok == Token.RIGHT_BRACKET)
           break;
         argCount++;
         if (argCount > expectedArgs) error(cntx, "vmm.parser.TooManyArguments", funcName);
         argType = parseBExpr(cntx);
         if (funcTok == Token.FUNCTION || funcTok == Token.FUNCTION_COMPLEX_TO_REAL) {
           if (argType != Type.REAL) error(cntx, "vmm.parser.NeedRealArgument", funcName);
         } else if (funcTok == Token.COMPLEX_FUNCTION) {
           if (argType == Type.BOOLEAN) error(cntx, "vmm.parser.NeedComplexArgument", funcName);
           if (argType == Type.REAL) cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX);
         } else if (funcTok == Token.STANDARD_FUNCTION) {
           StandardFunction f = (StandardFunction) symbol;
           if (argType == Type.COMPLEX) {
             if (f.getComplexArgOp() == null) error(cntx, "vmm.parser.NeedRealArgument", funcName);
           } else if (argType == Type.REAL) {
             if (f.getRealArgOp() == null
                 || (cntx.complexOnly && needRealToComplex.contains(f.getRealArgOp()))) {
               cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX);
               argType = Type.COMPLEX;
             }
           } else { // argType is boolean
             if (f.getRealArgOp() == null
                 || (cntx.complexOnly && needRealToComplex.contains(f.getRealArgOp())))
               error(cntx, "vmm.parser.NeedComplexArgument", funcName);
             else error(cntx, "vmm.parser.NeedRealArgument", funcName);
           }
         }
         tok = cntx.peek();
         if (tok != Token.COMMA) break;
         cntx.next();
       }
       tok = cntx.next();
       if (argCount < expectedArgs) error(cntx, "vmm.parser.NotEnoughArguments", funcName);
       if (openingParen == Token.LEFT_PAREN && tok != Token.RIGHT_PAREN)
         error(cntx, "vmm.parser.MissingCloseOfArgumentList", ")");
       if (openingParen == Token.LEFT_BRACE && tok != Token.RIGHT_BRACE)
         error(cntx, "vmm.parser.MissingCloseOfArgumentList", "}");
       if (openingParen == Token.LEFT_BRACKET && tok != Token.RIGHT_BRACKET)
         error(cntx, "vmm.parser.MissingCloseOfArgumentList", "]");
       if (funcTok == Token.FUNCTION) {
         cntx.bldr.addFunctionRef(((Function) symbol).getProgFunction());
         return Type.REAL;
       } else if (funcTok == Token.COMPLEX_FUNCTION) {
         cntx.bldr.addFunctionRef(((ComplexFunction) symbol).getProgFunction());
         return Type.COMPLEX;
       } else if (funcTok == Token.FUNCTION_COMPLEX_TO_REAL) return Type.COMPLEX;
       else {
         StandardFunction f = (StandardFunction) symbol;
         cntx.bldr.addStackOp(argType == Type.COMPLEX ? f.getComplexArgOp() : f.getRealArgOp());
         return argType == Type.COMPLEX
             ? f.getReturnTypeForComplexArg()
             : f.getReturnTypeForRealArg();
       }
     case LEFT_PAREN:
       type = parseBExpr(cntx);
       tok = cntx.next();
       if (tok == Token.EOS) error(cntx, "vmm.parser.MissingRightGroupThingAtEOS", ")", "(");
       if (tok != Token.RIGHT_PAREN)
         error(cntx, "vmm.parser.MissingRightGroupThing", ")", "(", cntx.tokstr);
       return type;
     case LEFT_BRACE:
       type = parseBExpr(cntx);
       tok = cntx.next();
       if (tok == Token.EOS) error(cntx, "vmm.parser.MissingRightGroupThingAtEOS", "]", "[");
       if (tok != Token.RIGHT_BRACE)
         error(cntx, "vmm.parser.MissingRightGroupThing", "]", "[", cntx.tokstr);
       return type;
     case LEFT_BRACKET:
       type = parseBExpr(cntx);
       tok = cntx.next();
       if (tok == Token.EOS) error(cntx, "vmm.parser.MissingRightGroupThingAtEOS", "}", "{");
       if (tok != Token.RIGHT_PAREN)
         error(cntx, "vmm.parser.MissingRightGroupThing", "}", "{", cntx.tokstr);
       return type;
     case RIGHT_PAREN:
       error(cntx, "vmm.parser.ExtraRightGroupThing", ")", "(");
       return null;
     case RIGHT_BRACE:
       error(cntx, "vmm.parser.ExtraRightGroupThing", "}", "{");
       return null;
     case RIGHT_BRACKET:
       error(cntx, "vmm.parser.ExtraRightGroupThing", "]", "[");
       return null;
     case UNKNOWN_CHAR:
       error(cntx, "vmm.parser.UnknownChar", cntx.tokstr);
       return null;
     case UNKNOWN_WORD:
       error(cntx, "vmm.parser.UndefinedWord", cntx.tokstr);
       return null;
     case ILLEGAL_NUMBER:
       error(cntx, "vmm.parser.IllegalNumber", cntx.tokstr);
       return null;
     case EOS:
       error(cntx, "vmm.parser.IncompleteExpression");
     default:
       error(cntx, "vmm.parser.UnexcpectedToken", cntx.tokstr);
       return null;
   }
 }
예제 #9
0
 private Type doParse(Context cntx) {
   if (cntx.peek() == Token.EOS) error(cntx, "vmm.parser.EmpytDefinition");
   Type type = parseBExpr(cntx);
   if (cntx.peek() != Token.EOS) error(cntx, "vmm.parser.ExtraStuff");
   return type;
 }