in src/language/semantics/xslLexer.ts [207:509]
protected calcNewState(
isCurrentCharNewLine: boolean,
char: string,
nextChar: string,
existing: XMLCharState
): XMLCharState {
let rc: XMLCharState = existing
let firstCharOfToken = true
if (firstCharOfToken) {
}
switch (existing) {
case XMLCharState.lCt:
rc = XMLCharState.lCt2
break
case XMLCharState.lCt2:
rc = XMLCharState.lCtName
break
case XMLCharState.lCtName:
if (char === '>') {
rc = XMLCharState.rCt
}
break
case XMLCharState.lPi:
rc = XMLCharState.lPi2
break
case XMLCharState.lPi2:
rc = XMLCharState.lPiName
break
case XMLCharState.lPiName:
if (this.isWhitespace(isCurrentCharNewLine, char)) {
rc = XMLCharState.rPiName
} else if (char === '?' && nextChar === '>') {
rc = XMLCharState.rPiNameOnly
this.skipTokenChar = true
}
break
case XMLCharState.rPiName:
if (this.isWhitespace(isCurrentCharNewLine, char)) {
// no change
} else if (char === '?' && nextChar === '>') {
rc = XMLCharState.rPi
this.skipTokenChar = true
} else {
rc = XMLCharState.lPiValue
}
break
case XMLCharState.lPiValue:
if (char === '?' && nextChar === '>') {
rc = XMLCharState.rPi
this.skipTokenChar = true
}
break
case XMLCharState.rPi:
case XMLCharState.rPiNameOnly:
case XMLCharState.rSelfCt:
case XMLCharState.rSelfCtNoAtt:
if (this.skipTokenChar) {
this.skipTokenChar = false
} else {
rc = this.testChar(char, nextChar, false)
}
break
case XMLCharState.lComment:
if (this.commentCharCount === 0) {
// char === '-' we've already processed <!-
this.commentCharCount++
} else if (this.commentCharCount === 1) {
// if commendCharCount === 1 then we're just in the comment value
if (char === '-' && nextChar === '-') {
this.commentCharCount++
}
} else if (this.commentCharCount === 2) {
// we're on the second '-' at comment end
this.commentCharCount++
} else if (this.commentCharCount === 3) {
// we're expecting the '>' at the comment end
if (char === '>') {
rc = XMLCharState.rComment
}
// stop checking as '--' already encountered without '>'
this.commentCharCount = 4
}
break
case XMLCharState.lExclam:
// assume <![CDATA[
if (char === '[' && nextChar === 'C') {
this.cdataCharCount = 0
rc = XMLCharState.lCd
} else if (char === '-' && nextChar === '-') {
rc = XMLCharState.lComment
this.commentCharCount = 0
} else if (char === '>') {
this.dtdNesting--
if (this.dtdNesting < 0) {
this.dtdNesting = 0
rc = XMLCharState.rDtd
}
} else if (char === '<') {
this.dtdNesting++
}
// TODO: Handle internal DTD subset
break
case XMLCharState.lCd:
switch (this.cdataCharCount) {
case 0:
// [C of <![CDATA[ already checked
case 2:
// DA already checked
case 4:
// TA already checked
this.cdataCharCount++
break
case 1:
if (char === 'D' && nextChar === 'A') {
this.cdataCharCount++
} else {
rc = XMLCharState.init
}
break
case 3:
if (char === 'T' && nextChar === 'A') {
this.cdataCharCount++
} else {
rc = XMLCharState.init
}
break
case 5:
if (char === '[') {
this.cdataCharCount = 0
rc = XMLCharState.lCdataEnd
} else {
rc = XMLCharState.init
}
break
}
break
case XMLCharState.lCdataEnd:
case XMLCharState.awaitingRcdata:
if (char === ']' && nextChar === ']') {
this.cdataCharCount = 0
rc = XMLCharState.rCd
} else if (char === '{') {
if (nextChar === '{') {
rc = XMLCharState.escTvtCdata
} else {
rc = XMLCharState.tvtCdata
}
}
break
// otherwise continue awaiting ]]>
case XMLCharState.rCd:
if (this.cdataCharCount === 0) {
this.cdataCharCount++
} else if (char === '>') {
this.cdataCharCount = 0
rc = XMLCharState.rCdataEnd
} else {
// TODO: ]] not permited on its own in CDATA, show error
this.cdataCharCount = 0
rc = XMLCharState.init
}
break
case XMLCharState.lSt:
if (char === '>') {
// error for: '<>'
rc = XMLCharState.rSt
} else {
// TODO: check first char of element name is oK
rc = XMLCharState.lEn
}
break
// element name started
case XMLCharState.lEn:
if (this.isWhitespace(isCurrentCharNewLine, char)) {
rc = XMLCharState.lsElementNameWs
} else if (char === '>') {
rc = XMLCharState.rStNoAtt
} else if (char === '/' && nextChar === '>') {
rc = XMLCharState.rSelfCtNoAtt
this.skipTokenChar = true
}
break
// whitespace after element name (or after att-value)
case XMLCharState.lsElementNameWs:
case XMLCharState.rSq:
case XMLCharState.rDq:
case XMLCharState.wsBeforeAttname:
if (this.isWhitespace(isCurrentCharNewLine, char)) {
if (existing !== XMLCharState.lsElementNameWs) {
rc = XMLCharState.wsBeforeAttname
}
} else if (char === '>') {
rc = XMLCharState.rSt
} else if (char === '/' && nextChar === '>') {
rc = XMLCharState.rSelfCt
this.skipTokenChar = true
} else {
rc = XMLCharState.lAn
}
break
// attribute name started
case XMLCharState.lAn:
if (this.isWhitespace(isCurrentCharNewLine, char)) {
rc = XMLCharState.wsAfterAttName
} else if (char === '=') {
rc = XMLCharState.lStEq
} else {
const charState = this.testAttNameChar(char, nextChar)
if (charState !== XMLCharState.lText) {
rc = charState
}
}
break
// whitespace after attribute name
case XMLCharState.wsAfterAttName:
if (char === '=') {
rc = XMLCharState.lStEq
} else if (!this.isWhitespace(isCurrentCharNewLine, char)) {
// TODO: force error - guessing intended end of start tag
rc = XMLCharState.syntaxError
}
break
// '=' char after attribute name or
// whitespace after attname and '=' char
case XMLCharState.lStEq:
case XMLCharState.lsEqWs:
if (this.isWhitespace(isCurrentCharNewLine, char)) {
rc = XMLCharState.lsEqWs
} else if (char === '"') {
rc = XMLCharState.lDq
} else if (char === "'") {
rc = XMLCharState.lSq
} else {
rc = XMLCharState.syntaxError
}
break
case XMLCharState.lDq:
if (char === '"') {
rc = XMLCharState.rDq
} else if (char === '{') {
if (nextChar === '{') {
rc = XMLCharState.escDqAvt
} else {
rc = XMLCharState.dqAvt
}
} else if (char === '&') {
rc = XMLCharState.lEntity
this.entityContext = EntityPosition.attrDq
} else {
const charState = this.testAttValueChar(char, nextChar)
if (charState !== XMLCharState.lText) {
rc = charState
}
}
break
case XMLCharState.lSq:
if (char === "'") {
rc = XMLCharState.rSq
} else if (char === '{') {
if (nextChar === '{') {
rc = XMLCharState.escSqAvt
} else {
rc = XMLCharState.sqAvt
}
} else if (char === '&') {
rc = XMLCharState.lEntity
this.entityContext = EntityPosition.attrSq
} else {
const charState = this.testAttValueChar(char, nextChar)
if (charState !== XMLCharState.lText) {
rc = charState
}
}
break
case XMLCharState.escDqAvt:
rc = XMLCharState.lDq
break
case XMLCharState.escSqAvt:
rc = XMLCharState.lSq
break
case XMLCharState.escTvt:
rc = XMLCharState.init
break
case XMLCharState.escTvtCdata:
rc = XMLCharState.awaitingRcdata
break
case XMLCharState.lEntity:
if (char === ';') {
rc = XMLCharState.rEntity
} else if (this.isWhitespace(isCurrentCharNewLine, char)) {
rc = this.testChar(char, nextChar, false)
}
break
case XMLCharState.lText:
rc = this.testChar(char, nextChar, true)
break
default:
// awaiting a new node
rc = this.testChar(char, nextChar, false)
}
return rc
}