⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evaluator.java

📁 外国人写的c#语法解析器
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/**
 * Soft Gems Resource parser. Created by Mike Lischke.
 * 
 * The source code in this file can freely be used for any purpose provided this notice remains 
 * unchanged in the file.
 * 
 * Copyright 2004 by Mike Lischke, www.soft-gems.net, public@soft-gems.net. All rights reserved.
 */

package net.softgems.resourceparser.expressions;

import java.math.BigInteger;
import java.util.StringTokenizer;

import antlr.collections.AST;

/** 
 * Evaluates an expression contained in an AST.
 */
public class Evaluator
{
  private static ISymbolTable symbols;
  /** If <b>true</b> then unresolvable symbols are assumed to be integers with value 0. */
  private static boolean implicitSymbols;
  
  //------------------------------------------------------------------------------------------------
  
  private Evaluator()
  {
    // Using a private contructor to prevent instantiation.
    // Using class as a simple static utility class.
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is of type boolen and throws an exception if not.
   * 
   * @param value The value to check.
   */
  private static void checkBoolean(Object value)
  {
    checkEmpty(value);
    if (!isBoolean(value))
      showError("Boolean value expected, but " + value.toString() + " found.");
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Checks if value is assigned.
   * 
   * @param value The value to check.
   */
  private static void checkEmpty(Object value)
  {
    if (value == null)
      showError("Internal error. Empty expression value encountered.");
  }

  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is an integer type and throws an exception if not.
   * 
   * @param value The class to check.
   */
  private static void checkInteger(Object value)
  {
    checkEmpty(value);
    if (!isInteger(value))
      showError("Integer value expected, but " + value.toString() + " found.");
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is a float or integer type and throws an exception if not.
   * 
   * @param value The class to check.
   */
  private static void checkNumber(Object value)
  {
    checkEmpty(value);
    if (!isNumber(value))
      showError("Number value expected, but " + value.toString() + " found.");
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is a character or string type and throws an exception if not.
   * 
   * @param value The class to check.
   */
  private static void checkString(Object value)
  {
    checkEmpty(value);
    if (!isString(value))
      showError("Character literal or string value expected, but " + value.toString() + " found.");
  }

  //------------------------------------------------------------------------------------------------
  
  /**
   * Checks the class of the given value whether it is derived from the class given in <b>classType</b>.
   * It throws an exception if it does not correspond.
   * 
   * @param value The value to check.
   * @param classType The type to check against.
   */
  private static void checkType(Object value, Class classType)
  {
    checkEmpty(value);
    if (!isBoolean(value))
      showError(classType.toString() + " expected but " + value.toString() + " found.");
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is a boolean type.
   * 
   * @param value The class to check.
   * @return <b>true</b> if the value is a boolean value, otherwise <b>false</b>.
   */
  private static boolean isBoolean(Object value)
  {
    return (value instanceof Boolean);
  }

  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is of type float, that is, Float or Double.
   * 
   * @param value The class to check.
   * @return <b>true</b> if the value is a float value, otherwise <b>false</b>.
   */
  private static boolean isFloat(Object value)
  {
    return (value instanceof Float || value instanceof Double);
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is an integer type, that is, Byte, Integer, Long or Short.
   * 
   * @param value The class to check.
   * @return <b>true</b> if the value is an integer value, otherwise <b>false</b>.
   */
  private static boolean isInteger(Object value)
  {
    return (value instanceof Byte || value instanceof Integer || value instanceof Long || 
      value instanceof Short);
  }

  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is an integer type, that is, Byte, Integer, Long or Short.
   * 
   * @param value The class to check.
   * @return <b>true</b> if the value is a number value, otherwise <b>false</b>.
   */
  private static boolean isNumber(Object value)
  {
    return (isFloat(value) || isInteger(value));
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Determines if value is an integer type, that is, Byte, Integer, Long or Short.
   * 
   * @param value The class to check.
   * @return <b>true</b> if the value is a character or string value, otherwise <b>false</b>.
   */
  private static boolean isString(Object value)
  {
    return (value instanceof Character || value instanceof String);
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Does a lookup on the symbol table to find the predefined value for the given identifier.
   * 
   * @param symbol The identifier to look up.
   * @param node The node for which a value must be looked up. Contains location info for error messages.
   * @return The value of the identifier.
   */
  private static Object lookupValue(String symbol, AST node)
  {
    if (symbols == null || !symbols.isDefined(symbol))
    {
      if (implicitSymbols)
        return new Integer(0);
      else
      {
        showError("Undeclared identifier \"" + symbol + "\"");
        return null;
      }
    }
    
    return symbols.lookup(symbol, node.getLine(), node.getColumn());
  }

  //------------------------------------------------------------------------------------------------
  
  /**
   * Handles all forms of a long integer. Due to various suffixes this requires a bit extra work.
   * Fortunately, hexadecimal and octal number parsing is done by the decode method implicitly.
   * 
   * @param node The node containing the value as string.
   * @return The parsed Integer.
   */
  private static Object parserIntegerType(AST node)
  {
    String raw = node.getText().toLowerCase();
    
    // Remove any suffix. We cannot distinct between pure negative and positive types anyway.
    if (raw.endsWith("i128") || raw.endsWith("u128"))
      return new BigInteger(raw.substring(0, raw.length() - 4));
    else
      if (raw.endsWith("i64") || raw.endsWith("u64"))
        return Long.decode(raw.substring(0, raw.length() - 3));
      else
        if (raw.endsWith("i32") || raw.endsWith("u32") || raw.endsWith("ul"))
          return Integer.decode(raw.substring(0, raw.length() - 3));
        else
          if (raw.endsWith("i16") || raw.endsWith("u16"))
            return Short.decode(raw.substring(0, raw.length() - 3));
          else
            if (raw.endsWith("i8") || raw.endsWith("u8"))
              return Byte.decode(raw.substring(0, raw.length() - 2));
            else
              if (raw.endsWith("l") || raw.endsWith("u"))
                return Long.decode(raw.substring(0, raw.length() - 1));
              else
                return Long.decode(raw);
  }

  //------------------------------------------------------------------------------------------------
  
  /**
   * Evaluates the given AST into a scalar value.
   * 
   * @param node The (sub) AST to evaluate.
   * @return An object, which encapsulates a scalar value.
   */
  private static Object process(AST node)
  {
    if (node == null)
      return null;
    else
    {
      AST left = node.getFirstChild();
      AST right = null;
      if (left != null)
        right = left.getNextSibling();
      Object leftValue = null;
      Object result = null;
      try
      {
        switch (node.getType())
        {
          // Node values.
          case ExpressionLexerTokenTypes.CHARACTER_LITERAL:
            result = new Character(node.getText().charAt(0));
            break;
          case ExpressionLexerTokenTypes.STRING_LITERAL:
            result = processStringLiteral(node.getText());
            break;
          case ExpressionLexerTokenTypes.IDENTIFIER:
            result = lookupValue(node.getText(), node);
            break;
          case ExpressionLexerTokenTypes.FLOAT_LITERAL:
            result = new Float(node.getText());
            break;
          case ExpressionLexerTokenTypes.DOUBLE_LITERAL:
            result = new Double(node.getText());
            break;
          case ExpressionLexerTokenTypes.HEX_LITERAL:
          case ExpressionLexerTokenTypes.OCTAL_LITERAL:
          case ExpressionLexerTokenTypes.BYTE_LITERAL:
          case ExpressionLexerTokenTypes.SHORT_LITERAL:
          case ExpressionLexerTokenTypes.INTEGER_LITERAL:
          case ExpressionLexerTokenTypes.LONG_LITERAL:
          case ExpressionLexerTokenTypes.BIGINT_LITERAL:
            result = parserIntegerType(node);
            break;
          case ExpressionLexerTokenTypes.NUMERAL:
            result = new Integer(node.getText());
            break;
          case ExpressionLexerTokenTypes.LITERAL_true:
            result = new Boolean(true);
            break;
          case ExpressionLexerTokenTypes.LITERAL_false:
            result = new Boolean(false);
            break;
          default:
          {
            leftValue = process(left);

            // Handle non-terminals.
            switch (node.getType())
            {
              // Unary operations.
              case ExpressionLexerTokenTypes.LOGICAL_NOT:
                result = processLogicalNot(leftValue);
                break;
              case ExpressionLexerTokenTypes.BITWISE_NOT:
                result = processBitwiseNot(leftValue);
                break;
              case ExpressionLexerTokenTypes.INC:
              case ExpressionLexerTokenTypes.POST_INC:
                result = processInc(leftValue);
                break;
              case ExpressionLexerTokenTypes.DEC:
              case ExpressionLexerTokenTypes.POST_DEC:
                result = processDec(leftValue);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -