| | |
| | | #ifndef EXTERNINTERFACE_H |
| | | #define EXTERNINTERFACE_H |
| | | #include <iostream> |
| | | #include<vector> |
| | | |
| | | //这个类用在做SCPI命令的语法分析,会将词法匹配的结果返回给SCPI库 |
| | | #ifdef __cplusplus |
| | | extern "C" |
| | | { |
| | | #endif |
| | | namespace SCPIPASER |
| | | typedef struct |
| | | { |
| | | class Segment { |
| | | public: |
| | | //必填 |
| | | bool is_required = false; |
| | | //变量 [:Measure] 这种的为变量 会置为TRUE |
| | | bool is_variable = false; |
| | | //是否有嵌套形式 |
| | | bool is_nested = false; |
| | | // 可选组的数量 |
| | | int variableSize = 0; |
| | | std::vector<std::string> options; |
| | | // std::vector<Segment> sub_segments; // 用于存储嵌套的可选组 |
| | | }; |
| | | int is_required; |
| | | int is_variable; |
| | | int is_nested; |
| | | int variableSize; |
| | | char** options; |
| | | int options_count; |
| | | } CSegment; |
| | | |
| | | class PatternParser |
| | | typedef struct |
| | | { |
| | | private: |
| | | static void trim_whitespace(std::string& str) |
| | | { |
| | | auto not_space = [](int ch) { return !std::isspace(ch); }; |
| | | str.erase(str.begin(), std::find_if(str.begin(), str.end(), not_space)); |
| | | str.erase(std::find_if(str.rbegin(), str.rend(), not_space).base(), str.end()); |
| | | } |
| | | |
| | | static std::vector<std::string> split_options(const std::string& input) { |
| | | std::vector<std::string> result; |
| | | size_t start = 0; |
| | | size_t end = input.find('|'); |
| | | |
| | | while (end != std::string::npos) { |
| | | std::string token = input.substr(start, end - start); |
| | | trim_whitespace(token); |
| | | //token = remove_colon(token); // 移除冒号 |
| | | if (!token.empty()) result.push_back(token); |
| | | start = end + 1; |
| | | end = input.find('|', start); |
| | | } |
| | | |
| | | std::string last_token = input.substr(start); |
| | | trim_whitespace(last_token); |
| | | last_token = remove_colon(last_token); // 移除冒号 |
| | | if (!last_token.empty()) result.push_back(last_token); |
| | | return result; |
| | | } |
| | | |
| | | static std::string remove_colon(const std::string& input) { |
| | | std::string result; |
| | | for (char ch : input) { |
| | | if (ch != ':') { |
| | | result += ch; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | public: |
| | | static std::vector<std::string> parse_input_data(const std::string& input) |
| | | { |
| | | std::vector<std::string> result; |
| | | size_t start = 0; |
| | | size_t end = input.find(':'); |
| | | |
| | | while (end != std::string::npos) |
| | | { |
| | | result.push_back(input.substr(start, end - start)); |
| | | start = end + 1; |
| | | end = input.find(':', start); |
| | | } |
| | | |
| | | result.push_back(input.substr(start)); |
| | | return result; |
| | | } |
| | | static bool match_all_segments(std::vector<std::string> stringList, std::vector<Segment> vecSegment) |
| | | { |
| | | int currentIndex = 0; |
| | | for (int i =0;i<vecSegment.size();i++) |
| | | { |
| | | auto currentSegment = vecSegment[i]; |
| | | //严格匹配 |
| | | if (currentSegment.is_required) |
| | | { |
| | | for (auto option : currentSegment.options) |
| | | { |
| | | if (stringList[currentIndex] != option) |
| | | { |
| | | //std::cout << "参数匹配失败 " << stringList[currentIndex] << " option : " << option; |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | //std::cout << "参数匹配成功 " << stringList[currentIndex] << " option : " << option<<std::endl; |
| | | currentIndex += 1; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | //可选组 |
| | | else if (currentSegment.is_variable) |
| | | { |
| | | //如果有可选组的情况下 且参数长度一直 则匹配可选项内容 否则的话跳过 |
| | | if (stringList.size() == vecSegment.size()) |
| | | { |
| | | auto vecTempSegments = currentSegment.options; |
| | | for (auto option : vecTempSegments) |
| | | { |
| | | if (stringList[currentIndex] != option) |
| | | { |
| | | //std::cout << "参数匹配失败 " << stringList[currentIndex] << " option : " << option; |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | //std::cout << "参数匹配成功 " << stringList[currentIndex] << " option : " << option << std::endl; |
| | | currentIndex += 1; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | //可变参 |
| | | else |
| | | { |
| | | //std::cout << "可变参数: "<< stringList[currentIndex] << " " << currentSegment.options[0] << std::endl; |
| | | currentIndex += 1; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | CSegment* segments; |
| | | int segments_count; |
| | | } CPatternResult; |
| | | |
| | | |
| | | static std::vector<Segment> extract_all_segments(const std::string& pattern) |
| | | { |
| | | std::vector<Segment> segments; |
| | | size_t pos = 0; |
| | | const size_t len = pattern.length(); |
| | | |
| | | while (pos < len) |
| | | { |
| | | while (pos < len && std::isspace(pattern[pos])) ++pos; |
| | | if (pos >= len) break; |
| | | |
| | | if (pattern[pos] == '<') { |
| | | size_t end_pos = pattern.find('>', pos); |
| | | if (end_pos == std::string::npos) break; |
| | | |
| | | std::string content = pattern.substr(pos + 1, end_pos - pos - 1); |
| | | trim_whitespace(content); |
| | | |
| | | Segment segment; |
| | | segment.is_variable = false; // `<...>` 不被视为变量 |
| | | segment.options = split_options(content); |
| | | |
| | | // 检查是否包含 `:` |
| | | if (content.find(':') != std::string::npos) { |
| | | segment.is_required = true; // 如果包含 `:` |
| | | } |
| | | else { |
| | | segment.is_required = false; // 如果不包含 `:` |
| | | } |
| | | |
| | | segments.push_back(segment); |
| | | pos = end_pos + 1; |
| | | } |
| | | else if (pattern[pos] == '[') |
| | | { |
| | | size_t end_pos = pattern.find(']', pos); |
| | | if (end_pos == std::string::npos) break; |
| | | |
| | | std::string content = pattern.substr(pos + 1, end_pos - pos - 1); |
| | | trim_whitespace(content); |
| | | |
| | | Segment segment; |
| | | segment.variableSize += 1; |
| | | segment.is_required = false; |
| | | segment.is_variable = true; |
| | | |
| | | segment.options = split_options(content); |
| | | |
| | | segments.push_back(segment); |
| | | pos = end_pos + 1; |
| | | } |
| | | else |
| | | { |
| | | size_t next_lt = pattern.find('<', pos); |
| | | size_t next_lb = pattern.find('[', pos); |
| | | size_t next_special = std::min(next_lt, next_lb); |
| | | |
| | | std::string content; |
| | | if (next_special != std::string::npos) |
| | | { |
| | | content = pattern.substr(pos, next_special - pos); |
| | | } |
| | | else |
| | | { |
| | | content = pattern.substr(pos); |
| | | } |
| | | trim_whitespace(content); |
| | | |
| | | if (!content.empty()) |
| | | { |
| | | // 用 ':' 拆分参数 |
| | | size_t start = 0; |
| | | size_t end = content.find(':'); |
| | | while (end != std::string::npos) |
| | | { |
| | | std::string token = content.substr(start, end - start); |
| | | trim_whitespace(token); |
| | | |
| | | if (!token.empty()) |
| | | { |
| | | Segment segment; |
| | | segment.is_required = true; // 明确标记为必填项 |
| | | segment.is_variable = false; // 普通文本不视为变量 |
| | | segment.options.push_back(token); |
| | | segments.push_back(segment); |
| | | } |
| | | start = end + 1; |
| | | end = content.find(':', start); |
| | | } |
| | | // 处理最后一个部分 |
| | | std::string last_token = content.substr(start); |
| | | trim_whitespace(last_token); |
| | | if (!last_token.empty()) |
| | | { |
| | | Segment segment; |
| | | segment.is_required = true; |
| | | segment.is_variable = false; |
| | | segment.options.push_back(last_token); |
| | | segments.push_back(segment); |
| | | } |
| | | } |
| | | pos = (next_special != std::string::npos) ? next_special : len; |
| | | } |
| | | } |
| | | |
| | | return segments; |
| | | } |
| | | |
| | | }; |
| | | } |
| | | int match_segments_global(const char* input, int pattern_index); |
| | | void parse_pattern_global(const char* pattern); |
| | | int get_pattern_count(); |
| | | void clear_global_patterns(); |
| | | #ifdef __cplusplus |
| | | } |
| | | #endif |
| | | |
| | | #endif // EXTERNINTERFACE_H |