private calcNewState()

in src/language/semantics/xpLexer.ts [392:641]


  private calcNewState(
    isFirstChar: boolean,
    nesting: number,
    char: string,
    nextChar: string,
    existing: CharLevelState
  ): [CharLevelState, number] {
    let rv: CharLevelState
    let firstCharOfToken = true

    switch (existing) {
      case CharLevelState.lNl:
        let charCode = char.charCodeAt(0)
        let nextCharCode = nextChar ? nextChar.charCodeAt(0) : -1
        if (XPathLexer.isDigit(charCode) || char === '.') {
          rv = existing
        } else if (char === 'e' || char === 'E') {
          if (
            nextChar === '-' ||
            nextChar === '+' ||
            XPathLexer.isDigit(nextCharCode)
          ) {
            rv = CharLevelState.exp
          } else {
            rv = existing
          }
        } else {
          ;({ rv, nesting } = this.testChar(
            existing,
            firstCharOfToken,
            char,
            nextChar,
            nesting
          ))
        }
        break
      case CharLevelState.exp:
        rv = CharLevelState.lNl
        break
      case CharLevelState.rDqEnt:
        rv = existing
        switch (nesting) {
          case 0:
          case 2:
            nesting++
            break
          case 1:
            if (char === 'u' && nextChar === 'o') {
              nesting++
            } else {
              nesting = 0
              rv = CharLevelState.lDqEnt
            }
            break
          case 3:
            if (char === 't') {
              nesting++
            } else {
              rv = CharLevelState.lDqEnt
              nesting = 0
            }
            break
          case 4:
            if (char === ';') {
              rv = CharLevelState.rDq
            } else {
              rv = CharLevelState.lDqEnt
            }
            nesting = 0
            break
        }
        break
      case CharLevelState.rSqEnt:
        rv = existing
        switch (nesting) {
          case 0:
          case 2:
            nesting++
            break
          case 1:
            if (char === 'p' && nextChar === 'o') {
              nesting++
            } else {
              nesting = 0
              rv = CharLevelState.lSqEnt
            }
            break
          case 3:
            if (char === 's') {
              nesting++
            } else {
              rv = CharLevelState.lSqEnt
              nesting = 0
            }
            break
          case 4:
            if (char === ';') {
              rv = CharLevelState.rSq
            } else {
              rv = CharLevelState.lSqEnt
            }
            nesting = 0
            break
        }
        break
      case CharLevelState.lWs:
        if (char === ' ' || char === '\t') {
          rv = existing
          this.wsCharNumber++
        } else if (char === '\n') {
          rv = existing
          this.wsCharNumber = 0
          this.wsNewLine = true
          this.lineNumber++
        } else {
          // we must switch to the new state, depending on the char/nextChar
          ;({ rv, nesting } = this.testChar(
            existing,
            firstCharOfToken,
            char,
            nextChar,
            nesting
          ))
        }
        break
      case CharLevelState.lName:
      case CharLevelState.lVar:
      case CharLevelState.lAttr:
        if (
          char === '-' ||
          char === '.' ||
          (char === ':' &&
            !(
              nextChar === ':' ||
              nextChar === '*' ||
              nextChar === ' ' ||
              nextChar === '\n' ||
              nextChar === '\r' ||
              nextChar === '\t'
            ))
        ) {
          rv = existing
        } else {
          // we must switch to the new state, depending on the char/nextChar
          ;({ rv, nesting } = this.testChar(
            existing,
            isFirstChar,
            char,
            nextChar,
            nesting
          ))
        }
        break
      case CharLevelState.dSep:
        rv = CharLevelState.dSep2
        break
      case CharLevelState.lUri:
        rv = char === '}' ? CharLevelState.rUri : existing
        break
      case CharLevelState.lSqEnt:
        rv = char === '&' && nextChar === 'a' ? CharLevelState.rSqEnt : existing
        break
      case CharLevelState.lDqEnt:
        rv = char === '&' && nextChar === 'q' ? CharLevelState.rDqEnt : existing
        break
      case CharLevelState.lSq:
      case CharLevelState.rLiteralSqEnt:
        if (char === "'") {
          if (nextChar === "'") {
            rv = CharLevelState.escSq
          } else {
            rv = CharLevelState.rSq
          }
        } else if (char === '&') {
          rv = CharLevelState.lLiteralSqEnt
        } else {
          rv = CharLevelState.lSq
        }
        break
      case CharLevelState.lLiteralSqEnt:
        if (char === "'") {
          if (nextChar === "'") {
            rv = CharLevelState.escSq
          } else {
            rv = CharLevelState.rSq
          }
        } else if (char === ';') {
          rv = CharLevelState.rLiteralSqEnt
        } else {
          rv = existing
        }
        break
      case CharLevelState.escSq:
        rv = CharLevelState.lSq
        break
      case CharLevelState.escDq:
        rv = CharLevelState.lDq
        break
      case CharLevelState.lDq:
      case CharLevelState.rLiteralDqEnt:
        if (char === '"') {
          if (nextChar === '"') {
            rv = CharLevelState.escDq
          } else {
            rv = CharLevelState.rDq
          }
        } else if (char === '&') {
          rv = CharLevelState.lLiteralDqEnt
        } else {
          rv = CharLevelState.lDq
        }
        break
      case CharLevelState.lLiteralDqEnt:
        if (char === '"') {
          if (nextChar === '"') {
            rv = CharLevelState.escDq
          } else {
            rv = CharLevelState.rDq
          }
        } else if (char === ';') {
          rv = CharLevelState.rLiteralDqEnt
        } else {
          rv = existing
        }
        break
      case CharLevelState.lC:
        if (char === ':' && nextChar === ')') {
          rv = nesting === 1 ? CharLevelState.rC : existing
          nesting--
        } else if (char === '(' && nextChar === ':') {
          rv = existing
          nesting++
        } else {
          rv = existing
        }
        break
      case CharLevelState.lEnt:
        rv = char === ';' ? CharLevelState.rEnt : existing
        break
      default:
        ;({ rv, nesting } = this.testChar(
          existing,
          isFirstChar,
          char,
          nextChar,
          nesting
        ))
    }
    return [rv, nesting]
  }