public static void ParseStream <T>(StreamReader reader, System.Action <Data, T> dataReceiver, T custom) { var phase = ParsePhase.New; int lineNumber = 1; while (!reader.EndOfStream) { var line = reader.ReadLine(); #if LOG_LINE Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(String.Format("TryParseLine[{0}]\n{1}", lineNumber, line)); #endif try { phase = ParseLine(line, lineNumber, phase, dataReceiver, custom); } catch (LexException e) { e.line = line; e.row = lineNumber; throw e; } ++lineNumber; } if (ParsePhase.Note == phase) { var exception = new LexException(Error.NoteNoEnd); exception.content = "No \"*/\""; throw exception; } }
public static Number TryParseNumber(Token token, string str) { var number = new Number(); switch (token) { case Token.Int8: number.i_8 = DoTryParseNumber <sbyte>(token, str, sbyte.TryParse); break; case Token.UInt8: number.ui_8 = DoTryParseNumber <byte>(token, str, byte.TryParse); break; case Token.Int16: number.i_16 = DoTryParseNumber <short>(token, str, short.TryParse); break; case Token.UInt16: number.ui_16 = DoTryParseNumber <ushort>(token, str, ushort.TryParse); break; case Token.Int32: number.i_32 = DoTryParseNumber <int>(token, str, int.TryParse); break; case Token.UInt32: number.ui_32 = DoTryParseNumber <uint>(token, str, uint.TryParse); break; case Token.Int64: number.i_64 = DoTryParseNumber <long>(token, str, long.TryParse); break; case Token.UInt64: number.ui_64 = DoTryParseNumber <ulong>(token, str, ulong.TryParse); break; case Token.Float: number.f = DoTryParseNumber <float>(token, str, float.TryParse); break; case Token.Double: number.d = DoTryParseNumber <double>(token, str, double.TryParse); break; default: { var exception = new LexException(Error.InvalidToken); exception.content = token.ToString(); throw exception; } } return(number); }
internal static void Log_LexException(LexException e) { Console.ForegroundColor = ConsoleColor.Red; Console.Write(String.Format("LexException: {0}, {1}\n at [{2},{3}]: ", e.errorCode.ToString(), e.content, e.row, e.col)); if (null != e.line && 0 < e.col && e.line.Length >= e.col) { Console.ForegroundColor = ConsoleColor.Black; Console.Write(e.line.Substring(0, e.col - 1)); Console.ForegroundColor = ConsoleColor.Red; Console.Write(e.line[e.col - 1]); Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine(e.line.Substring(e.col)); } }
private static T DoTryParseNumber <T>(Token token, string str, NumberParseFunc <T> parseFunc) { T v; if (parseFunc(str, out v)) { return(v); } else { var exception = new LexException(Error.ParseNumberFailed); exception.content = str; exception.col = (int)token; throw exception; } }
private static string ParseFunc_String(string line, ref int i, ref ParsePhase phase, char separator) { var begIndex = i + 1; var endIndex = IndexOfStringEnd(line, begIndex, separator); if (i < endIndex) { var str = line.Substring(begIndex, endIndex - i); i = endIndex; return(str); } else { var exception = new LexException(Error.StringNoEnd); exception.col = i + 1; throw exception; } }
public static ParsePhase ParseLine <T>(string line, int lineNumber, ParsePhase phase, System.Action <Data, T> dataReceiver, T custom) { if (string.IsNullOrEmpty(line)) { return(phase); } int i = 0; if (ParsePhase.Note == phase) { var endIndex = line.IndexOf("*/"); if (0 > endIndex) { #if LOG_NOTE Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine(line); #endif return(phase); } #if LOG_NOTE Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine(line.Substring(0, endIndex + 2)); #endif phase = ParsePhase.New; i = endIndex + 2; } for (; i < line.Length; ++i) { var startI = i; Data data = null; var c = line[i]; ParseFunc func; if (StartCharMap.TryGetValue(c, out func)) { if (null != func) { data = func(line, ref i, ref phase); } } else if ('_' == c) { // identify var identify = ParseFunc_Identify(line, ref i, ref phase, c); data = new Data(Token.Identify, identify); } else if (char.IsLetter(c)) { var identify = ParseFunc_Identify(line, ref i, ref phase, c); Keyword k; if (Enum.TryParse(identify, true, out k) && ("API" == identify || identify.ToLower() == identify)) { // keyword data = new Data(Token.Keyword, k); } else { // identify data = new Data(Token.Identify, identify); } } else if (char.IsDigit(c)) { // constant data = ParseFunc_Number(line, ref i, ref phase, c); } else if (!char.IsWhiteSpace(c)) { var exception = new LexException(Error.InvalidCharactor); exception.col = i + 1; throw exception; } if (null != data) { data.line = line; data.row = lineNumber; data.col = startI + 1; dataReceiver(data, custom); } } return(phase); }
private static Data ParseFunc_Number(string line, ref int i, ref ParsePhase phase, char c) { /* * number phase * 0: scan number * 1: scan float or double * 2: scan end char * 3: check next char is not(letter,digit,_) */ Token token = Token.Int32; int numberPhase = 0; int j = i + 1; for (; j < line.Length; ++j) { var d = line[j]; switch (numberPhase) { case 0: switch (d) { case 't': numberPhase = 3; token = Token.Int8; continue; case 's': numberPhase = 3; token = Token.Int16; continue; case 'l': numberPhase = 3; token = Token.Int64; continue; case 'f': numberPhase = 3; token = Token.Float; continue; case 'u': numberPhase = 2; token = Token.UInt32; continue; case '.': numberPhase = 1; token = Token.Double; continue; } break; case 1: if ('f' == d) { numberPhase = 3; token = Token.Float; continue; } break; case 2: switch (d) { case 't': numberPhase = 3; token = Token.UInt8; continue; case 's': numberPhase = 3; token = Token.UInt16; continue; case 'l': numberPhase = 3; token = Token.UInt64; continue; } break; case 3: if ('_' == d || '.' == d || char.IsLetterOrDigit(d)) { var exception = new LexException(Error.InvalidCharactor); exception.col = j + 1; throw exception; } else { // end var data = new Data(token); data.number = TryParseNumber(token, line.Substring(i, j - i)); i = j - 1; return(data); } } if (!char.IsDigit(d)) { if ('_' == d || '.' == d || char.IsLetter(d)) { var exception = new LexException(Error.InvalidCharactor); exception.col = j + 1; throw exception; } else { // end var data = new Data(token); data.number = TryParseNumber(token, line.Substring(i, j - i)); i = j - 1; return(data); } } } return(null); }