// 字符串匹配 bool AnalysisABnfStringMatch(ABnfRuleInfo rule , ABnfRuleNodeInfo node, ABnfNodeElement parent, bool not_key , ref int line, ref int col, ref int offset , bool ignore_error) { // 跳过空格,制表符,换行 AnalysisSkip(ref line, ref col, ref offset); bool succeed = true; for (int i = 0; i < node.value.value.Length; ++i) { // 匹配失败 if (offset + i >= m_file.m_text.Length || node.value.value[i] != m_file.m_text[offset + i]) { succeed = false; break; } } // 检查 if (succeed) { int next = offset + node.value.value.Length; if (next < m_file.m_text.Length) { if (m_symbol_check.TryGetValue(node.value.value, out HashSet <char> set)) { if (set.Contains(m_file.m_text[next])) { succeed = false; } } } } if (!succeed) { // 如果是注释就跳过 if (rule == m_line_comment || rule == m_block_comment) { return(false); } // 如果忽略错误就跳过 if (ignore_error) { return(false); } // 添加错误节点 if (offset < m_file.m_text.Length) { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却得到" + m_file.m_text[offset], new ABnfStringElement(m_factory, m_file, line, col, offset, node.value.value))); } else { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却得到文件结尾", new ABnfStringElement(m_factory, m_file, line, col, offset, node.value.value))); } return(false); } // 添加正确的节点 parent.AddChild(CreateStringElement(line, col, offset, node.value.value)); AnalysisOffset(node.value.value.Length, ref line, ref col, ref offset); return(true); }
// 关键字匹配 bool AnalysisABnfKeyMatch(ABnfRuleInfo rule , ABnfRuleNodeInfo node, ABnfNodeElement parent, bool not_key , ref int line, ref int col, ref int offset , bool ignore_error) { // 跳过空格,制表符,换行 AnalysisSkip(ref line, ref col, ref offset); bool succeed = true; for (int i = 0; i < node.value.value.Length; ++i) { // 匹配失败 if (offset + i >= m_file.m_text.Length || node.value.value[i] != m_file.m_text[offset + i]) { succeed = false; break; } } if (succeed) { int next_offset = offset + node.value.value.Length; if (next_offset < m_file.m_text.Length) { char next_char = m_file.m_text[next_offset]; if (next_char >= '0' && next_char <= '9' || next_char >= 'a' && next_char <= 'z' || next_char >= 'A' && next_char <= 'Z' || next_char == '_') { succeed = false; } } } if (!succeed) { // 如果是注释就跳过 if (rule == m_line_comment || rule == m_block_comment) { return(false); } // 如果忽略错误就跳过 if (ignore_error) { return(false); } // 添加错误节点 if (offset < m_file.m_text.Length) { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却得到" + m_file.m_text[offset], new ABnfKeyElement(m_factory, m_file, line, col, offset, node.value.value))); } else { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却得到文件结尾", new ABnfKeyElement(m_factory, m_file, line, col, offset, node.value.value))); } return(false); } // 添加正确的节点 parent.AddChild(CreateKeyElement(line, col, offset, node.value.value)); AnalysisOffset(node.value.value.Length, ref line, ref col, ref offset); return(true); }
// 规则节点 bool AnalysisABnfRuleMatch(ABnfRuleInfo rule, ABnfNodeElement parent, bool not_key , ref int line, ref int col, ref int offset , ref int pin_offset, bool ignore_error) { // 跳过空格,制表符,换行 AnalysisSkip(ref line, ref col, ref offset); // 跳过注释 AnalysisABnfCommentMatch(rule, parent, not_key, ref line, ref col, ref offset); // 跳过空格,制表符,换行 AnalysisSkip(ref line, ref col, ref offset); if (offset >= m_file.m_text.Length) { return(false); } char next_char = m_file.m_text[offset]; if (!rule.CheckNextChar(next_char, out List <int> index_list)) { return(false); } // 遍历选择规则 List <ABnfNodeElement> option_list = null; foreach (var option_index in index_list) { if (!rule.node.PreCheck(m_file, offset)) { continue; } var node_list = rule.node.node_list[option_index]; // 缓存位置 int temp_line = line; int temp_col = col; int temp_offset = offset; // 标记当前规则是否有pin int temp_pin_offset = -1; // 是否匹配成功 bool match = true; // 开始处理规则 ABnfNodeElement element = CreateNodeElement(line, col, offset, rule.id.value); for (int index = 0; index < node_list.Count; ++index) { int sub_pin_offset = -1; if (!AnalysisABnfNode(rule, node_list[index], element, not_key , ref temp_line, ref temp_col, ref temp_offset , ref sub_pin_offset, false)) { // 如果匹配失败,并且内部有pin,那么当前也要设置为pin if (sub_pin_offset >= 0) { temp_pin_offset = sub_pin_offset; } match = false; break; } // 如果匹配失败,并且内部有pin,那么当前也要设置为pin if (sub_pin_offset >= 0) { temp_pin_offset = sub_pin_offset; } // 如果规则本身有pin,那么也要设置为pin if (node_list[index].pin == ABnfRuleNodePinType.NPT_TRUE) { temp_pin_offset = temp_offset; } } // 匹配成功 if (match) { // 添加到节点中 if (element.GetChilds().Count != 0) { parent.AddChild(element); } // 返回结果位置 line = temp_line; col = temp_col; offset = temp_offset; if (temp_pin_offset >= 0) { pin_offset = temp_pin_offset; } return(true); } // 如果出现pin,那么对外比较pin // 清理之前的节点,添加自己并跳出 if (temp_pin_offset >= 0) { pin_offset = temp_pin_offset; line = temp_line; col = temp_col; offset = temp_offset; if (option_list == null) { option_list = new List <ABnfNodeElement>(); } option_list.Clear(); option_list.Add(element); break; } // 如果没有出现pin,把错误添加到option_list else { if (option_list == null) { option_list = new List <ABnfNodeElement>(); } option_list.Add(element); } } // 没有pin并且忽略错误的情况下,直接返回false if (pin_offset < 0 && ignore_error) { return(false); } // 处理option_list if (option_list != null) { foreach (var option in option_list) { if (option.GetChilds().Count != 0) { parent.AddChild(option); } } } // 如果有pin,并且有结束符 if (pin_offset >= 0) { // 从pin_offset开始查找结束符 int find = m_file.m_text.Length; int index = -1; for (int i = m_stop_stack.Count - 1; i >= 0; --i) { string stop_token = m_stop_stack[i].GetStopToken(); if (stop_token == null) { continue; } int value = m_file.m_text.IndexOf(stop_token, pin_offset, find - pin_offset); if (value >= 0 && find > value) { find = value; index = i; } } if (index >= 0) { if (m_stop_stack[index] == rule) { AnalysisOffset(find + m_stop_stack[index].GetStopToken().Length - offset, ref line, ref col, ref offset); parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, "语法错误", null)); return(true); } else if (index == m_stop_stack.Count - 2) { AnalysisOffset(find - offset, ref line, ref col, ref offset); parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, "语法错误", null)); return(true); } } } return(false); }
// 分析节点 bool AnalysisABnfNodeMatch(ABnfRuleInfo rule , ABnfRuleNodeInfo node, ABnfNodeElement parent, bool not_key , ref int line, ref int col, ref int offset , ref int pin_offset, bool ignore_error) { // 判断是不是叶子节点 if (node.value != null) { // 如果是匹配子规则 if (node.value.type == ABnfRuleTokenType.TT_ID) { // 如果没有找到子规则 ABnfRuleInfo child = node.value.rule; if (child == null) { child = m_rule.FindRuleInfo(node.value.value); node.value.rule = child; } if (child == null) { // 如果忽略错误,直接返回false if (ignore_error) { return(false); } // 跳过空格,tab,换行 AnalysisSkip(ref line, ref col, ref offset); // 添加错误节点 parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, "未知规则:" + node.value.value, null)); return(false); } // 添加结束符 m_stop_stack.Add(child); // 匹配子规则,子规则的pin是不能传出来的 bool result = AnalysisABnfRuleMatch(child, parent, node.not_key == ABnfRuleNodeNotKeyType.NNKT_TRUE || not_key , ref line, ref col, ref offset , ref pin_offset, ignore_error); // 删除结束符 m_stop_stack.RemoveAt(m_stop_stack.Count - 1); return(result); } // 如果是正则表达式 if (node.value.type == ABnfRuleTokenType.TT_REGEX) { return(AnalysisABnfRegexMatch(rule, node, parent, node.not_key == ABnfRuleNodeNotKeyType.NNKT_TRUE || not_key, ref line, ref col, ref offset, ref pin_offset, ignore_error)); } // 如果是关键字 if (node.value.type == ABnfRuleTokenType.TT_KEY) { return(AnalysisABnfKeyMatch(rule, node, parent, node.not_key == ABnfRuleNodeNotKeyType.NNKT_TRUE || not_key, ref line, ref col, ref offset, ignore_error)); } // 剩下的就是普通字符串 return(AnalysisABnfStringMatch(rule, node, parent, node.not_key == ABnfRuleNodeNotKeyType.NNKT_TRUE || not_key, ref line, ref col, ref offset, ignore_error)); } // 如果是一个组规则 // 跳过空格,制表符,换行 AnalysisSkip(ref line, ref col, ref offset); // 跳过注释 AnalysisABnfCommentMatch(rule, parent, not_key, ref line, ref col, ref offset); // 跳过空格,制表符,换行 AnalysisSkip(ref line, ref col, ref offset); if (offset >= m_file.m_text.Length) { return(false); } char next_char = m_file.m_text[offset]; if (!node.CheckNextChar(m_rule, next_char, out List <int> index_list)) { return(false); } // 遍历选择规则 List <ABnfNodeElement> option_list = null; foreach (var option_index in index_list) { if (!node.PreCheck(m_file, offset)) { continue; } var node_list = node.node_list[option_index]; // 缓存位置 int temp_line = line; int temp_col = col; int temp_offset = offset; // 标记当前规则是否有pin int temp_pin_offset = -1; // 是否匹配成功 bool match = true; // 开始处理规则 ABnfNodeElement element = new ABnfNodeElement(m_factory, m_file, line, col, offset, ""); for (int index = 0; index < node_list.Count; ++index) { int sub_pin_offset = -1; if (!AnalysisABnfNode(rule, node_list[index], element, not_key , ref temp_line, ref temp_col, ref temp_offset , ref sub_pin_offset, false)) { // 如果匹配失败,并且内部有pin,那么当前也要设置为pin if (sub_pin_offset >= 0) { temp_pin_offset = sub_pin_offset; } match = false; break; } // 如果匹配失败,并且内部有pin,那么当前也要设置为pin if (sub_pin_offset >= 0) { temp_pin_offset = sub_pin_offset; } // 如果规则本身有pin,那么也要设置为pin if (node_list[index].pin == ABnfRuleNodePinType.NPT_TRUE) { temp_pin_offset = temp_offset; } } // 匹配成功 if (match) { // 添加到节点中 foreach (var child in element.GetChilds()) { if (child.IsLeafOrHasChildOrError()) { parent.AddChild(child); } } // 返回结果位置 line = temp_line; col = temp_col; offset = temp_offset; if (temp_pin_offset >= 0) { pin_offset = temp_pin_offset; } return(true); } // 如果出现pin,那么对外比较pin // 清理之前的节点,添加自己并跳出 if (temp_pin_offset >= 0) { pin_offset = temp_pin_offset; line = temp_line; col = temp_col; offset = temp_offset; if (option_list == null) { option_list = new List <ABnfNodeElement>(); } option_list.Clear(); option_list.Add(element); break; } // 如果没有出现pin,把错误添加到option_list else { if (option_list == null) { option_list = new List <ABnfNodeElement>(); } option_list.Add(element); } } // 没有pin并且忽略错误的情况下,直接返回false if (pin_offset < 0 && ignore_error) { return(false); } // 处理option_list if (option_list != null) { foreach (var option in option_list) { foreach (var child in option.GetChilds()) { if (child.IsLeafOrHasChildOrError()) { parent.AddChild(child); } } } } return(false); }
// 正则表达式匹配 bool AnalysisABnfRegexMatch(ABnfRuleInfo rule , ABnfRuleNodeInfo node, ABnfNodeElement parent, bool not_key , ref int line, ref int col, ref int offset , ref int pin_offset, bool ignore_error) { // 跳过空格,制表符,换行 AnalysisSkip(ref line, ref col, ref offset); // 获取缓存 int length = 0; Dictionary <ABnfRuleNodeInfo, int> map; bool cache = m_regex_skip.TryGetValue(offset, out map) && map.TryGetValue(node, out length); if (!cache) { // 正则表达式匹配 if (node.value.regex == null) { node.value.regex = new Regex(node.value.value, RegexOptions.Compiled); } // 开始匹配 var match = node.value.regex.Match(m_file.m_text, offset, m_file.m_text.Length - offset); if (match != null && match.Success && match.Index == offset) { length = match.Value.Length; } // 如果没有匹配到,并且规则的预测值有pin if (length == 0 && rule.prediction != null && rule.prediction_pin == ABnfRuleNodePinType.NPT_TRUE) { // 正则表达式匹配 if (rule.prediction.regex == null) { rule.prediction.regex = new Regex(rule.prediction.value, RegexOptions.Compiled); } // 预测匹配 var pre_match = rule.prediction.regex.Match(m_file.m_text, offset, m_file.m_text.Length - offset); if (pre_match != null && pre_match.Success && pre_match.Index == offset) { length = -pre_match.Value.Length; } } // 添加缓存 if (map == null) { map = new Dictionary <ABnfRuleNodeInfo, int>(); m_regex_skip.Add(offset, map); } map.Add(node, length); } // 如果有找到,那么就添加正确节点 if (length > 0) { string value = m_file.m_text.Substring(offset, length); // 正则表达式匹配的结果不能是关键字 if (not_key || !m_rule.GetKeySet().Contains(value)) { parent.AddChild(CreateRegexElement(line, col, offset, value, node.value.regex)); AnalysisOffset(length, ref line, ref col, ref offset); return(true); } } // 如果是注释那么不添加错误节点 if (rule == m_line_comment || rule == m_block_comment) { return(false); } // 如果忽略错误,也不添加错误节点 if (ignore_error) { return(false); } // 添加错误节点 if (offset < m_file.m_text.Length) { if (length > 0) { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却得到关键字" + m_file.m_text.Substring(offset, length), new ABnfRegexElement(m_factory, m_file, line, col, offset, "", node.value.regex))); } else if (length < 0) { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却只得到" + m_file.m_text.Substring(offset, -length), new ABnfRegexElement(m_factory, m_file, line, col, offset, "", node.value.regex))); AnalysisOffset(-length, ref line, ref col, ref offset); pin_offset = offset - length; } else { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却得到" + m_file.m_text[offset], new ABnfRegexElement(m_factory, m_file, line, col, offset, "", node.value.regex))); } } else { parent.AddChild(new ABnfErrorElement(m_factory, m_file, line, col, offset, rule.id.value + "期望匹配" + node.value.value + " 却得到文件结尾", new ABnfRegexElement(m_factory, m_file, line, col, offset, "", node.value.regex))); } return(false); }