private static string ConstructErrorMessage(ScannerErrorState error) { string errMsg = string.Empty; switch (error) { case ScannerErrorState.CannotHaveBlankExponent: errMsg = "Cannot have blank exponent"; break; case ScannerErrorState.CannotHaveBlankMantissa: errMsg = "Cannot have blank mantissa"; break; case ScannerErrorState.InternalErrorCouldNotResolveTokenType: errMsg = "Internal error could not resolve token type"; break; case ScannerErrorState.InternalErrorCouldNotTransitionState: errMsg = "Internal error could not transition scanner state"; break; case ScannerErrorState.UnexpectedCharacter: errMsg = "Unexpected character"; break; case ScannerErrorState.UnexpectedSymbol: errMsg = "Unexpected symbol"; break; } return(errMsg); }
public ScannerException(ScannerErrorState error, int line, int startPos, int endPos) : base(line, startPos, endPos, ConstructErrorMessage(error)) { }
public Token GetNextToken() { StringBuilder tokenValue = new StringBuilder(); ScannerState scannerState = ScannerState.Start; ScannerErrorState scannerError = ScannerErrorState.None; bool finishedScan = false; _startPosition = _pos; while (!finishedScan) { bool ignoreCharacter = false; char nextChar = GetNextRelevantChar(); #region DFA Implementation switch (scannerState) { case ScannerState.Start: if (char.IsWhiteSpace(nextChar)) { scannerState = ScannerState.Start; ignoreCharacter = true; } else if (char.IsLetter(nextChar)) { scannerState = ScannerState.Identifier; } else if (char.IsDigit(nextChar)) { scannerState = ScannerState.Number; } else if (IsSymbol(nextChar)) { #region Scan symbol switch (nextChar) { case '^': scannerState = ScannerState.Power; finishedScan = true; break; case '+': scannerState = ScannerState.Plus; finishedScan = true; break; case '-': scannerState = ScannerState.Minus; finishedScan = true; break; case '*': scannerState = ScannerState.Multiplication; finishedScan = true; break; case '/': scannerState = ScannerState.Division; finishedScan = true; break; case '[': scannerState = ScannerState.OpenBracket; finishedScan = true; break; case ']': scannerState = ScannerState.CloseBracket; finishedScan = true; break; case '(': scannerState = ScannerState.OpenParenthesis; finishedScan = true; break; case ')': scannerState = ScannerState.CloseParenthesis; finishedScan = true; break; case '{': scannerState = ScannerState.BeginBracket; finishedScan = true; break; case '}': scannerState = ScannerState.EndBracket; finishedScan = true; break; case '=': scannerState = ScannerState.Assign; break; case '&': scannerState = ScannerState.AlmostAnd; break; case '|': scannerState = ScannerState.AlmostOr; break; case ',': scannerState = ScannerState.Comma; finishedScan = true; break; case '.': scannerState = ScannerState.Dot; finishedScan = true; break; case ';': scannerState = ScannerState.SemiColon; finishedScan = true; break; case '!': scannerState = ScannerState.Not; break; case '<': scannerState = ScannerState.LessThan; break; case '>': scannerState = ScannerState.GreaterThan; break; case '%': scannerState = ScannerState.Modulus; finishedScan = true; break; default: finishedScan = true; scannerError = ScannerErrorState.UnexpectedSymbol; RestoreChar(nextChar); break; } #endregion } else if (nextChar == char.MaxValue) { scannerState = ScannerState.EndOfCode; finishedScan = true; } else { finishedScan = true; scannerError = ScannerErrorState.UnexpectedCharacter; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.Identifier: if (char.IsLetterOrDigit(nextChar)) { scannerState = ScannerState.Identifier; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.Number: if (char.IsDigit(nextChar)) { scannerState = ScannerState.Number; } else if (nextChar == '.') { scannerState = ScannerState.AlmostDecimal; } else if (nextChar == 'E') { scannerState = ScannerState.NumberWithExponent; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.AlmostDecimal: if (char.IsDigit(nextChar)) { scannerState = ScannerState.Decimal; } else { finishedScan = true; scannerError = ScannerErrorState.CannotHaveBlankMantissa; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.Decimal: if (char.IsDigit(nextChar)) { scannerState = ScannerState.Decimal; } else if (nextChar == 'E') { scannerState = ScannerState.NumberWithExponent; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.NumberWithExponent: if (char.IsDigit(nextChar)) { scannerState = ScannerState.NumberWithUnsignedExponent; } else if (nextChar == '+') { scannerState = ScannerState.NumberWithSignedExponent; } else if (nextChar == '-') { scannerState = ScannerState.NumberWithSignedExponent; } else { finishedScan = true; scannerError = ScannerErrorState.CannotHaveBlankExponent; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.NumberWithSignedExponent: if (char.IsDigit(nextChar)) { scannerState = ScannerState.NumberWithSignedExponent; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.NumberWithUnsignedExponent: if (char.IsDigit(nextChar)) { scannerState = ScannerState.NumberWithUnsignedExponent; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.Assign: if (nextChar == '=') { scannerState = ScannerState.Equality; finishedScan = true; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.Not: if (nextChar == '=') { scannerState = ScannerState.Inequality; finishedScan = true; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.LessThan: if (nextChar == '=') { scannerState = ScannerState.LessThanEqualTo; finishedScan = true; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.GreaterThan: if (nextChar == '=') { scannerState = ScannerState.GreaterThanEqualTo; finishedScan = true; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.AlmostOr: if (nextChar == '|') { scannerState = ScannerState.Or; finishedScan = true; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; case ScannerState.AlmostAnd: if (nextChar == '&') { scannerState = ScannerState.And; finishedScan = true; } else { finishedScan = true; RestoreChar(nextChar); ignoreCharacter = true; } break; default: scannerError = ScannerErrorState.InternalErrorCouldNotTransitionState; break; } #endregion if (scannerError != ScannerErrorState.None) { RestoreChar(nextChar); ignoreCharacter = true; throw new ScannerException( scannerError, _line, _startPosition, _pos ); } else { if (!ignoreCharacter) { tokenValue.Append(nextChar); } } } string tokenString = tokenValue.ToString(); Token token = new Token( ResolveTokenType(scannerState, tokenString), tokenString, _line, _startPosition, !_haveRestoredChar ? _pos : _pos - 1 ); return(token); }