tokenize method

List<Token> tokenize(
  1. String inputString
)

Tokenizes a given input string. Returns a list of Token in infix notation.

Implementation

List<Token> tokenize(String inputString) {
  final List<Token> tempTokenStream = <Token>[];
  final String clearedString = inputString.replaceAll(' ', '').trim();
  final RuneIterator iter = clearedString.runes.iterator;

  while (iter.moveNext()) {
    final String si = iter.currentAsString;
    /*
     * Check if the current Character is a keyword. If it is a keyword, check if the intBuffer is not empty and add
     * a Value Token for the intBuffer and the corresponding Token for the keyword.
     */
    bool keywordsContainsKey = keywords.containsKey(si);

    /*
    * There's a situation that 'ceil' conflict with 'e', we use this to look back the buffer and decide
    * which way should go.
    */
    if (si == 'e' && varBuffer.isNotEmpty) {
      keywordsContainsKey = false;
    }

    if (keywordsContainsKey) {
      // check and or do intBuffer and varBuffer
      if (intBuffer.isNotEmpty) {
        _doIntBuffer(tempTokenStream);
      }
      if (varBuffer.isNotEmpty) {
        _doVarBuffer(tempTokenStream);
      }
      // MH - Bit of a hack here to handle exponentials of the form e^x rather than e(x)
      if (keywords[si] == TokenType.POW &&
          tempTokenStream.last.type == TokenType.EFUNC) {
        // Clear varBuffer since we have nothing to add to the stream as EFUNC is already in it
        //_doVarBuffer(tempTokenStream);
        varBuffer = '';
      } else {
        // Normal behaviour
        tempTokenStream.add(Token(si, keywords[si]!));
      }
    } else {
      // Check if the current string is a Number. If it's the case add the string to the intBuffer.
      StringBuffer sb = StringBuffer(intBuffer);
      try {
        // A variable can contains digits
        if (varBuffer.isNotEmpty) {
          throw FormatException();
        }
        int.parse(si);
        // The current string is a number and it is added to the intBuffer.
        sb.write(si);
        intBuffer = sb.toString();
        if (varBuffer.isNotEmpty) {
          _doVarBuffer(tempTokenStream);
        }
      } on FormatException {
        // Check if the current string is part of a floating point input
        if (si == '.') {
          sb.write(si);
          intBuffer = sb.toString();
          continue;
        }

        // The current string is not a number and not a simple keyword, so it has to be a variable or function.
        sb = StringBuffer(varBuffer);
        if (intBuffer.isNotEmpty) {
          /*
           * The intBuffer contains a string and the current string is a
           * variable or part of a complex keyword, so the value is added
           * to the token stream and the current string is added to the
           * var buffer.
           */
          _doIntBuffer(tempTokenStream);
          sb.write(si);
          varBuffer = sb.toString();
        } else {
          // intBuffer contains no string and the current string is a variable, so both Tokens are added to the tokenStream.
          sb.write(si);
          varBuffer = sb.toString();
        }
      }
    }
  }

  if (intBuffer.isNotEmpty) {
    // There are no more symbols in the input string but there is still an int in the intBuffer
    _doIntBuffer(tempTokenStream);
  }
  if (varBuffer.isNotEmpty) {
    // There are no more symbols in the input string but there is still a variable or keyword in the varBuffer
    _doVarBuffer(tempTokenStream);
  }
  return tempTokenStream;
}