static public Token LexNext() { int state = 0; string value = string.Empty; int startOffset = 0; ErrorKind errorKind = ErrorKind.DEFAULT; char? cQuestion; char c; while (true) { cQuestion = SourceViewModel.NextChar(); if (cQuestion.HasValue) { c = cQuestion.Value; switch (state) { case 0: startOffset = SourceViewModel.GetOffset(); if (char.IsLetter(c) || c == '_') { state = 1; value += c; break; } if (char.IsDigit(c)) { state = 2; value += c; break; } if (char.IsWhiteSpace(c)) { break; } if (c == '>') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.GT)); } if (c == '+') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.ADD));; } if (c == '-') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.SUB)); } if (c == '*') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.MULT)); } if (c == '/') { state = 7; value += c; break; } if (c == '=') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.EQU)); } if (c == '<') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.LT)); } if (c == '{') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.LBRA)); } if (c == '}') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.RBRA)); } if (c == '(') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.LPAR)); } if (c == ')') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.RPAR)); } if (c == ';') { value = c.ToString(); return(new Token(startOffset, value, TokenKind.SEMI)); } if (c == '.') { state = 4; value += c; errorKind = ErrorKind.NUMBERERROR; break; } //ERROR state = 4; value += c; errorKind = ErrorKind.INVALIDCHAR; break; case 1: if (char.IsLetterOrDigit(c)) { value += c; break; } SourceViewModel.putBack(); if (KeyWords.ContainsKey(value)) { return(new Token(startOffset, value, KeyWords[value])); } else { return(new Token(startOffset, value, TokenKind.ID)); } case 2: if (char.IsDigit(c)) { value += c; break; } if (c == '.') { state = 5; value += c; break; } SourceViewModel.putBack(); return(new Token(startOffset, value, TokenKind.NUM)); case 3: if (c == '*') { state = 9; } value += c; break; case 4: switch (errorKind) { case ErrorKind.NUMBERERROR: if (char.IsDigit(c) || c == '.') { value += c; } else { SourceViewModel.putBack(); HandleError(startOffset, value, errorKind); return(new Token(startOffset, value, TokenKind.ERROR)); } break; case ErrorKind.INVALIDCHAR: if (char.IsLetterOrDigit(c) || symbols.Contains(c) || char.IsWhiteSpace(c)) { SourceViewModel.putBack(); HandleError(startOffset, value, errorKind); return(new Token(startOffset, value, TokenKind.ERROR)); } else { value += c; } break; default: if (char.IsWhiteSpace(c)) { HandleError(startOffset, value, errorKind); return(new Token(startOffset, value, TokenKind.ERROR)); } else { value += c; } break; } break; case 5: if (char.IsDigit(c)) { state = 6; value += c; break; } if (c == '.') { state = 4; value += c; errorKind = ErrorKind.NUMBERERROR; break; } SourceViewModel.putBack(); HandleError(startOffset, value, ErrorKind.NUMBERERROR); return(new Token(startOffset, value, TokenKind.ERROR)); case 6: if (char.IsDigit(c)) { state = 6; value += c; break; } if (c == '.') { state = 4; value += c; errorKind = ErrorKind.NUMBERERROR; break; } SourceViewModel.putBack(); return(new Token(startOffset, value, TokenKind.NUM)); case 7: if (c == '*') { value += c; state = 3; break; } if (c == '/') { value += c; state = 8; break; } SourceViewModel.putBack(); return(new Token(startOffset, value, TokenKind.DIV)); case 8: if (c == '\r' || c == '\n') //for the case "\r\n" and "\n"; { return(new Token(startOffset, value, TokenKind.ANNO)); } value += c; break; case 9: if (c == '/') { value += c; return(new Token(startOffset, value, TokenKind.ANNO)); } value += c; state = 3; break; } } else { switch (state) { case 0: return(new Token(SourceViewModel.GetEndOffset(), value, TokenKind.END)); case 1: if (KeyWords.ContainsKey(value)) { return(new Token(startOffset, value, KeyWords[value])); } else { return(new Token(startOffset, value, TokenKind.ID)); } case 2: case 6: return(new Token(startOffset, value, TokenKind.NUM)); case 3: case 9: HandleError(startOffset, value, ErrorKind.ANNONOTCLOSED); return(new Token(startOffset, value, TokenKind.ERROR)); case 4: HandleError(startOffset, value, errorKind); return(new Token(startOffset, value, TokenKind.ERROR)); case 5: HandleError(startOffset, value, ErrorKind.NUMBERERROR); return(new Token(startOffset, value, TokenKind.ERROR)); case 7: return(new Token(startOffset, value, TokenKind.DIV)); case 8: return(new Token(startOffset, value, TokenKind.ANNO)); } } } }