xeij/ExpressionEvaluator.java (2/2)
1 2


  //--------------------------------------------------------------------------------
  //  1引数関数
  protected ExpressionElement evxParseFunctionFloatFloat (ExpressionElement elem, LinkedList<ExpressionElement> tokenList, int mode) {
    return evxParseFunction1 (elem, tokenList,
                              ElementType.ETY_FLOAT, ElementType.ETY_FLOAT, mode);
  }  //evxParseFunctionFloatFloat
  protected ExpressionElement evxParseFunctionFloatString (ExpressionElement elem, LinkedList<ExpressionElement> tokenList, int mode) {
    return evxParseFunction1 (elem, tokenList,
                              ElementType.ETY_FLOAT, ElementType.ETY_STRING, mode);
  }  //evxParseFunctionFloatString
  protected ExpressionElement evxParseFunctionStringFloat (ExpressionElement elem, LinkedList<ExpressionElement> tokenList, int mode) {
    return evxParseFunction1 (elem, tokenList,
                              ElementType.ETY_STRING, ElementType.ETY_FLOAT, mode);
  }  //evxParseFunctionStringFloat
  protected ExpressionElement evxParseFunction1 (ExpressionElement elem, LinkedList<ExpressionElement> tokenList,
                                                 ElementType valueType, ElementType paramTypeX, int mode) {
    ExpressionElement commaOrParen = tokenList.pollFirst ();  //(
    if (commaOrParen == null || commaOrParen.exlType != ElementType.ETY_TOKEN_LEFT_PARENTHESIS) {  //(がない
      evxPrintError (Multilingual.mlnJapanese ?
                     "( がありません" :
                     "( is not found",
                     elem.exlSource, -1, 1);
      return null;
    }
    ExpressionElement paramX = evxParseAssignment (tokenList, mode);  //コンマ演算子の次に優先順位の低い演算子
    if (paramX == null) {
      return null;
    }
    if (paramX.exlValueType != paramTypeX) {  //1番目の引数の型が違う
      evxPrintError (Multilingual.mlnJapanese ?
                     "1 番目の引数の型が違います" :
                     "wrong type of the 1st parameter",
                     paramX.exlSource, paramX.exlOffset, paramX.exlLength);
      return null;
    }
    commaOrParen = tokenList.pollFirst ();  //)
    if (commaOrParen == null || commaOrParen.exlType != ElementType.ETY_TOKEN_RIGHT_PARENTHESIS) {  //)がない
      evxPrintError (Multilingual.mlnJapanese ?
                     ") がありません" :
                     ") is not found",
                     elem.exlSource, -1, 1);
      return null;
    }
    elem.exlValueType = valueType;
    elem.exlParamX = paramX;
    elem.exlParamY = null;
    elem.exlParamZ = null;
    elem.exlLength = commaOrParen.exlOffset + commaOrParen.exlLength - elem.exlOffset;
    return elem;
  }  //evxParseFunction1


  //--------------------------------------------------------------------------------
  //  2引数関数
  protected ExpressionElement evxParseFunctionFloatFloatFloat (ExpressionElement elem, LinkedList<ExpressionElement> tokenList, int mode) {
    return evxParseFunction2 (elem, tokenList,
                              ElementType.ETY_FLOAT, ElementType.ETY_FLOAT, ElementType.ETY_FLOAT, mode);
  }  //evxParseFunctionFloatFloatFloat
  protected ExpressionElement evxParseFunction2 (ExpressionElement elem, LinkedList<ExpressionElement> tokenList,
                                                 ElementType valueType, ElementType paramTypeX, ElementType paramTypeY, int mode) {
    ExpressionElement commaOrParen = tokenList.pollFirst ();  //(
    if (commaOrParen == null || commaOrParen.exlType != ElementType.ETY_TOKEN_LEFT_PARENTHESIS) {  //(がない
      evxPrintError (Multilingual.mlnJapanese ?
                     "( がありません" :
                     "( is not found",
                     elem.exlSource, -1, 1);
      return null;
    }
    ExpressionElement paramX = evxParseAssignment (tokenList, mode);  //コンマ演算子の次に優先順位の低い演算子
    if (paramX == null) {
      return null;
    }
    if (paramX.exlValueType != paramTypeX) {  //1番目の引数の型が違う
      evxPrintError (Multilingual.mlnJapanese ?
                     "1 番目の引数の型が違います" :
                     "wrong type of the 1st parameter",
                     paramX.exlSource, paramX.exlOffset, paramX.exlLength);
      return null;
    }
    commaOrParen = tokenList.pollFirst ();  //,
    if (commaOrParen == null || commaOrParen.exlType != ElementType.ETY_OPERATOR_COMMA) {  //,がない
      evxPrintError (Multilingual.mlnJapanese ?
                     ", がありません" :
                     ", is not found",
                     elem.exlSource, -1, 1);
      return null;
    }
    ExpressionElement paramY = evxParseAssignment (tokenList, mode);  //コンマ演算子の次に優先順位の低い演算子
    if (paramY == null) {
      return null;
    }
    if (paramX.exlValueType != paramTypeY) {  //2番目の引数の型が違う
      evxPrintError (Multilingual.mlnJapanese ?
                     "2 番目の引数の型が違います" :
                     "wrong type of the 2nd parameter",
                     paramY.exlSource, paramY.exlOffset, paramY.exlLength);
      return null;
    }
    commaOrParen = tokenList.pollFirst ();  //)
    if (commaOrParen == null || commaOrParen.exlType != ElementType.ETY_TOKEN_RIGHT_PARENTHESIS) {  //)がない
      evxPrintError (Multilingual.mlnJapanese ?
                     ") がありません" :
                     ") is not found",
                     elem.exlSource, -1, 1);
      return null;
    }
    elem.exlValueType = valueType;
    elem.exlParamX = paramX;
    elem.exlParamY = paramY;
    elem.exlParamZ = null;
    elem.exlLength = commaOrParen.exlOffset + commaOrParen.exlLength - elem.exlOffset;
    return elem;
  }  //evxParseFunction2


  //--------------------------------------------------------------------------------
  //  @演算子
  protected ExpressionElement evxParseAt (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParsePrimitive (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_AT:  // x@y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParsePrimitive (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "アドレスの型が違います" :
                       "wrong type of the address",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "ファンクションコードの型が違います" :
                       "wrong type of the function code",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseAt


  //--------------------------------------------------------------------------------
  //  後置演算子
  protected ExpressionElement evxParsePostfix (LinkedList<ExpressionElement> tokenList, int mode) {

    ExpressionElement paramX = evxParseAt (tokenList, mode);
    if (paramX == null) {
      return null;
    }

    for (ExpressionElement operator = tokenList.peekFirst ();
         operator != null;
         operator = tokenList.peekFirst ()) {

      //ポストインクリメントまたはポストデクリメント
      //    x++
      //    x--
      if (operator.exlType == ElementType.ETY_TOKEN_PLUS_PLUS ||  // x++
          operator.exlType == ElementType.ETY_TOKEN_MINUS_MINUS) {  // x--
        tokenList.pollFirst ();  // ++または--
        if (paramX.exlValueType != ElementType.ETY_FLOAT) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "引数の型が違います" :
                         "wrong type of parameter",
                         operator.exlSource, operator.exlOffset, operator.exlLength);
          return null;
        }
        if (mode == EVM_ASSEMBLER) {  //アセンブラモード
          evxPrintError (Multilingual.mlnJapanese ?
                         "副作用を起こす演算子はここでは使えません" :
                         "operators which cause a side effect is unusable here",
                         operator.exlSource, operator.exlOffset, operator.exlLength);
          return null;
        }
        if (!paramX.exlIsFloatSubstituend ()) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "引数が場所を示していません" :
                         "parameter is not indicating a location",
                         operator.exlSource, operator.exlOffset, operator.exlLength);
          return null;
        }
        paramX = new ExpressionElement (
          operator.exlType == ElementType.ETY_TOKEN_PLUS_PLUS ?
          ElementType.ETY_OPERATOR_POSTINCREMENT :
          ElementType.ETY_OPERATOR_POSTDECREMENT, 0,
          ElementType.ETY_FLOAT, null, null,
          paramX.exlSource, paramX.exlOffset, operator.exlOffset + operator.exlLength - paramX.exlOffset,
          paramX, null, null);
        continue;
      }  //if x++ x--

      if (mode != EVM_ASSEMBLER) {  //アセンブラモード以外
        break;
      }

      //アセンブラモード

      //ディスプレースメントまたはインデックスレジスタのサイズ
      //    x.w
      //    x.l
      if ((operator.exlType == ElementType.ETY_OPERATOR_SIZE_WORD ||
           operator.exlType == ElementType.ETY_OPERATOR_SIZE_LONG) &&  // .wまたは.l
          (paramX.exlValueType == ElementType.ETY_FLOAT ||  //ディスプレースメント
           paramX.exlType == ElementType.ETY_INTEGER_REGISTER)) {  //インデックスレジスタ
        tokenList.pollFirst ();  // .wまたは.l
        paramX = new ExpressionElement (
          ElementType.ETY_SIZE, operator.exlSubscript,
          ElementType.ETY_UNDEF, null, null,
          paramX.exlSource, paramX.exlOffset, operator.exlOffset + operator.exlLength - paramX.exlOffset,
          paramX, null, null);
        continue;
      }  //if x.wまたはx.l

      //括弧の左側に書かれたディスプレースメント
      //  浮動小数点数またはサイズ付き浮動小数点数の直後に(があるときディスプレースメントとみなして括弧の中に入れる
      //    x() → (x)  この括弧は省略できない括弧なので(x,za0,zd0.w*1)になる
      //    x(y) → (x,y)
      //    x(y,z) → (x,y,z)
      if ((paramX.exlValueType == ElementType.ETY_FLOAT ||  // x
           (paramX.exlType == ElementType.ETY_SIZE &&
            paramX.exlParamX.exlValueType == ElementType.ETY_FLOAT)) &&  // x.wまたはx.l
          operator.exlType == ElementType.ETY_TOKEN_LEFT_PARENTHESIS) {  // x(またはx.w(またはx.l(
        tokenList.pollFirst ();  // (
        ExpressionElement commaRight = tokenList.peekFirst ();  // )
        if (commaRight != null && commaRight.exlType != ElementType.ETY_TOKEN_RIGHT_PARENTHESIS) {  // x(の直後に)以外のものがある
          for (;;) {
            //右辺
            ExpressionElement paramY = evxParseColon (tokenList, mode);
            if (paramY == null) {
              return null;
            }
            paramX = new ExpressionElement (
              ElementType.ETY_OPERATOR_COMMA, 0,
              paramY.exlValueType, null, null,
              paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
              paramX, paramY, null);
            commaRight = tokenList.peekFirst ();  // ,または)
            if (commaRight == null || commaRight.exlType != ElementType.ETY_TOKEN_COMMA) {  // ,が続いていない
              break;
            }
            tokenList.pollFirst ();  // ,
          }
        }
        if (commaRight == null || commaRight.exlType != ElementType.ETY_TOKEN_RIGHT_PARENTHESIS) {  // )がない
          evxPrintError (Multilingual.mlnJapanese ?
                         "(...) が閉じていません" :
                         "(...) is not closed",
                         paramX.exlSource, paramX.exlOffset, paramX.exlLength);
          return null;
        }
        tokenList.pollFirst ();  // )
        paramX = new ExpressionElement (
          ElementType.ETY_PARENTHESIS, 0,
          ElementType.ETY_UNDEF, null, null,
          paramX.exlSource, paramX.exlOffset, commaRight.exlOffset + commaRight.exlLength - paramX.exlOffset,
          paramX, null, null);
        continue;
      }  //if x(またはx.w(またはx.l(

      //ビットフィールドまたはk-factor
      //    <ea>{offset:width}
      //    <ea>{k-factor}
      if (operator.exlType == ElementType.ETY_TOKEN_LEFT_CURLY_BRACKET) {  // <ea>{
        tokenList.pollFirst ();  // {
        ExpressionElement paramY = evxParseAssignment (tokenList, mode);  // offsetまたはk-factor
        if (paramY == null) {
          return null;
        }
        ExpressionElement colon = tokenList.peekFirst ();  // :または}
        if (colon == null) {  // <ea>{offset:または<ea>{k-factor}のいずれでもない
          evxPrintError (Multilingual.mlnJapanese ?
                         "不完全なビットフィールドまたは k-factor" :
                         "incomplete bit-field or k-factor",
                         operator.exlSource, operator.exlOffset, paramY.exlOffset + paramY.exlLength - operator.exlOffset);
          return null;
        }
        tokenList.pollFirst ();  // :または}
        if (colon.exlType == ElementType.ETY_TOKEN_COLON) {  // <ea>{offset:
          //ビットフィールド
          ExpressionElement paramZ = evxParseAssignment (tokenList, mode);  // width
          if (paramZ == null) {
            return null;
          }
          ExpressionElement right = tokenList.peekFirst ();  // }
          if (right == null || right.exlType != ElementType.ETY_TOKEN_RIGHT_CURLY_BRACKET) {  // <ea>{offset:widthの後に}がない
            evxPrintError (Multilingual.mlnJapanese ?
                           "不完全なビットフィールド" :
                           "incomplete bit-field",
                           operator.exlSource, operator.exlOffset, paramZ.exlOffset + paramZ.exlLength - operator.exlOffset);
            return null;
          }
          tokenList.pollFirst ();  // }
          if (!(paramY.exlValueType == ElementType.ETY_FLOAT ||  //浮動小数点数または
                paramY.exlType == ElementType.ETY_IMMEDIATE ||  //イミディエイトまたは
                (paramY.exlType == ElementType.ETY_INTEGER_REGISTER && paramY.exlSubscript < 8))) {  //データレジスタのいずれでもない
            evxPrintError (Multilingual.mlnJapanese ?
                           "ビットフィールドのオフセットの型が違います" :
                           "wrong type of bit-field offset",
                           paramY.exlSource, paramY.exlOffset, paramY.exlLength);
          }
          if (!(paramZ.exlValueType == ElementType.ETY_FLOAT ||  //浮動小数点数または
                paramZ.exlType == ElementType.ETY_IMMEDIATE ||  //イミディエイトまたは
                (paramZ.exlType == ElementType.ETY_INTEGER_REGISTER && paramZ.exlSubscript < 8))) {  //データレジスタのいずれでもない
            evxPrintError (Multilingual.mlnJapanese ?
                           "ビットフィールドの幅の型が違います" :
                           "wrong type of bit-field width",
                           paramZ.exlSource, paramZ.exlOffset, paramZ.exlLength);
          }
          paramX = new ExpressionElement (
            ElementType.ETY_BIT_FIELD, 0,
            ElementType.ETY_UNDEF, null, null,
            paramX.exlSource, paramX.exlOffset, right.exlOffset + right.exlLength - paramX.exlOffset,
            paramX, paramY, paramZ);
          continue;
        }
        if (colon.exlType == ElementType.ETY_TOKEN_RIGHT_CURLY_BRACKET) {  // <ea>{k-factor}
          //k-factor
          if (!(paramY.exlValueType == ElementType.ETY_FLOAT ||  //浮動小数点数または
                paramY.exlType == ElementType.ETY_IMMEDIATE ||  //イミディエイトまたは
                (paramY.exlType == ElementType.ETY_INTEGER_REGISTER && paramY.exlSubscript < 8))) {  //データレジスタのいずれでもない
            evxPrintError (Multilingual.mlnJapanese ?
                           "k-factor の型が違います" :
                           "wrong type of k-factor",
                           paramY.exlSource, paramY.exlOffset, paramY.exlLength);
          }
          paramX = new ExpressionElement (
            ElementType.ETY_K_FACTOR, 0,
            ElementType.ETY_UNDEF, null, null,
            paramX.exlSource, paramX.exlOffset, colon.exlOffset + colon.exlLength - paramX.exlOffset,
            paramX, paramY, null);
          continue;
        }
        // <ea>{offset:または<ea>{k-factor}のいずれでもない
        evxPrintError (Multilingual.mlnJapanese ?
                       "不完全なビットフィールドまたは k-factor" :
                       "incomplete bit-field or k-factor",
                       operator.exlSource, operator.exlOffset, paramY.exlOffset + paramY.exlLength - operator.exlOffset);
        return null;
      }  //if <ea>{

      break;
    }  //for

    return paramX;

  }  //evxParsePostfix


  //--------------------------------------------------------------------------------
  //  前置演算子
  protected ExpressionElement evxParsePrefix (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement operator = tokenList.peekFirst ();
    if (operator == null) {
      return null;
    }
    ElementType type = operator.exlType;
    if (type == ElementType.ETY_TOKEN_PLUS_PLUS) {  // ++x
      type = ElementType.ETY_OPERATOR_PREINCREMENT;
    } else if (type == ElementType.ETY_TOKEN_MINUS_MINUS) {  // --x
      type = ElementType.ETY_OPERATOR_PREDECREMENT;
    } else if (type == ElementType.ETY_TOKEN_PLUS_SIGN) {  // +x
      type = ElementType.ETY_OPERATOR_NOTHING;
    } else if (type == ElementType.ETY_TOKEN_HYPHEN_MINUS) {  //-x
      type = ElementType.ETY_OPERATOR_NEGATION;
    } else if (type == ElementType.ETY_TOKEN_TILDE) {  // ~x
      type = ElementType.ETY_OPERATOR_BITWISE_NOT;
    } else if (type == ElementType.ETY_TOKEN_EXCLAMATION_MARK) {  // !x
      type = ElementType.ETY_OPERATOR_LOGICAL_NOT;
    } else if (mode == EVM_ASSEMBLER &&  //アセンブラモード
               type == ElementType.ETY_TOKEN_NUMBER_SIGN) {  // #x
      type = ElementType.ETY_IMMEDIATE;
    } else {
      return evxParsePostfix (tokenList, mode);
    }
    tokenList.pollFirst ();
    ExpressionElement paramX = evxParsePrefix (tokenList, mode);  //右から結合するので自分を呼ぶ
    if (paramX == null) {
      return null;
    }
    if (mode == EVM_ASSEMBLER &&  //アセンブラモード
        type == ElementType.ETY_OPERATOR_NEGATION &&
        paramX.exlType == ElementType.ETY_REGISTER_INDIRECT &&
        8 <= paramX.exlSubscript) {  // -(Ar)
      return new ExpressionElement (
        ElementType.ETY_PREDECREMENT, paramX.exlSubscript - 8,
        ElementType.ETY_UNDEF, null, null,
        operator.exlSource, operator.exlOffset, paramX.exlOffset + paramX.exlLength - operator.exlOffset,
        null, null, null);
    }
    if (paramX.exlValueType != ElementType.ETY_FLOAT) {
      evxPrintError (Multilingual.mlnJapanese ?
                     "引数の型が違います" :
                     "wrong type of parameter",
                     operator.exlSource, operator.exlOffset, operator.exlLength);
      return null;
    }
    if (type == ElementType.ETY_OPERATOR_PREINCREMENT ||  // ++x
        type == ElementType.ETY_OPERATOR_PREDECREMENT) {  // --x
      if (mode == EVM_ASSEMBLER) {  //アセンブラモード
        evxPrintError (Multilingual.mlnJapanese ?
                       "副作用を起こす演算子はここでは使えません" :
                       "operators which cause a side effect is unusable here",
                       operator.exlSource, operator.exlOffset, operator.exlLength);
        return null;
      }
      if (!paramX.exlIsFloatSubstituend ()) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "引数が場所を示していません" :
                       "parameter is not indicating a location",
                       operator.exlSource, operator.exlOffset, operator.exlLength);
        return null;
      }
    }
    return new ExpressionElement (
      type, 0,
      ElementType.ETY_FLOAT, null, null,
      operator.exlSource, operator.exlOffset, paramX.exlOffset + paramX.exlLength - operator.exlOffset,
      paramX, null, null);
  }  //evxParsePrefix


  //--------------------------------------------------------------------------------
  //  累乗演算子
  protected ExpressionElement evxParseExponentiation (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParsePrefix (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    if (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_POWER:  // x**y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseExponentiation (tokenList, mode);  //右から結合するので自分を呼ぶ
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      return elem;
    }
    return paramX;
  }  //evxParseExponentiation


  //--------------------------------------------------------------------------------
  //  乗除算演算子
  protected ExpressionElement evxParseMultiplication (LinkedList<ExpressionElement> tokenList, int mode) {
    //左辺
    ExpressionElement paramX = evxParseExponentiation (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    for (ExpressionElement operator = tokenList.peekFirst ();
         operator != null;
         operator = tokenList.peekFirst ()) {
      ElementType type = operator.exlType;
      if (type == ElementType.ETY_TOKEN_ASTERISK) {  // x*y
        type = ElementType.ETY_OPERATOR_MULTIPLICATION;
      } else if (type == ElementType.ETY_TOKEN_SOLIDUS) {  // x/y
        type = ElementType.ETY_OPERATOR_DIVISION;
      } else if (type == ElementType.ETY_TOKEN_PERCENT_SIGN) {  // x%y
        type = ElementType.ETY_OPERATOR_MODULUS;
      } else {
        break;
      }
      tokenList.pollFirst ();  // *または/または%
      //右辺
      ExpressionElement paramY = evxParseExponentiation (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType == ElementType.ETY_FLOAT &&
          paramY.exlValueType == ElementType.ETY_FLOAT) {  //両辺が浮動小数点数なので普通の演算
        paramX = new ExpressionElement (
          type, 0,
          ElementType.ETY_FLOAT, null, null,
          paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
          paramX, paramY, null);
        continue;
      }
      if (mode == EVM_ASSEMBLER) {  //アセンブラモード
        //  乗算かつ左辺がRnまたはRn.WまたはRn.Lかつ右辺が浮動小数点数ときスケールファクタとみなす
        if (type == ElementType.ETY_OPERATOR_MULTIPLICATION &&  //乗算かつ
            (paramX.exlType == ElementType.ETY_INTEGER_REGISTER ||  // 左辺がRnまたは
             (paramX.exlType == ElementType.ETY_SIZE &&
              paramX.exlParamX.exlType == ElementType.ETY_INTEGER_REGISTER)) &&  // Rn.WまたはRn.Lかつ
            paramY.exlValueType == ElementType.ETY_FLOAT) {  //右辺が浮動小数点数
          paramX = new ExpressionElement (
            ElementType.ETY_SCALE_FACTOR, 0,
            ElementType.ETY_UNDEF, null, null,
            paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
            paramX, paramY, null);
          continue;
        }
        if (type == ElementType.ETY_OPERATOR_MULTIPLICATION &&  //乗算かつ
            (paramY.exlType == ElementType.ETY_INTEGER_REGISTER ||  // 右辺がRnまたは
             (paramY.exlType == ElementType.ETY_SIZE &&
              paramY.exlParamX.exlType == ElementType.ETY_INTEGER_REGISTER)) &&  // Rn.WまたはRn.Lかつ
            paramX.exlValueType == ElementType.ETY_FLOAT) {  //左辺が浮動小数点数
          paramX = new ExpressionElement (
            ElementType.ETY_SCALE_FACTOR, 0,
            ElementType.ETY_UNDEF, null, null,
            paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
            paramY, paramX, null);
          continue;
        }
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
      } else {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
      }
      return null;
    }  //for operator
    return paramX;
  }  //evxParseMultiplication


  //--------------------------------------------------------------------------------
  //  加減算演算子
  protected ExpressionElement evxParseAddition (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseMultiplication (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement operator = tokenList.peekFirst ();
    while (operator != null) {
      ElementType type = operator.exlType;
      ElementType valueType = paramX.exlValueType;
      ExpressionElement paramY;
      if (type == ElementType.ETY_TOKEN_PLUS_SIGN) {  // x+y
        tokenList.pollFirst ();  // +
        if (mode == EVM_ASSEMBLER &&
            paramX.exlType == ElementType.ETY_REGISTER_INDIRECT &&
            8 <= paramX.exlSubscript) {  // (Ar)+
          return new ExpressionElement (
            ElementType.ETY_POSTINCREMENT, paramX.exlSubscript - 8,
            ElementType.ETY_UNDEF, null, null,
            paramX.exlSource, paramX.exlOffset, operator.exlOffset + operator.exlLength - paramX.exlOffset,
            null, null, null);
        }
        paramY = evxParseMultiplication (tokenList, mode);
        if (paramY == null) {
          return null;
        }
        if (paramX.exlValueType == ElementType.ETY_FLOAT) {
          if (paramY.exlValueType == ElementType.ETY_FLOAT) {  //浮動小数点数+浮動小数点数
            type = ElementType.ETY_OPERATOR_ADDITION_FLOAT_FLOAT;
            valueType = ElementType.ETY_FLOAT;
          } else if (paramY.exlValueType == ElementType.ETY_STRING) {  //浮動小数点数+文字列
            type = ElementType.ETY_OPERATOR_ADDITION_FLOAT_STRING;
            valueType = ElementType.ETY_STRING;
          } else {
            if (mode != EVM_ASSEMBLER) {
              evxPrintError (Multilingual.mlnJapanese ?
                             "2 番目の引数の型が違います" :
                             "wrong type of the 2nd parameter",
                             paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset);
              return null;
            }
          }
        } else if (paramX.exlValueType == ElementType.ETY_STRING) {
          if (paramY.exlValueType == ElementType.ETY_FLOAT) {  //文字列+浮動小数点数
            type = ElementType.ETY_OPERATOR_ADDITION_STRING_FLOAT;
            valueType = ElementType.ETY_STRING;
          } else if (paramY.exlValueType == ElementType.ETY_STRING) {  //文字列+文字列
            type = ElementType.ETY_OPERATOR_ADDITION_STRING_STRING;
            valueType = ElementType.ETY_STRING;
          } else {
            if (mode != EVM_ASSEMBLER) {
              evxPrintError (Multilingual.mlnJapanese ?
                             "2 番目の引数の型が違います" :
                             "wrong type of the 2nd parameter",
                             paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset);
              return null;
            }
          }
        } else {
          if (mode != EVM_ASSEMBLER) {
            evxPrintError (Multilingual.mlnJapanese ?
                           "1 番目の引数の型が違います" :
                           "wrong type of the 1st parameter",
                           paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset);
            return null;
          }
        }
      } else if (mode != EVM_ASSEMBLER &&
                 type == ElementType.ETY_TOKEN_HYPHEN_MINUS) {  // x-y
        tokenList.pollFirst ();  // -
        paramY = evxParseMultiplication (tokenList, mode);
        if (paramY == null) {
          return null;
        }
        if (paramX.exlValueType != ElementType.ETY_FLOAT) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "1 番目の引数の型が違います" :
                         "wrong type of the 1st parameter",
                         paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset);
          return null;
        }
        if (paramY.exlValueType != ElementType.ETY_FLOAT) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "2 番目の引数の型が違います" :
                         "wrong type of the 2nd parameter",
                         paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset);
          return null;
        }
        type = ElementType.ETY_OPERATOR_SUBTRACTION;
        valueType = ElementType.ETY_FLOAT;
      } else {
        return paramX;
      }
      paramX = new ExpressionElement (
        type, 0,
        valueType, null, null,
        paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
        paramX, paramY, null);
      operator = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseAddition


  //--------------------------------------------------------------------------------
  //  シフト演算子
  protected ExpressionElement evxParseShift (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseAddition (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_LEFT_SHIFT:  // x<<y
      case ETY_OPERATOR_RIGHT_SHIFT:  // x>>y
      case ETY_OPERATOR_UNSIGNED_RIGHT_SHIFT:  // x>>>y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseAddition (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseShift


  //--------------------------------------------------------------------------------
  //  比較演算子
  protected ExpressionElement evxParseComparison (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseShift (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_LESS_THAN:  // x<y
      case ETY_OPERATOR_LESS_OR_EQUAL:  // x<=y
      case ETY_OPERATOR_GREATER_THAN:  // x>y
      case ETY_OPERATOR_GREATER_OR_EQUAL:  // x>=y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseShift (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxComparison


  //--------------------------------------------------------------------------------
  //  等価演算子
  protected ExpressionElement evxParseEquality (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseComparison (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_EQUAL:  // x==y
      case ETY_OPERATOR_NOT_EQUAL:  // x!=y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseComparison (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseEquality


  //--------------------------------------------------------------------------------
  //  ビットAND演算子
  protected ExpressionElement evxParseBitwiseAnd (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseEquality (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_BITWISE_AND:  // x&y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseEquality (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseBitwiseAnd


  //--------------------------------------------------------------------------------
  //  ビットXOR演算子
  protected ExpressionElement evxParseBitwiseXor (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseBitwiseAnd (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_BITWISE_XOR:  // x^y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseBitwiseAnd (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseBitwiseXor


  //--------------------------------------------------------------------------------
  //  ビットOR演算子
  protected ExpressionElement evxParseBitwiseOr (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseBitwiseXor (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_BITWISE_OR:  // x|y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseBitwiseXor (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseBitwiseOr


  //--------------------------------------------------------------------------------
  //  論理AND演算子
  protected ExpressionElement evxParseLogicalAnd (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseBitwiseOr (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_LOGICAL_AND:  // x&&y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseBitwiseOr (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseLogicalAnd


  //--------------------------------------------------------------------------------
  //  論理OR演算子
  protected ExpressionElement evxParseLogicalOr (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseLogicalAnd (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    while (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_LOGICAL_OR:  // x||y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseLogicalAnd (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (paramY.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlValueType = ElementType.ETY_FLOAT;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      paramX = elem;
      elem = tokenList.peekFirst ();
    }
    return paramX;
  }  //evxParseLogicalOr


  //--------------------------------------------------------------------------------
  //  条件演算子
  protected ExpressionElement evxParseConditional (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseLogicalOr (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    if (elem != null) {
      switch (elem.exlType) {
      case ETY_TOKEN_QUESTION_MARK:  // x?y:z
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseConditional (tokenList, mode);  //右から結合するので自分を呼ぶ
      if (paramY == null) {
        return null;
      }
      ExpressionElement colon = tokenList.pollFirst ();
      if (colon == null) {  //?があるのに:がない
        evxPrintError (Multilingual.mlnJapanese ?
                       ": がありません" :
                       ": is not found",
                       elem.exlSource, -1, 1);
        return null;
      }
      if (colon.exlType != ElementType.ETY_TOKEN_COLON) {  //?があるのに:がない
        evxPrintError (Multilingual.mlnJapanese ?
                       ": がありません" :
                       ": is not found",
                       colon.exlSource, colon.exlOffset, 1);
        return null;
      }
      ExpressionElement paramZ = evxParseConditional (tokenList, mode);  //右から結合するので自分を呼ぶ
      if (paramZ == null) {
        return null;
      }
      if (paramX.exlValueType != ElementType.ETY_FLOAT) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "1 番目の引数の型が違います" :
                       "wrong type of the 1st parameter",
                       paramX.exlSource, paramX.exlOffset, paramZ.exlOffset + paramZ.exlLength - paramX.exlOffset);
        return null;
      }
      if (!(paramY.exlValueType == ElementType.ETY_FLOAT ||
            paramY.exlValueType == ElementType.ETY_STRING)) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "2 番目の引数の型が違います" :
                       "wrong type of the 2nd parameter",
                       paramX.exlSource, paramX.exlOffset, paramZ.exlOffset + paramZ.exlLength - paramX.exlOffset);
        return null;
      } else if (paramY.exlValueType != paramZ.exlValueType) {
        evxPrintError (Multilingual.mlnJapanese ?
                       "3 番目の引数の型が違います" :
                       "wrong type of the 3rd parameter",
                       paramX.exlSource, paramX.exlOffset, paramZ.exlOffset + paramZ.exlLength - paramX.exlOffset);
        return null;
      }
      elem.exlType = paramY.exlValueType == ElementType.ETY_FLOAT ? ElementType.ETY_OPERATOR_CONDITIONAL_FLOAT : ElementType.ETY_OPERATOR_CONDITIONAL_STRING;
      elem.exlValueType = paramY.exlValueType;
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlParamZ = paramZ;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramZ.exlOffset + paramZ.exlLength - paramX.exlOffset;
      return elem;
    }
    return paramX;
  }  //evxParseConditional


  //--------------------------------------------------------------------------------
  //  代入演算子
  protected ExpressionElement evxParseAssignment (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = evxParseConditional (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    ExpressionElement elem = tokenList.peekFirst ();
    if (elem != null) {
      switch (elem.exlType) {
      case ETY_OPERATOR_ASSIGNMENT:  // x=y
      case ETY_OPERATOR_SELF_POWER:  // x**=y
      case ETY_OPERATOR_SELF_MULTIPLICATION:  // x*=y
      case ETY_OPERATOR_SELF_DIVISION:  // x/=y
      case ETY_OPERATOR_SELF_MODULUS:  // x%=y
      case ETY_OPERATOR_SELF_ADDITION:  // x+=y
      case ETY_OPERATOR_SELF_SUBTRACTION:  // x-=y
      case ETY_OPERATOR_SELF_LEFT_SHIFT:  // x<<=y
      case ETY_OPERATOR_SELF_RIGHT_SHIFT:  // x>>=y
      case ETY_OPERATOR_SELF_UNSIGNED_RIGHT_SHIFT:  // x>>>=y
      case ETY_OPERATOR_SELF_BITWISE_AND:  // x&=y
      case ETY_OPERATOR_SELF_BITWISE_XOR:  // x^=y
      case ETY_OPERATOR_SELF_BITWISE_OR:  // x|=y
        break;
      default:
        return paramX;
      }
      tokenList.pollFirst ();
      ExpressionElement paramY = evxParseAssignment (tokenList, mode);  //右から結合するので自分を呼ぶ
      if (paramY == null) {
        return null;
      }
      if (mode == EVM_ASSEMBLER) {  //アセンブラモード
        evxPrintError (Multilingual.mlnJapanese ?
                       "副作用を起こす演算子はここでは使えません" :
                       "operators which cause a side effect is unusable here",
                       elem.exlSource, elem.exlOffset, elem.exlLength);
        return null;
      }
      if (!(paramX.exlIsFloatSubstituend () ||  //数値被代入項
            paramX.exlType == ElementType.ETY_VARIABLE_STRING)) {  // 文字列変数
        evxPrintError (Multilingual.mlnJapanese ?
                       "引数が場所を示していません" :
                       "parameter is not indicating a location",
                       paramX.exlSource, paramX.exlOffset, paramX.exlLength);
        return null;
      }
      if (elem.exlType == ElementType.ETY_OPERATOR_ASSIGNMENT &&  //単純代入
          paramX.exlType == ElementType.ETY_VARIABLE_STRING &&  //左辺が文字列変数
          paramY.exlValueType == ElementType.ETY_STRING) {  //右辺が文字列
        elem.exlType = ElementType.ETY_OPERATOR_ASSIGN_STRING_TO_VARIABLE;  //文字列変数への文字列単純代入に変更
        elem.exlValueType = ElementType.ETY_STRING;
      } else if (elem.exlType == ElementType.ETY_OPERATOR_SELF_ADDITION &&  //加算・連結複合代入
                 paramX.exlType == ElementType.ETY_VARIABLE_STRING &&  //左辺が文字列変数
                 paramY.exlValueType == ElementType.ETY_STRING) {  //右辺が文字列
        elem.exlType = ElementType.ETY_OPERATOR_CONCAT_STRING_TO_VARIABLE;  //文字列変数への文字列連結複合代入に変更
        elem.exlValueType = ElementType.ETY_STRING;
      } else if (elem.exlType == ElementType.ETY_OPERATOR_ASSIGNMENT &&  //単純代入
                 paramX.exlType == ElementType.ETY_SQUARE_BRACKET &&  //左辺がメモリ
                 paramY.exlValueType == ElementType.ETY_STRING) {  //右辺が文字列
        elem.exlType = ElementType.ETY_OPERATOR_ASSIGN_STRING_TO_MEMORY;  //メモリへの文字列単純代入に変更
        elem.exlValueType = ElementType.ETY_STRING;
      } else if (elem.exlType == ElementType.ETY_OPERATOR_SELF_ADDITION &&  //加算・連結複合代入
                 paramX.exlType == ElementType.ETY_SQUARE_BRACKET &&  //左辺がメモリ
                 paramY.exlValueType == ElementType.ETY_STRING) {  //右辺が文字列
        elem.exlType = ElementType.ETY_OPERATOR_CONCAT_STRING_TO_MEMORY;  //メモリへの文字列連結複合代入に変更
        elem.exlValueType = ElementType.ETY_STRING;
      } else if (paramX.exlType != ElementType.ETY_VARIABLE_STRING &&  //左辺が文字列変数ではない
                 paramY.exlValueType == ElementType.ETY_FLOAT) {  //右辺が数値
        elem.exlValueType = ElementType.ETY_FLOAT;
      } else {
        evxPrintError (Multilingual.mlnJapanese ?
                       "引数の型が違います" :
                       "wrong type of parameter",
                       paramY.exlSource, paramY.exlOffset, paramY.exlLength);
        return null;
      }
      elem.exlParamX = paramX;
      elem.exlParamY = paramY;
      elem.exlOffset = paramX.exlOffset;
      elem.exlLength = paramY.exlOffset + paramY.exlLength - elem.exlOffset;
      return elem;
    }
    return paramX;
  }  //evxParseAssignment


  //--------------------------------------------------------------------------------
  //  コロン演算子
  protected ExpressionElement evxParseColon (LinkedList<ExpressionElement> tokenList, int mode) {
    //左辺
    ExpressionElement paramX = evxParseAssignment (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    for (ExpressionElement operator = tokenList.peekFirst ();
         operator != null && operator.exlType == ElementType.ETY_TOKEN_COLON;  // :
         operator = tokenList.peekFirst ()) {
      tokenList.pollFirst ();  // :
      //右辺
      ExpressionElement paramY = evxParseAssignment (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      if (mode == EVM_ASSEMBLER) {  //アセンブラモード
        if (paramX.exlType == ElementType.ETY_INTEGER_REGISTER && paramX.exlSubscript < 8 &&  //Dh
            paramY.exlType == ElementType.ETY_INTEGER_REGISTER && paramY.exlSubscript < 8) {  //Dl
          //データレジスタペア
          int h = paramX.exlSubscript;
          int l = paramY.exlSubscript;
          int subscript = h << 3 | l;
          return new ExpressionElement (
            ElementType.ETY_DATA_REGISTER_PAIR, subscript,
            ElementType.ETY_UNDEF, null, null,
            paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
            null, null, null);
        }
        if (paramX.exlType == ElementType.ETY_REGISTER_INDIRECT &&  //(Rr)
            paramY.exlType == ElementType.ETY_REGISTER_INDIRECT) {  //(Rs)
          //レジスタ間接ペア
          int r = paramX.exlSubscript;
          int s = paramY.exlSubscript;
          int subscript = r << 4 | s;
          return new ExpressionElement (
            ElementType.ETY_REGISTER_INDIRECT_PAIR, subscript,
            ElementType.ETY_UNDEF, null, null,
            paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
            null, null, null);
        }
      }
      paramX = new ExpressionElement (
        ElementType.ETY_OPERATOR_COLON, 0,
        ElementType.ETY_UNDEF, null, null,
        paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
        paramX, paramY, null);
    }
    return paramX;
  }  //evxParseColon


  //--------------------------------------------------------------------------------
  //  コンマ演算子
  protected ExpressionElement evxParseComma (LinkedList<ExpressionElement> tokenList, int mode) {
    //左辺
    ExpressionElement paramX = evxParseColon (tokenList, mode);
    if (paramX == null) {
      return null;
    }
    for (ExpressionElement operator = tokenList.peekFirst ();
         operator != null && operator.exlType == ElementType.ETY_TOKEN_COMMA;  // ,
         operator = tokenList.peekFirst ()) {
      tokenList.pollFirst ();  // ,
      //右辺
      ExpressionElement paramY = evxParseColon (tokenList, mode);
      if (paramY == null) {
        return null;
      }
      paramX = new ExpressionElement (
        ElementType.ETY_OPERATOR_COMMA, 0,
        paramY.exlValueType, null, null,
        paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset,
        paramX, paramY, null);
    }
    return paramX;
  }  //evxParseComma


  //--------------------------------------------------------------------------------
  //  コマンド
  protected ExpressionElement evxParseCommand (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement elem = tokenList.peekFirst ();
    if (elem == null) {
      return null;
    }
    int minParamCount = 0;
    int maxParamCount = 0;
    switch (elem.exlType) {
    case ETY_COMMAND_RUN:  //g
    case ETY_COMMAND_STEP:  //s
    case ETY_COMMAND_TRACE:  //t
    case ETY_COMMAND_TRACE_REGS:  //tx
    case ETY_COMMAND_TRACE_FLOAT_REGS:  //txf
      maxParamCount = 1;
      break;
    case ETY_COMMAND_DUMP:  //d
    case ETY_COMMAND_LIST:  //l
      maxParamCount = 2;
      break;
    case ETY_COMMAND_MEMORY_EDIT:  //me
      minParamCount = 1 + 1;
      maxParamCount = 1 + 65536;
      break;
    case ETY_COMMAND_FILL:  //f
    case ETY_COMMAND_MEMORY_SEARCH:  //ms
      minParamCount = 2 + 1;
      maxParamCount = 2 + 65536;
      break;
    case ETY_COMMAND_HELP:  //h
      maxParamCount = 65536;  //ヘルプの引数は何を書いてもよいがすべて無視する
      break;
    case ETY_COMMAND_PRINT:  //p
      maxParamCount = 65536;
      break;
    case ETY_COMMAND_STOP:  //i
    case ETY_COMMAND_LABEL_LIST:  //ll
    case ETY_COMMAND_RETURN:  //r
    case ETY_COMMAND_REGS:  //x
    case ETY_COMMAND_FLOAT_REGS:  //xf
      break;
    default:
      return evxParseComma (tokenList, mode);
    }
    elem = tokenList.pollFirst ();
    int paramCount = 0;
    ExpressionElement paramX = null;
    if (!tokenList.isEmpty () &&
        tokenList.peekFirst ().exlType != ElementType.ETY_TOKEN_SEMICOLON) {  //引数がある
      paramX = evxParseComma (tokenList, mode);
      if (paramX == null) {
        return null;
      }
      paramCount = paramX.exlLengthOfCommaList ();  //引数リストの長さ
    }
    if (paramCount < minParamCount) {
      evxPrintError (Multilingual.mlnJapanese ?
                     "引数が足りません" :
                     "too few arguments",
                     elem.exlSource, elem.exlOffset, elem.exlLength);
      return null;
    }
    if (maxParamCount < paramCount) {
      evxPrintError (Multilingual.mlnJapanese ?
                     "引数が多すぎます" :
                     "too many arguments",
                     elem.exlSource, elem.exlOffset, elem.exlLength);
      return null;
    }
    elem.exlValueType = ElementType.ETY_VOID;
    elem.exlParamX = paramX;
    return elem;
  }  //evxParseCommand


  //--------------------------------------------------------------------------------
  //  ライン
  protected ExpressionElement evxParseLine (LinkedList<ExpressionElement> tokenList, int mode) {
    ExpressionElement paramX = null;  //ラベル
    String stringValue = null;  //ニモニック
    int subscript = -1;  //オペレーションサイズ
    ExpressionElement paramY = null;  //オペランド
    ExpressionElement elem = tokenList.peekFirst ();
    if (elem == null) {
      return null;
    }
    ExpressionElement head = elem;
    ExpressionElement tail = elem;
    //ラベル
    if (elem.exlType == ElementType.ETY_LABEL_DEFINITION ||
        elem.exlType == ElementType.ETY_LOCAL_LABEL_DEFINITION) {
      paramX = elem;
      tokenList.pollFirst ();
      elem = tokenList.peekFirst ();
    }
    //ニモニック
    elem = tokenList.peekFirst ();
    if (elem != null && elem.exlType == ElementType.ETY_MNEMONIC) {
      tail = elem;
      stringValue = elem.exlStringValue;
      tokenList.pollFirst ();
      elem = tokenList.peekFirst ();
      //オペレーションサイズ
      if (elem != null && (elem.exlType == ElementType.ETY_OPERATOR_SIZE_BYTE ||  // x.b
                           elem.exlType == ElementType.ETY_OPERATOR_SIZE_WORD ||  // x.w
                           elem.exlType == ElementType.ETY_OPERATOR_SIZE_LONG ||  // x.l
                           elem.exlType == ElementType.ETY_OPERATOR_SIZE_QUAD ||  // x.q
                           elem.exlType == ElementType.ETY_OPERATOR_SIZE_SINGLE ||  // x.s
                           elem.exlType == ElementType.ETY_OPERATOR_SIZE_DOUBLE ||  // x.d
                           elem.exlType == ElementType.ETY_OPERATOR_SIZE_EXTENDED ||  // x.x
                           elem.exlType == ElementType.ETY_OPERATOR_SIZE_PACKED)) {  // x.p
        tail = elem;
        subscript = elem.exlSubscript;
        tokenList.pollFirst ();
        elem = tokenList.peekFirst ();
      }
      //オペランド
      if (elem != null && elem.exlType != ElementType.ETY_TOKEN_SEMICOLON) {
        paramY = evxParseComma (tokenList, mode);
        tail = paramY;
        elem = tokenList.peekFirst ();
      }
    }
    if (elem != null && elem.exlType != ElementType.ETY_TOKEN_SEMICOLON) {
      evxPrintError (Multilingual.mlnJapanese ?
                     "文法エラー" :
                     "syntax error",
                     elem.exlSource, elem.exlOffset, elem.exlLength);
      return null;
    }
    return new ExpressionElement (
      ElementType.ETY_LINE, subscript,
      ElementType.ETY_VOID, null, stringValue,
      head.exlSource, head.exlOffset, tail.exlOffset + tail.exlLength - head.exlOffset,
      paramX, paramY, null);
  }  //evxParseLine


  //--------------------------------------------------------------------------------
  //  セパレータ
  protected ExpressionElement evxParseSeparator (LinkedList<ExpressionElement> tokenList, int mode) {
    //左辺
    ExpressionElement paramX = (mode == EVM_EXPRESSION ? evxParseComma (tokenList, mode) :  //式評価モード
                                mode == EVM_COMMAND ? evxParseCommand (tokenList, mode) :  //コマンドモード
                                mode == EVM_ASSEMBLER ? evxParseLine (tokenList, mode) :  //アセンブラモード
                                null);
    if (paramX == null) {
      return null;
    }
    for (ExpressionElement elem = tokenList.peekFirst ();
         elem != null &&
         elem.exlType == ElementType.ETY_TOKEN_SEMICOLON;  // ;
         elem = tokenList.peekFirst ()) {
      //;の並びを読み飛ばす
      do {
        tokenList.pollFirst ();
        if (tokenList.isEmpty ()) {  //;の並びで終わった
          break;
        }
        elem = tokenList.peekFirst ();
      } while (elem.exlType == ElementType.ETY_TOKEN_SEMICOLON);
      //右辺
      ExpressionElement paramY = (mode == EVM_EXPRESSION ? evxParseComma (tokenList, mode) :  //式評価モード
                                  mode == EVM_COMMAND ? evxParseCommand (tokenList, mode) :  //コマンドモード
                                  mode == EVM_ASSEMBLER ? evxParseLine (tokenList, mode) :  //アセンブラモード
                                  null);
      if (paramY == null) {
        return null;
      }
      ExpressionElement separator = new ExpressionElement (
        ElementType.ETY_SEPARATOR, 0,
        paramY.exlValueType, null, null,
        paramX.exlSource, paramX.exlOffset, paramY.exlOffset + paramY.exlLength - paramX.exlOffset);
      separator.exlParamX = paramX;
      separator.exlParamY = paramY;
      paramX = separator;
    }
    return paramX;
  }  //evxParseSeparator



  //オペランドモード
  //  コンストラクタを呼び出すときに指定する
  public static final int ORM_BASIC     = 0;  //基本
  public static final int ORM_BIT_FIELD = 1;  //ビットフィールド付き
  public static final int ORM_K_FACTOR  = 2;  //k-factor付き
  public static final int ORM_RELATIVE  = 3;  //相対アドレス


  //オペランド型
  //  コンストラクタがオペランドを見て決める
  //  原則としてサイズの最適化でオペランド型と添字が変化することはない
  //  JBcc→BNcc+JMPは命令側で処理する
  public static final int ORT_ERROR            = -1;  //                  エラー
  public static final int ORT_DATA_REGISTER    =  0;  // Dr               データレジスタ直接。0..7
  public static final int ORT_ADDRESS_REGISTER =  1;  // Ar               アドレスレジスタ直接。0..7
  public static final int ORT_POSTINCREMENT    =  2;  // (Ar)+            アドレスレジスタ間接ポストインクリメント付き。0..7
  public static final int ORT_PREDECREMENT     =  3;  // -(Ar)            アドレスレジスタ間接プリデクリメント付き。0..7
  public static final int ORT_IMMEDIATE        =  4;  // #<data>          イミディエイト
  public static final int ORT_ABSOLUTE_ADDRESS =  5;  // xxx              絶対アドレス。絶対分岐命令の数値オペランド
  //                                                     (xxx).W          絶対ショート
  //                                                     (xxx).L          絶対ロング
  public static final int ORT_RELATIVE_ADDRESS =  6;  // xxx              相対アドレス。相対分岐命令の数値オペランド
  public static final int ORT_ADDRESS_INDIRECT =  7;  // (Ar)             アドレスレジスタ間接。0..7
  //                                                     (d16,Ar)         アドレスレジスタ間接ディスプレースメント付き。0..7
  //                                                     (d8,Ar,Rn.wl)    アドレスレジスタ間接インデックス付き。0..7
  public static final int ORT_PROGRAM_INDIRECT =  8;  //                  プログラムカウンタ間接
  //                                                     (d16,PC)         プログラムカウンタ間接ディスプレースメント付き
  //                                                     (d8,PC,Rn.wl)    プログラムカウンタ間接インデックス付き
  public static final int ORT_CONDITION_CODE   =  9;  // CCR              コンディションコードレジスタ
  public static final int ORT_STATUS_REGISTER  = 10;  // SR               ステータスレジスタ
  public static final int ORT_REGISTER_LIST    = 11;  // D0-D7/A0-A7      レジスタリスト。0x0000..0xffff
  public static final int ORT_REGISTER_PAIR    = 12;  // Dh:Dl            データレジスタペア。0x00..0x3f
  public static final int ORT_INDIRECT_PAIR    = 13;  // (Rr):(Rs)        レジスタ間接ペア。0x00..0xff
  public static final int ORT_FLOAT_REGISTER   = 14;  // FPn              浮動小数点レジスタ。0..7
  public static final int ORT_FLOAT_LIST       = 15;  // FP0-FP7          浮動小数点レジスタリスト。0x00..0xff
  public static final int ORT_FLOAT_CONTROL    = 16;  // FPIAR/FPSR/FPCR  浮動小数点制御レジスタ(リスト)。0..7
  public static final int ORT_CACHE_SELECTION  = 17;  // NC DC IC BC      キャッシュ選択。0..3
  public static final int ORT_CONTROL_REGISTER = 18;  // SFC ...          制御レジスタ(MOVEC)。0x0000..0xffff
  //public static final int ORT_MMU_REGISTER     = 19;  // TT0 ...          メモリ管理レジスタ(PMOVE)。0x0000..0xffff


  //class Operand
  //  オペランド
  public class Operand {

    //オペランドモード
    public int asoOperandMode;  //オペランドモード

    //オペランド
    public ExpressionElement asoOperandElement;  //オペランドの要素
    public ExpressionElement asoBasicElement;  //ビットフィールドまたはk-factorを除いた基本要素

    //オペレーションサイズ
    public int asoMinimumOperationSize;  //最小オペレーションサイズ。1,2,4
    public int asoMaximumOperationSize;  //最大オペレーションサイズ。1,2,4
    public int asoOperationSize;  //オペレーションサイズ。1,2,4

    //ビットフィールド
    //  ビットフィールド付きデータレジスタ
    //  ビットフィールド付きメモリ実効アドレス
    public boolean asoWithBitField;  //true=ビットフィールド付き
    //  以下はasoWithBitField==trueのとき有効
    public int asoBitFieldOffsetRegister;  //オフセットのレジスタ番号。-1=イミディエイト
    public ExpressionElement asoBitFieldOffsetElement;  //オフセットの要素
    public int asoBitFieldOffsetValue;  //オフセットの値
    public int asoBitFieldWidthRegister;  //幅のレジスタ番号。-1=イミディエイト
    public ExpressionElement asoBitFieldWidthElement;  //幅の要素
    public int asoBitFieldWidthValue;  //幅の値

    //k-factor
    //  k-factor付きメモリ実効アドレス
    public boolean asoWithKFactor;  //true=k-factor付き
    //  以下はasoWithKFactor==trueのとき有効
    public int asoKFactorRegister;  //k-factorのレジスタ番号。-1=イミディエイト
    public ExpressionElement asoKFactorElement;  //k-factorの式
    public int asoKFactorValue;  //k-factorの式の値

    //オペランド型
    public int asoOperandType;  //オペランド型
    public int asoSubscript;  //添字。レジスタ番号など

    //実効アドレス
    //  ベースレジスタ
    public boolean asoBaseRegisterSuppress;  //ベースレジスタサプレス
    //  ベースディスプレースメント
    public int asoMinimumBaseDisplacementSize;  //最小ベースディスプレースメントサイズ。0,1,2,4
    public int asoMaximumBaseDisplacementSize;  //最大ベースディスプレースメントサイズ。0,1,2,4
    public ExpressionElement asoBaseDisplacementElement;  //ベースディスプレースメントの要素
    public int asoBaseDisplacementValue;  //ベースディスプレースメントの値
    public int asoBaseDisplacementSize;  //ベースディスプレースメントサイズ。0,1,2,4
    //  メモリ間接
    public boolean asoMemoryIndirect;  //メモリ間接
    //  アウタディスプレースメント
    //    メモリ間接のとき有効
    public int asoMinimumOuterDisplacementSize;  //最小アウタディスプレースメントサイズ。0,2,4
    public int asoMaximumOuterDisplacementSize;  //最大アウタディスプレースメントサイズ。0,2,4
    public ExpressionElement asoOuterDisplacementElement;  //アウタディスプレースメントの要素
    public int asoOuterDisplacementValue;  //アウタディスプレースメントの値
    public int asoOuterDisplacementSize;  //アウタディスプレースメントサイズ。0,2,4
    //  インデックス
    public boolean asoPostindex;  //ポストインデックス
    public boolean asoIndexSuppress;  //インデックスサプレス
    public int asoIndexRegister;  //インデックスレジスタ。0..15
    public ExpressionElement asoScaleFactorElement;  //スケールファクタの要素
    public int asoScaleFactorValue;  //スケールファクタの値
    public int asoLog2ScaleFactor;  //スケールファクタのlog2。0..3
    //  イミディエイト
    //    最終パスでイミディエイトの値のサイズがオペレーションサイズを超えていたらエラー
    public ExpressionElement asoImmediateElement;  //イミディエイトの式
    public int asoImmediateValue;  //イミディエイトの式の値
    public int asoImmediateSize;  //イミディエイトの式の値のサイズ
    //  絶対アドレス
    //    サイズ付きのとき最終パスで絶対アドレスの値のサイズが指定されたサイズを超えていたらエラー
    public int asoMinimumAbsoluteAddressSize;  //最小絶対アドレスサイズ
    public int asoMaximumAbsoluteAddressSize;  //最大絶対アドレスサイズ
    public ExpressionElement asoAbsoluteAddressElement;  //絶対アドレスの式
    public int asoAbsoluteAddressValue;  //絶対アドレスの式の値
    public int asoAbsoluteAddressSize;  //絶対アドレスの式の値のサイズ

    //相対アドレス
    //  asoOperandMode==ORM_RELATIVEのとき有効
    public int asoBaseAddress;  //ベースアドレス。最初の拡張ワードの位置。通常は命令の先頭+2。FBccのとき命令の先頭+4。ディスプレースメントの位置ではない
    public ExpressionElement asoRelativeAddressElement;  //相対アドレスの式(絶対アドレス)
    public int asoRelativeAddressValue;  //相対アドレスの式の値-ベースアドレス(相対アドレス)
    public int asoRelativeAddressSize;  //相対アドレスの式の値-ベースアドレス(相対アドレス)のサイズ。0,1,2,4


    //----------------------------------------------------------------
    //  コンストラクタ
    public Operand (int operandMode, ExpressionElement operandElement,
                    int minimumOperationSize, int maximumOperationSize) {
      this (operandMode, operandElement,
            minimumOperationSize, maximumOperationSize,
            0);
    }
    public Operand (int operandMode, ExpressionElement operandElement,
                    int minimumOperationSize, int maximumOperationSize,
                    int baseAddress) {
      asoOperandMode = operandMode;
      asoOperandElement = operandElement;
      asoMinimumOperationSize = minimumOperationSize;
      asoMaximumOperationSize = maximumOperationSize;
      asoBaseAddress = baseAddress;

      asoBasicElement = asoOperandElement;
      asoOperationSize = maximumOperationSize;

      //------------------------------------------------
      //ビットフィールドを分離する
      //    <ea>{<offset>:<width>}
      asoWithBitField = false;
      if (asoOperandMode != ORM_BIT_FIELD) {
        if (asoOperandElement.exlType == ElementType.ETY_BIT_FIELD) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "予期しないビットフィールド" :
                         "unexpected bit-field",
                         asoOperandElement.exlSource, asoOperandElement.exlOffset, asoOperandElement.exlLength);
          asoOperandType = ORT_ERROR;
          return;
        }
      } else {
        if (asoOperandElement.exlType != ElementType.ETY_BIT_FIELD) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "ビットフィールドが必要です" :
                         "bit-field is required",
                         asoOperandElement.exlSource, asoOperandElement.exlOffset, asoOperandElement.exlLength);
          asoOperandType = ORT_ERROR;
          return;
        }
        asoBasicElement = asoOperandElement.exlParamX;  // <ea>
        asoBitFieldOffsetRegister = -1;
        asoBitFieldOffsetElement = asoOperandElement.exlParamY;  // oまたは#oまたはDo
        if (asoBitFieldOffsetElement.exlType == ElementType.ETY_INTEGER_REGISTER) {  // Do
          asoBitFieldOffsetRegister = asoBitFieldOffsetElement.exlSubscript;
        } else {  // oまたは#o
          if (asoBitFieldOffsetElement.exlType == ElementType.ETY_IMMEDIATE) {  // #o
            asoBitFieldOffsetElement = asoBitFieldOffsetElement.exlParamX;  // o
          }
          asoBitFieldOffsetValue = asoBitFieldOffsetElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
        }
        asoBitFieldWidthRegister = -1;
        asoBitFieldWidthElement = asoOperandElement.exlParamZ;  // wまたは#wまたはDw
        if (asoBitFieldWidthElement.exlType == ElementType.ETY_INTEGER_REGISTER) {  // Dw
          asoBitFieldWidthRegister = asoBitFieldWidthElement.exlSubscript;
        } else {  //wまたは#w
          if (asoBitFieldWidthElement.exlType == ElementType.ETY_IMMEDIATE) {  // #w
            asoBitFieldWidthElement = asoBitFieldWidthElement.exlParamX;  // w
          }
          asoBitFieldWidthValue = asoBitFieldWidthElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
        }
      }

      //------------------------------------------------
      //k-factorを分離する
      //    <ea>{<k-factor>}
      asoWithKFactor = false;
      if (asoOperandMode != ORM_K_FACTOR) {
        if (asoOperandElement.exlType == ElementType.ETY_K_FACTOR) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "予期しない k-factor" :
                         "unexpected k-factor",
                         asoOperandElement.exlSource, asoOperandElement.exlOffset, asoOperandElement.exlLength);
          asoOperandType = ORT_ERROR;
          return;
        }
      } else {
        if (asoOperandElement.exlType != ElementType.ETY_K_FACTOR) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "k-factor が必要です" :
                         "k-factor is required",
                         asoOperandElement.exlSource, asoOperandElement.exlOffset, asoOperandElement.exlLength);
          asoOperandType = ORT_ERROR;
          return;
        }
        asoBasicElement = asoOperandElement.exlParamX;  // <ea>
        asoKFactorRegister = -1;
        asoKFactorElement = asoOperandElement.exlParamY;  // kまたは#kまたはDk
        if (asoKFactorElement.exlType == ElementType.ETY_INTEGER_REGISTER) {  // Dk
          asoKFactorRegister = asoKFactorElement.exlSubscript;
        } else {  //kまたは#k
          if (asoKFactorElement.exlType == ElementType.ETY_IMMEDIATE) {  // #k
            asoKFactorElement = asoKFactorElement.exlParamX;  // k
          }
          asoKFactorValue = asoKFactorElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
        }
      }

      //実効アドレス
      //  (Ar)で初期化する
      //  ベースレジスタ
      asoBaseRegisterSuppress = false;
      //  ベースディスプレースメント
      asoMinimumBaseDisplacementSize = 0;
      asoMaximumBaseDisplacementSize = 0;
      asoBaseDisplacementElement = null;
      asoBaseDisplacementValue = 0;
      asoBaseDisplacementSize = 0;
      //  メモリ間接
      asoMemoryIndirect = false;
      //  アウタディスプレースメント
      asoMinimumOuterDisplacementSize = 0;
      asoMaximumOuterDisplacementSize = 0;
      asoOuterDisplacementElement = null;
      asoOuterDisplacementValue = 0;
      asoOuterDisplacementSize = 0;
      //  インデックス
      asoPostindex = false;
      asoIndexSuppress = true;
      asoIndexRegister = 0;
      asoScaleFactorElement = null;
      asoScaleFactorValue = 1;
      asoLog2ScaleFactor = 0;  // ZD0.W*1
      //  イミディエイト
      asoImmediateElement = null;
      asoImmediateValue = 0;
      asoImmediateSize = 0;
      //  絶対アドレス
      asoMinimumAbsoluteAddressSize = 2;
      asoMaximumAbsoluteAddressSize = 4;
      asoAbsoluteAddressElement = null;
      asoAbsoluteAddressValue = 0;
      asoAbsoluteAddressSize = 0;

      //------------------------------------------------
      //相対アドレス
      if (asoOperandMode == ORM_RELATIVE) {
        if (asoBasicElement.exlValueType != ElementType.ETY_FLOAT) {
          evxPrintError (Multilingual.mlnJapanese ?
                         "相対アドレスが必要です" :
                         "relative address is required",
                         asoBasicElement.exlSource, asoBasicElement.exlOffset, asoBasicElement.exlLength);
          asoOperandType = ORT_ERROR;
          return;
        }
        asoOperandType = ORT_RELATIVE_ADDRESS;
        asoRelativeAddressElement = asoBasicElement;
        asoRelativeAddressValue = asoRelativeAddressElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti () - asoBaseAddress;
        asoRelativeAddressSize = (asoRelativeAddressValue == 0 ? 0 :  //BRA/BSR/Bccは0を2にする
                                  (byte) asoRelativeAddressValue == asoRelativeAddressValue ? 1 :
                                  (short) asoRelativeAddressValue == asoRelativeAddressValue ? 2 :
                                  4);
        return;
      }

      //------------------------------------------------
      //  Dr               データレジスタ直接。0..7
      //  Ar               アドレスレジスタ直接。0..7
      if (asoBasicElement.exlType == ElementType.ETY_INTEGER_REGISTER) {
        if (asoBasicElement.exlSubscript < 8) {
          asoOperandType = ORT_DATA_REGISTER;
          asoSubscript = asoBasicElement.exlSubscript;
        } else {
          asoOperandType = ORT_ADDRESS_REGISTER;
          asoSubscript = asoBasicElement.exlSubscript - 8;
        }
        return;
      }

      //------------------------------------------------
      //  (Ar)+            アドレスレジスタ間接ポストインクリメント付き。0..7
      if (asoBasicElement.exlType == ElementType.ETY_POSTINCREMENT) {
        asoOperandType = ORT_POSTINCREMENT;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  -(Ar)            アドレスレジスタ間接プリデクリメント付き。0..7
      if (asoBasicElement.exlType == ElementType.ETY_PREDECREMENT) {
        asoOperandType = ORT_PREDECREMENT;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  #<data>          イミディエイト
      if (asoBasicElement.exlType == ElementType.ETY_IMMEDIATE) {
        asoOperandType = ORT_IMMEDIATE;
        asoImmediateElement = asoBasicElement.exlParamX;
        asoImmediateValue = asoImmediateElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
        asoImmediateSize = (asoImmediateValue == 0 ? 0 :
                            (byte) asoImmediateValue == asoImmediateValue ? 1 :
                            (short) asoImmediateValue == asoImmediateValue ? 2 :
                            4);
        return;
      }

      //------------------------------------------------
      //  xxx              絶対アドレス。絶対分岐命令の数値オペランド
      if (asoBasicElement.exlValueType == ElementType.ETY_FLOAT) {
        asoOperandType = ORT_ABSOLUTE_ADDRESS;
        asoMinimumAbsoluteAddressSize = 2;
        asoMaximumAbsoluteAddressSize = 4;
        asoAbsoluteAddressElement = asoBasicElement;
        asoAbsoluteAddressValue = asoAbsoluteAddressElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
        asoAbsoluteAddressSize = ((short) asoAbsoluteAddressValue == asoAbsoluteAddressValue ? 2 :
                                  4);
        return;
      }

      //------------------------------------------------
      //  (xxx).W          絶対ショート
      //  (xxx).L          絶対ロング
      if (asoBasicElement.exlType == ElementType.ETY_SIZE && (asoBasicElement.exlSubscript == 'w' ||
                                                              asoBasicElement.exlSubscript == 'l') &&
          asoBasicElement.exlParamX.exlValueType == ElementType.ETY_FLOAT) {
        asoOperandType = ORT_ABSOLUTE_ADDRESS;
        if (asoBasicElement.exlSubscript == 'w') {  // (xxx).W
          asoMinimumAbsoluteAddressSize = 2;
          asoMaximumAbsoluteAddressSize = 2;
        } else {  // (xxx).L
          asoMinimumAbsoluteAddressSize = 4;
          asoMaximumAbsoluteAddressSize = 4;
        }
        asoAbsoluteAddressElement = asoBasicElement.exlParamX;
        asoAbsoluteAddressValue = asoAbsoluteAddressElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
        asoAbsoluteAddressSize = ((short) asoAbsoluteAddressValue == asoAbsoluteAddressValue ? 2 :
                                  4);
        return;
      }

      //------------------------------------------------
      //  (Ar)             アドレスレジスタ間接
      if (asoBasicElement.exlType == ElementType.ETY_REGISTER_INDIRECT &&
          8 <= asoBasicElement.exlSubscript) {  // (Ar)
        asoOperandType = ORT_ADDRESS_INDIRECT;
        asoSubscript = asoBasicElement.exlSubscript - 8;
        return;
      }

      //------------------------------------------------
      //  CCR              コンディションコードレジスタ
      if (asoBasicElement.exlType == ElementType.ETY_CCR) {
        asoOperandType = ORT_CONDITION_CODE;
        return;
      }

      //------------------------------------------------
      //  SR               ステータスレジスタ
      if (asoBasicElement.exlType == ElementType.ETY_SR) {
        asoOperandType = ORT_STATUS_REGISTER;
        return;
      }

      //------------------------------------------------
      //  D0-D7/A0-A7      レジスタリスト。0x0000..0xffff
      if (asoBasicElement.exlType == ElementType.ETY_INTEGER_REGISTER_LIST) {
        asoOperandType = ORT_REGISTER_LIST;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  Dh:Dl            データレジスタペア。0x00..0x3f
      if (asoBasicElement.exlType == ElementType.ETY_DATA_REGISTER_PAIR) {
        asoOperandType = ORT_REGISTER_PAIR;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  (Rr):(Rs)        レジスタ間接ペア。0x00..0xff
      if (asoBasicElement.exlType == ElementType.ETY_REGISTER_INDIRECT_PAIR) {
        asoOperandType = ORT_INDIRECT_PAIR;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  FPn              浮動小数点レジスタ。0..7
      if (asoBasicElement.exlType == ElementType.ETY_FLOATING_POINT_REGISTER) {
        asoOperandType = ORT_FLOAT_REGISTER;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  FP0-FP7          浮動小数点レジスタリスト。0x00..0xff
      if (asoBasicElement.exlType == ElementType.ETY_FLOATING_POINT_REGISTER_LIST) {
        asoOperandType = ORT_FLOAT_LIST;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  FPIAR/FPSR/FPCR  浮動小数点制御レジスタ(リスト)。0..7
      if (asoBasicElement.exlType == ElementType.ETY_FLOATING_POINT_CONTROL_REGISTER_LIST) {
        asoOperandType = ORT_FLOAT_CONTROL;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  NC DC IC BC      キャッシュ選択。0..3
      if (asoBasicElement.exlType == ElementType.ETY_CACHE_SELECTION) {
        asoOperandType = ORT_CACHE_SELECTION;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  SFC ...          制御レジスタ(MOVEC)。0x0000..0xffff
      if (asoBasicElement.exlType == ElementType.ETY_CONTROL_REGISTER) {
        asoOperandType = ORT_CONTROL_REGISTER;
        asoSubscript = asoBasicElement.exlSubscript;
        return;
      }

      //------------------------------------------------
      //  TT0 ...          メモリ管理レジスタ(PMOVE)。0x0000..0xffff
      //if (asoBasicElement.exlType == ElementType.ETY_MMU_REGISTER) {
      //  asoOperandType = ORT_MMU_REGISTER;
      //  asoSubscript = asoBasicElement.exlSubscript;
      //  return;
      //}

      //------------------------------------------------
      //  (d16,Ar)         アドレスレジスタ間接ディスプレースメント付き
      //  (d8,Ar,Rn.wl)    アドレスレジスタ間接インデックス付き
      //  (d16,PC)         プログラムカウンタ間接ディスプレースメント付き
      //  (d8,PC,Rn.wl)    プログラムカウンタ間接インデックス付き
      if (asoBasicElement.exlType == ElementType.ETY_PARENTHESIS) {
        //メモリ間接を探す
        //  メモリ間接がないとき
        //    (ベースディスプレースメント,ベースレジスタ,プリインデックス)
        //  メモリ間接があるとき
        //    (アウタディスプレースメント,[ベースディスプレースメント,ベースレジスタ,プリインデックス])
        //    または
        //    (アウタディスプレースメント,[ベースディスプレースメント,ベースレジスタ],ポストインデックス)
        asoMemoryIndirect = false;  //メモリ間接なし
        LinkedList<ExpressionElement> baseList = asoBasicElement.exlParamX.exlToCommaList ();  //全体をベースにする
        LinkedList<ExpressionElement> outerList = null;  //アウタなし
        for (int i = 0, l = baseList.size (); i < l; i++) {
          if (baseList.get (i).exlType == ElementType.ETY_SQUARE_BRACKET) {  // [...]があるとき
            asoMemoryIndirect = true;  //メモリ間接あり
            outerList = baseList;  // [...]の外側をアウタにする
            baseList = outerList.remove (i).exlParamX.exlToCommaList ();  // [...]の内側をベースにする
            break;
          }
        }
        //ベースレジスタを探す
        asoBaseRegisterSuppress = true;
        asoOperandType = ORT_ADDRESS_INDIRECT;
        asoSubscript = 0;  // ZA0
        for (int i = 0, l = baseList.size (); i < l; i++) {
          ExpressionElement e = baseList.get (i);
          ElementType t = e.exlType;
          if (((t == ElementType.ETY_INTEGER_REGISTER ||  //アドレスレジスタ
                t == ElementType.ETY_ZERO_REGISTER) && 8 <= e.exlSubscript) ||  //サプレスされたアドレスレジスタ
              t == ElementType.ETY_PC ||  //プログラムカウンタ
              t == ElementType.ETY_ZERO_PC) {  //サプレスされたプログラムカウンタ
            baseList.remove (i);
            if (t == ElementType.ETY_INTEGER_REGISTER ||  //アドレスレジスタまたは
                t == ElementType.ETY_ZERO_REGISTER) {  //サプレスされたアドレスレジスタ
              asoOperandType = ORT_ADDRESS_INDIRECT;
              asoSubscript = e.exlSubscript - 8;
            } else {  //プログラムカウンタまたはサプレスされたプログラムカウンタ
              asoOperandType = ORT_PROGRAM_INDIRECT;
            }
            asoBaseRegisterSuppress = (t == ElementType.ETY_ZERO_REGISTER ||  //サプレスされたアドレスレジスタまたは
                                       t == ElementType.ETY_ZERO_PC);  //サプレスされたプログラムカウンタ
            break;
          }
        }
        //インデックスを探す
        asoPostindex = false;
        asoIndexSuppress = true;
        asoIndexRegister = 0;
        asoScaleFactorElement = null;
        asoScaleFactorValue = 1;
        asoLog2ScaleFactor = 0;  // ZD0.W*1
        //  プリインデックスを探す
        ExpressionElement indexElement = null;
        for (int i = 0, l = baseList.size (); i < l; i++) {
          ExpressionElement e = baseList.get (i);
          ElementType t = e.exlType;
          if (t == ElementType.ETY_INTEGER_REGISTER ||  // Rn
              (t == ElementType.ETY_SIZE && (e.exlSubscript == 'w' ||
                                             e.exlSubscript == 'l') &&
               e.exlParamX.exlType == ElementType.ETY_INTEGER_REGISTER) ||  // Rn.WまたはRn.L
              t == ElementType.ETY_SCALE_FACTOR) {  // Rn*SCALEまたはRn.W*SCALEまたはRn.L*SCALE
            indexElement = e;
            baseList.remove (i);
            break;
          }
        }
        //  プリインデックスがなくてメモリ間接があるときポストインデックスを探す
        if (indexElement == null && asoMemoryIndirect) {
          for (int i = 0, l = outerList.size (); i < l; i++) {
            ExpressionElement e = outerList.get (i);
            ElementType t = e.exlType;
            if (t == ElementType.ETY_INTEGER_REGISTER ||  // Rn
                (t == ElementType.ETY_SIZE && (e.exlSubscript == 'w' ||
                                               e.exlSubscript == 'l') &&
                 e.exlParamX.exlType == ElementType.ETY_INTEGER_REGISTER) ||  // Rn.WまたはRn.L
                t == ElementType.ETY_SCALE_FACTOR) {  // Rn*SCALEまたはRn.W*SCALEまたはRn.L*SCALE
              asoPostindex = true;
              indexElement = e;
              outerList.remove (i);
              break;
            }
          }
        }
        if (indexElement != null) {  //インデックスが見つかった
          ExpressionElement e = indexElement;
          ElementType t = e.exlType;
          asoIndexSuppress = false;
          asoIndexRegister = (t == ElementType.ETY_INTEGER_REGISTER ? e.exlSubscript :  // Rn
                              t == ElementType.ETY_SIZE ? e.exlParamX.exlSubscript :  // Rn.WまたはRn.L
                              e.exlParamX.exlType == ElementType.ETY_INTEGER_REGISTER ? e.exlParamX.exlSubscript :  // Rn*SCALE
                              e.exlParamX.exlParamX.exlSubscript);  // Rn.W*SCALEまたはRn.L*SCALE
          if (t == ElementType.ETY_SCALE_FACTOR) {  //スケールファクタがある
            asoScaleFactorElement = e.exlParamY;
            asoScaleFactorValue = asoScaleFactorElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
            asoLog2ScaleFactor = (asoScaleFactorValue == 1 ? 0 :
                                  asoScaleFactorValue == 2 ? 1 :
                                  asoScaleFactorValue == 4 ? 2 :
                                  asoScaleFactorValue == 8 ? 3 :
                                  0);  //最終パスは1,2,4,8のいずれでもなければエラーにする
          }
        }
        //ベースディスプレースメントを探す
        asoMinimumBaseDisplacementSize = 0;
        asoMaximumBaseDisplacementSize = 4;
        asoBaseDisplacementElement = null;
        asoBaseDisplacementValue = 0;
        asoBaseDisplacementSize = 0;
        for (int i = 0, l = baseList.size (); i < l; i++) {
          ExpressionElement e = baseList.get (i);
          ElementType t = e.exlType;
          if (e.exlValueType == ElementType.ETY_FLOAT) {  // bd
            asoMinimumBaseDisplacementSize = 0;
            asoMaximumBaseDisplacementSize = 4;
            asoBaseDisplacementElement = e;
            baseList.remove (i);
          } else if (t == ElementType.ETY_SIZE && (e.exlSubscript == 'w' ||
                                                   e.exlSubscript == 'l') &&
                     e.exlParamX.exlType == ElementType.ETY_FLOAT) {  // bd.Wまたはbd.L
            asoBaseDisplacementElement = e.exlParamX;
            if (e.exlSubscript == 'w') {
              asoMinimumBaseDisplacementSize = 2;
              asoMaximumBaseDisplacementSize = 2;
            } else {
              asoMinimumBaseDisplacementSize = 4;
              asoMaximumBaseDisplacementSize = 4;
            }
            baseList.remove (i);
          }
          asoBaseDisplacementValue = asoBaseDisplacementElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
          asoBaseDisplacementSize = (asoBaseDisplacementValue == 0 ? 0 :
                                     !asoMemoryIndirect && (byte) asoBaseDisplacementValue == asoBaseDisplacementValue ? 1 :
                                     (short) asoBaseDisplacementValue == asoBaseDisplacementValue ? 2 :
                                     4);  //最終パスで最大サイズを超えていたらエラー
          break;
        }
        //アウタディスプレースメントを探す
        asoMinimumOuterDisplacementSize = 0;
        asoMaximumOuterDisplacementSize = 4;
        asoOuterDisplacementElement = null;
        asoOuterDisplacementValue = 0;
        asoOuterDisplacementSize = 0;
        for (int i = 0, l = outerList.size (); i < l; i++) {
          ExpressionElement e = outerList.get (i);
          ElementType t = e.exlType;
          if (e.exlValueType == ElementType.ETY_FLOAT) {  // od
            asoMinimumOuterDisplacementSize = 0;
            asoMaximumOuterDisplacementSize = 4;
            asoOuterDisplacementElement = e;
            outerList.remove (i);
          } else if (t == ElementType.ETY_SIZE &&
                     e.exlParamX.exlType == ElementType.ETY_FLOAT) {  // od.Wまたはod.L
            asoOuterDisplacementElement = e.exlParamX;
            if (e.exlSubscript == 'w') {
              asoMinimumOuterDisplacementSize = 2;
              asoMaximumOuterDisplacementSize = 2;
            } else {
              asoMinimumOuterDisplacementSize = 4;
              asoMaximumOuterDisplacementSize = 4;
            }
            outerList.remove (i);
          }
          asoOuterDisplacementValue = asoOuterDisplacementElement.exlEval (EVM_EXPRESSION).exlFloatValue.geti ();
          asoOuterDisplacementSize = (asoOuterDisplacementValue == 0 ? 0 :
                                      (short) asoOuterDisplacementValue == asoOuterDisplacementValue ? 2 :
                                      4);  //最終パスで最大サイズを超えていたらエラー
          break;
        }
        //余分な要素が残っていたらエラー
        if (0 < baseList.size ()) {
          ExpressionElement e = baseList.get (0);
          evxPrintError (Multilingual.mlnJapanese ?
                         "文法エラー" :
                         "syntax error",
                         e.exlSource, e.exlOffset, e.exlLength);
          asoOperandType = ORT_ERROR;
          return;
        }
        if (0 < outerList.size ()) {
          ExpressionElement e = outerList.get (0);
          evxPrintError (Multilingual.mlnJapanese ?
                         "文法エラー" :
                         "syntax error",
                         e.exlSource, e.exlOffset, e.exlLength);
          asoOperandType = ORT_ERROR;
          return;
        }
        return;
      }  //if ETY_PARENTHESIS

      evxPrintError (Multilingual.mlnJapanese ?
                     "文法エラー" :
                     "syntax error",
                     asoBasicElement.exlSource, asoBasicElement.exlOffset, asoBasicElement.exlLength);
      asoOperandType = ORT_ERROR;

    }  //new Operand


    //----------------------------------------------------------------
    //asoUpdate (baseAddress, first, last)
    //  オペランドの中にある式を再計算してオペレーションサイズまたはアドレッシングモードを更新する
    //  初回パスは前回の値を無視して更新フラグを無条件にセットする
    //  最終パスでサイズが最大サイズを超えていたらエラー
    public void asoUpdate (int baseAddress, boolean first, boolean last) {
      asoBaseAddress = baseAddress;
      //!!!
    }


    //----------------------------------------------------------------
    //  文字列化
    public String toString () {
      return this.appendTo (new StringBuilder ()).toString ();
    }
    public StringBuilder appendTo (StringBuilder sb) {
      switch (asoOperandType) {

        //------------------------------------------------
        //  Dr               データレジスタ直接。0..7
      case ORT_DATA_REGISTER:
        return sb.append ('d').append (asoSubscript);

        //------------------------------------------------
        //  Ar               アドレスレジスタ直接。0..7
      case ORT_ADDRESS_REGISTER:
        if (asoSubscript < 7) {
          return sb.append ('a').append (asoSubscript);
        } else {
          return sb.append ("sp");
        }

        //------------------------------------------------
        //  (Ar)+            アドレスレジスタ間接ポストインクリメント付き。0..7
      case ORT_POSTINCREMENT:
        if (asoSubscript < 7) {
          return sb.append ("(a").append (asoSubscript).append (")+");
        } else {
          return sb.append ("(sp)+");
        }

        //------------------------------------------------
        //  -(Ar)            アドレスレジスタ間接プリデクリメント付き。0..7
      case ORT_PREDECREMENT:
        if (asoSubscript < 7) {
          return sb.append ("-(a").append (asoSubscript).append (')');
        } else {
          return sb.append ("-(sp)");
        }

        //------------------------------------------------
        //  #<data>          イミディエイト
      case ORT_IMMEDIATE:
        if (asoOperationSize <= 1) {
          return XEiJ.fmtHex2 (sb.append ('#'), asoImmediateValue);
        } else if (asoOperationSize <= 2) {
          return XEiJ.fmtHex4 (sb.append ('#'), asoImmediateValue);
        } else {
          return XEiJ.fmtHex8 (sb.append ('#'), asoImmediateValue);
        }

        //------------------------------------------------
        //  xxx              絶対アドレス。絶対分岐命令の数値オペランド
        //  (xxx).W          絶対ショート
        //  (xxx).L          絶対ロング
      case ORT_ABSOLUTE_ADDRESS:
        if (asoAbsoluteAddressSize <= 2) {
          return XEiJ.fmtHex4 (sb.append ('$'), asoAbsoluteAddressValue).append (".w");
        } else {
          return XEiJ.fmtHex8 (sb.append ('$'), asoAbsoluteAddressValue).append (".l");
        }

        //------------------------------------------------
        //  xxx              相対アドレス。相対分岐命令の数値オペランド
      case ORT_RELATIVE_ADDRESS:
        return XEiJ.fmtHex8 (sb.append ('$'), asoRelativeAddressValue + asoBaseAddress);

        //------------------------------------------------
        //  CCR              コンディションコードレジスタ
      case ORT_CONDITION_CODE:
        return sb.append ("ccr");

        //------------------------------------------------
        //  SR               ステータスレジスタ
      case ORT_STATUS_REGISTER:
        return sb.append ("sr");

        //------------------------------------------------
        //  D0-D7/A0-A7      レジスタリスト。0x0000..0xffff
      case ORT_REGISTER_LIST:
        {
          int m = asoSubscript;
          m = (m & 0x8000) << 2 | (m & 0x7f00) << 1 | (m & 0x00ff);  //D7/A0とA6/SPを不連続にする
          boolean s = false;
          while (m != 0) {
            int i = Integer.numberOfTrailingZeros (m);
            m += 1 << i;
            int j = Integer.numberOfTrailingZeros (m);
            m -= 1 << j;
            j--;
            if (s) {
              sb.append ('/');
            }
            if (i <= 7) {
              sb.append ('d').append (i);
            } else if (i <= 16) {
              sb.append ('a').append (i - 9);
            } else {
              sb.append ("sp");
            }
            if (i < j) {
              sb.append ('-');
              if (j <= 7) {
                sb.append ('d').append (j);
              } else if (j <= 16) {
                sb.append ('a').append (j - 9);
              } else {
                sb.append ("sp");
              }
            }
            s = true;
          }  //while m!=0
          return sb;
        }

        //------------------------------------------------
        //  Dh:Dl            データレジスタペア。0x00..0x3f
      case ORT_REGISTER_PAIR:
        {
          int h = asoSubscript >> 3;
          int l = asoSubscript & 7;
          return sb.append ('d').append (h).append (":d").append (l);
        }

        //------------------------------------------------
        //  (Rr):(Rs)        レジスタ間接ペア。0x00..0xff
      case ORT_INDIRECT_PAIR:
        {
          int r = asoSubscript >> 4;
          int s = asoSubscript & 15;
          sb.append ('(');
          if (r <= 7) {
            sb.append ('d').append (r);
          } else if (r <= 14) {
            sb.append ('a').append (r - 8);
          } else {
            sb.append ("sp");
          }
          sb.append ("):(");
          if (s <= 7) {
            sb.append ('d').append (s);
          } else if (s <= 14) {
            sb.append ('a').append (s - 8);
          } else {
            sb.append ("sp");
          }
          return sb.append (')');
        }

        //------------------------------------------------
        //  FPn              浮動小数点レジスタ。0..7
      case ORT_FLOAT_REGISTER:
        return sb.append ("fp").append (asoSubscript);

        //------------------------------------------------
        //  FP0-FP7          浮動小数点レジスタリスト。0x00..0xff
      case ORT_FLOAT_LIST:
        {
          int m = asoSubscript;
          boolean s = false;
          while (m != 0) {
            int i = Integer.numberOfTrailingZeros (m);
            m += 1 << i;
            int j = Integer.numberOfTrailingZeros (m);
            m -= 1 << j;
            j--;
            if (s) {
              sb.append ('/');
            }
            sb.append ("fp").append (i);
            if (i < j) {
              sb.append ("-fp").append (j);
            }
            s = true;
          }  //while m!=0
          return sb;
        }

        //------------------------------------------------
        //  FPIAR/FPSR/FPCR  浮動小数点制御レジスタ(リスト)。0..7
      case ORT_FLOAT_CONTROL:
        {
          int m = asoSubscript;
          boolean s = false;
          while (m != 0) {
            int i = Integer.numberOfTrailingZeros (m);
            m -= 1 << i;
            if (s) {
              sb.append ('/');
            }
            sb.append (EVX_FLOAT_CONTROL_NAME_ARRAY[i]);
            s = true;
          }  //while m!=0
          return sb;
        }

        //------------------------------------------------
        //  NC DC IC BC      キャッシュ選択。0..3
      case ORT_CACHE_SELECTION:
        return sb.append (EVX_CACHE_NAME_ARRAY[asoSubscript]);

        //------------------------------------------------
        //  SFC ...          制御レジスタ(MOVEC)。0x0000..0xffff
      case ORT_CONTROL_REGISTER:
        return sb.append (EVX_CONTROL_MPU_CODE_TO_NAME.get (asoSubscript));

        //------------------------------------------------
        //  TT0 ...          メモリ管理レジスタ(PMOVE)。0x0000..0xffff
        //case ORT_MMU_REGISTER:
        //  return sb.append (EVX_MMU_CODE_TO_NAME.get (asoSubscript));

        //------------------------------------------------
        //  (Ar)             アドレスレジスタ間接。0..7
        //  (d16,Ar)         アドレスレジスタ間接ディスプレースメント付き。0..7
        //  (d8,Ar,Rn.wl)    アドレスレジスタ間接インデックス付き。0..7
        //                   プログラムカウンタ間接
        //  (d16,PC)         プログラムカウンタ間接ディスプレースメント付き
        //  (d8,PC,Rn.wl)    プログラムカウンタ間接インデックス付き
      case ORT_ADDRESS_INDIRECT:
      case ORT_PROGRAM_INDIRECT:
        if (!asoBaseRegisterSuppress &&
            asoBaseDisplacementSize <= 1 &&
            !asoMemoryIndirect &&
            !asoIndexSuppress) {  //ブリーフフォーマット
          sb.append ('(');
          //  ベースディスプレースメント
          if (asoOperandType == ORT_PROGRAM_INDIRECT) {
            XEiJ.fmtHex8 (sb.append ('$'), asoBaseDisplacementValue + asoBaseAddress);
          } else {
            XEiJ.fmtHex2 (sb.append ('$'), asoBaseDisplacementValue);
          }
          sb.append (',');
          //  ベースレジスタ
          if (asoOperandType == ORT_PROGRAM_INDIRECT) {
            sb.append ("pc");
          } else if (asoSubscript < 7) {
            sb.append ('a').append (asoSubscript);
          } else {
            sb.append ("sp");
          }
          sb.append (',');
          //  インデックス
          if (asoIndexRegister < 8) {
            sb.append ('d').append (asoIndexRegister);
          } else if (asoIndexRegister < 15) {
            sb.append ('a').append (asoIndexRegister - 8);
          } else {
            sb.append ("sp");
          }
          if (0 < asoLog2ScaleFactor) {
            sb.append ('*').append (1 << asoLog2ScaleFactor);
          }
          sb.append (')');
        } else {  //フルフォーマット
          sb.append ('(');
          //  メモリ間接
          if (asoMemoryIndirect) {
            sb.append ('[');
          }
          //  ベースディスプレースメント
          if (0 < asoBaseDisplacementSize) {
            if (asoOperandType == ORT_PROGRAM_INDIRECT) {
              XEiJ.fmtHex8 (sb.append ('$'), asoBaseDisplacementValue + asoBaseAddress);
            } else if (asoBaseDisplacementSize <= 2) {
              XEiJ.fmtHex4 (sb.append ('$'), asoBaseDisplacementValue);
            } else {
              XEiJ.fmtHex8 (sb.append ('$'), asoBaseDisplacementValue);
            }
            sb.append (',');
          }
          //  ベースレジスタ
          if (asoBaseRegisterSuppress) {
            sb.append ('z');
          }
          if (asoOperandType == ORT_PROGRAM_INDIRECT) {
            sb.append ("pc");
          } else if (asoSubscript < 7) {
            sb.append ('a').append (asoSubscript);
          } else {
            sb.append ("sp");
          }
          //  プリインデックス
          if (!asoIndexSuppress && !asoPostindex) {
            sb.append (',');
            if (asoIndexRegister < 8) {
              sb.append ('d').append (asoIndexRegister);
            } else if (asoIndexRegister < 15) {
              sb.append ('a').append (asoIndexRegister - 8);
            } else {
              sb.append ("sp");
            }
            if (0 < asoLog2ScaleFactor) {
              sb.append ('*').append (1 << asoLog2ScaleFactor);
            }
          }
          //  メモリ間接
          if (asoMemoryIndirect) {
            sb.append (']');
            //  アウタディスプレースメント
            if (0 < asoOuterDisplacementSize) {
              if (asoBaseDisplacementSize <= 2) {
                XEiJ.fmtHex4 (sb.append ('$'), asoOuterDisplacementValue);
              } else {
                XEiJ.fmtHex8 (sb.append ('$'), asoOuterDisplacementValue);
              }
              sb.append (',');
            }
            //  ポストインデックス
            if (!asoIndexSuppress && asoPostindex) {
              sb.append (',');
              if (asoIndexRegister < 8) {
                sb.append ('d').append (asoIndexRegister);
              } else if (asoIndexRegister < 15) {
                sb.append ('a').append (asoIndexRegister - 8);
              } else {
                sb.append ("sp");
              }
              if (0 < asoLog2ScaleFactor) {
                sb.append ('*').append (1 << asoLog2ScaleFactor);
              }
            }
          }
          sb.append (')');
        }  //if ブリーフフォーマット/フルフォーマット
        return sb;

      }  //switch asoOperandType

      return sb.append ("???");

    }  //appendTo


  }  //class Operand



}  //class ExpressionEvaluator


1 2