/// <summary> 添加一个词法单元信息到列表 | Add a token to list </summary> private static void AddToken(List <LBToken> list, LBTag tag, int index, int length, int row, int column) { if (length > 0) { list.Add(new LBToken(tag, index, length, row, column)); } }
public LBToken(LBTag tag, int index, int length, int row, int column) { this.tag = tag; this.index = index; this.length = length; this.row = row; this.column = column; }
/// <summary> 词法分析(拆分成词法单元) | Lexical analyze(split and get lexical element) </summary> public static List <LBToken> Analyze(string code) { // 检查参数 if (string.IsNullOrEmpty(code)) { throw new System.ArgumentNullException("code", "Code can not be null or empty"); } List <LBToken> tokens = new List <LBToken>(16); // 当前词法单元信息 | Current lexical element info MatchState matchState = MatchState.Normal; int row = 1; int column = 0; // 上一个词法单元信息 | Last lexical element info char lastChar = '\x0'; // 上一个字符(默认空字符NUL) | Last character(default NUL) LBTag lastTag = LBTag.None; int lastIndex = 0; int lastLength = 0; int lastRow = 1; int lastColumn = 0; bool needClear = false; // 扫描所有字符 | Scan all characters int total = code.Length; for (int index = 0; index < total; index++) { char c = code[index]; // 如果注释开始 忽略除换行符和注释结束符以外的所有字符 | If Comments start Ignore all characters except newline and comments end characters if (matchState == MatchState.SingleLineComments) { // 查找单行注释结束 '\n' | Find single-line comments end '\n' if (c == '\n') { row += 1; column = 0; needClear = true; matchState = MatchState.Normal; } } else if (matchState == MatchState.MultiLineComments) { if (c == '\n') { // 换行符 | New line character row += 1; column = 0; needClear = true; } else if (c == '/' && lastChar == '*') { // 查找多行注释结束 "*/" | Find multi-line comments end "*/" needClear = true; matchState = MatchState.Normal; } } else if (c == ' ' || c == '\t') { // 分隔符 | Separator characters if (lastLength > 0) { needClear = true; tokens.Add(new LBToken(lastTag, lastIndex, lastLength, lastRow, lastColumn)); } else { needClear = false; } } else if (c == '\r') { // 忽略符 | Ignore character continue; } else if (c == '\n') { // 拆分符 | Split characters row += 1; column = 0; needClear = true; AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); } else if (c == ';') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.Semicolon, index, 1, row, column)); needClear = true; } else if (c == ',') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.Comma, index, 1, row, column)); needClear = true; } else if (c == '[') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.LSquareBracket, index, 1, row, column)); needClear = true; } else if (c == ']') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.RSquareBracket, index, 1, row, column)); needClear = true; } else if (c == '<') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.LAngleBracket, index, 1, row, column)); needClear = true; } else if (c == '>') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.RAngleBracket, index, 1, row, column)); needClear = true; } else if (c == '{') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.LCurlyBrace, index, 1, row, column)); needClear = true; } else if (c == '}') { AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); tokens.Add(new LBToken(LBTag.RCurlyBrace, index, 1, row, column)); needClear = true; } else { // 其他符号 | Other characters if (lastLength == 0) { // 新的单词开始 | New word start lastTag = LBTag.Word; lastIndex = index; lastLength = 1; } else { // 添加新字符 if (matchState == MatchState.Normal) { if (lastChar == '/') { // 判断注释是否开始 | Check if comments start if (c == '/') { // 单行注释 | Single-line comments start matchState = MatchState.SingleLineComments; } else if (c == '*') { // 多行注释开始 | Multi-line comments start matchState = MatchState.MultiLineComments; } else { // 非注释 添加字符 | Not comments. Add character lastLength += 1; } } else { // 非注释 添加字符 | Not comments. Add character lastLength += 1; } } } } // 已添加了词法单元信息 重置临时数据 | Reset temp data after add token if (needClear) { needClear = false; lastChar = '\x0'; lastTag = LBTag.None; lastIndex = index; lastLength = 0; lastRow = row; lastColumn = column; } column += 1; lastChar = c; } AddToken(tokens, lastTag, lastIndex, lastLength, lastRow, lastColumn); return(tokens); }
/// <summary> 语法解析 | Syntax parse </summary> public static LBReport Analyze(string code, List <LBToken> tokens) { // 检查参数 if (string.IsNullOrEmpty(code)) { throw new System.ArgumentNullException("code", "Code can not be null or empty"); } if (tokens == null || tokens.Count == 0) { throw new System.ArgumentNullException("tokens", "Tokens can not be null or empty"); } string error = ""; // 筛选有效单词 | Get valid worlds List <LBToken> validTokens = new List <LBToken>(7); int total = tokens.Count; for (int i = 0; i < total; i++) { LBToken token = tokens[i]; if (token.tag == LBTag.Word) { // 检查单词有效性 | Valid word if (IsDigit(code[token.index])) { // 第一个字符不能为数字 | The first character cannot be a number string err = "The first character of an identifier cannot be a number "; err += '\'' + code[token.index].ToString() + '\''; error = error + GetErrorPrefix(code, token) + err + '\n'; continue; } else if (IsAccessModifier(code, token)) { // 忽略访问修饰符 | Ignore access modifier continue; } } // 添加有效单词 | Add valid word validTokens.Add(token); } if (error != "") { return(new LBReport(false, null, error)); } // 检查是否是结构体格式 | Valid type format if (validTokens.Count < 7) { error += "Parse struct error: Not enough words"; return(new LBReport(false, null, error)); } bool isClass = IsMatch(code, validTokens[0], "class"); bool isStruct = IsMatch(code, validTokens[0], "struct"); if (!isClass && !isStruct) { LBToken token = validTokens[0]; string err = "Unexpected word \"" + GetString(code, token) + "\" expecting \"class\" or \"struct\" "; error = error + GetErrorPrefix(code, token) + err + '\n'; } if (!IsMatch(code, validTokens[2], "{")) { LBToken token = validTokens[2]; string err = "Unexpected word \"" + GetString(code, token) + "\" expecting '{'"; error = error + GetErrorPrefix(code, token) + err + '\n'; } if (!IsMatch(code, validTokens[validTokens.Count - 1], "}")) { LBToken token = validTokens[validTokens.Count - 1]; string err = "Unexpected word \"" + GetString(code, token) + "\" expecting '}'"; error = error + GetErrorPrefix(code, token) + err + '\n'; } if (error != "") { return(new LBReport(false, null, error)); } // 解析结构体字段 | Parse fields int count = validTokens.Count - 1; List <LBType> fields = new List <LBType>(); LBType field = new LBType(); bool hasType = false; bool hasName = false; bool hasLSquareBracket = false; bool hasRSquareBracket = false; for (int i = 3; i < count; i++) { LBToken token = validTokens[i]; LBTag tag = token.tag; if (!hasType) { // 匹配字段类型 | Match field type if (tag == LBTag.Word) { hasType = true; field.InitTypeName(GetString(code, token), field.Name); } else { string err = "Unexpected word \"" + GetString(code, token) + "\" expecting [FieldType]"; error = error + GetErrorPrefix(code, token) + err + '\n'; } } else if (!hasName) { // 匹配字段名称 | Match field name if (tag == LBTag.Word) { hasName = true; field.InitTypeName(field.Type, GetString(code, token)); } else { // 匹配数组的"[]" | Match array "[]" if (!hasLSquareBracket && tag == LBTag.LSquareBracket) { hasLSquareBracket = true; } else if (hasLSquareBracket && !hasRSquareBracket) { if (tag == LBTag.RSquareBracket) { // 匹配到数组 "[]" | Match to array "[]" hasRSquareBracket = true; LBType elementType = new LBType(field.Type, null); field.InitTypeName(field.Type + "[]", field.Name); field.InitArray(elementType); } else { string err = "Unexpected word \"" + GetString(code, token) + "\" expecting ']'"; error = error + GetErrorPrefix(code, token) + err + '\n'; } } else { string err = "Unexpected word \"" + GetString(code, token) + "\" expecting [FieldName]"; error = error + GetErrorPrefix(code, token) + err + '\n'; } } } else { // 匹配字段结束 | Match end if (tag == LBTag.Semicolon) { fields.Add(field); } else { string err = "Expecting \";\""; error = error + GetErrorPrefix(code, validTokens[i - 1]) + err + '\n'; if (i > 3) { i -= 1; } } // 重置临时数据 | Reset temp data field = new LBType(); hasType = false; hasName = false; hasLSquareBracket = false; hasRSquareBracket = false; } } // 最末尾 | At the end if (hasType) { LBToken token = validTokens[count - 1]; if (!hasName) { string err = "Expecting [FieldName]"; error = error + GetErrorPrefix(code, token) + err + '\n'; } else { string err = "Expecting \";\""; error = error + GetErrorPrefix(code, validTokens[count - 2]) + err + '\n'; } } // 检查字段数量 | Check fields count if (fields.Count == 0) { error = error + "Valid field count is 0"; } if (error != "") { return(new LBReport(false, null, error)); } // 生成主体类型 | Generate main type LBType customType = new LBType(GetString(code, validTokens[0]), GetString(code, validTokens[1])); customType.InitCustomType(isClass, isStruct, fields); return(new LBReport(true, customType, null)); }