函數語法分析

這兩天在做一個報送交易所交易系統信息的工作,任務內容是從已有的信息中取出配置文件指定的信息,按照指定的格式拼接好。爲了實現一些擴展性,對配置項的語法進行了函數支持。在做這個事情的同時,順便實現了一些字符串相關的函數。

ParseSystemInfo.h

#include <vector>
#include <string>
#pragma once

enum class NodeType
{
	CONST_VALUE,
	FIELD,
	FUNCTION,
};

struct Node
{
	NodeType NodeType;
	std::string NodeName;

	std::vector<Node*> Children;

	std::string GetValue();
};

typedef std::string FUNCTION(std::vector<Node*>);

void Init();
void PrintNode(Node* head, int depth);

bool StartsWith(std::string src, std::string sub);
bool EndsWith(std::string src, std::string sub);

std::string Lstrip(const std::string& src);
std::string Rstrip(const std::string& src);
std::string Strip(const std::string& src);
std::string StripQuote(const std::string& src);

std::vector<std::string> Split(const std::string& src, const std::string& separator);
std::vector<std::string> Split(const std::string& src, char separator);



std::string GetParamString(const std::string& src, size_t& endIndex);
std::string GetNextNodeString(const std::string& src, size_t& endIndex, char op);
std::string GetTopLevelNextNodeString(const std::string& src, size_t& endIndex);
std::string GetParamNextNodeString(const std::string& src, size_t& endIndex);

void ParseParam(std::string src, Node* parent);
void ParseNode(std::string src, Node* node);
std::string ParseSystemInfo(std::string src);

ParseSystemInfo.cpp

#include "ParseSystemInfo.h"
#include <map>

using namespace std;

map<string, string> StepValues;
map<string, FUNCTION*> StepFuncs;

string StringCat(vector<Node*> nodes)
{
	string result = "";
	for (auto node : nodes)
	{
		result += node->GetValue();
	}
    return result;
}
string IfNull(vector<Node*> nodes)
{
	if (nodes.size() != 3)
	{
		return "";
	}
	auto condition = nodes[0]->GetValue();
	auto first = nodes[1]->GetValue();
	auto second = nodes[2]->GetValue();
	if (!condition.empty())
	{
		return first;
	}
	return second;
}


std::string Node::GetValue()
{
	if (NodeType == NodeType::CONST_VALUE)
	{
		return NodeName;
	}
	else if (NodeType == NodeType::FIELD)
	{
		return StepValues[NodeName];
	}
	else if (NodeType == NodeType::FUNCTION)
	{
		return StepFuncs[NodeName](Children);
	}
        return "";
}

void Init()
{
	string key = "STEP_IP";
	string value = "192.168.6.78";
	StepValues[key] = value;
	key = "STEP_MAC";
	value = "F4-8E-38-83-E2-3D";
	StepValues[key] = value;
	key = "STEP_LOCAL_MAC";
	value = "F4-8E-38-83-E2-4E";
	StepValues[key] = value;

	key = "STRING";
	StepFuncs[key] = StringCat;
	key = "IFNULL";
	StepFuncs[key] = IfNull;
}
void PrintNode(Node* head, int depth)
{
	string indent(depth * 2, '-');
	printf("%sNodeType[%d], NodeName[%s]\n", indent.c_str(), head->NodeType, head->NodeName.c_str());
	depth++;
	for (auto node : head->Children)
	{
		PrintNode(node, depth);
	}
}

bool StartsWith(std::string src, std::string sub)
{
	return src.find(sub) == 0;
}
bool EndsWith(std::string src, std::string sub)
{
	return src.rfind(sub) == (src.length() - sub.length());
}

std::string Lstrip(const std::string& s)
{
	if (s.front() != ' ')
		return s;
	for (auto index = 0u; index < s.size(); index++)
	{
		if (s[index] != ' ')
		{
			return s.substr(index);
		}
	}
	return s;
}
std::string Rstrip(const std::string& s)
{
	if (s.back() != ' ')
		return s;
	for (auto index = s.size() - 1; index >= 0; index--)
	{
		if (s[index] != ' ')
		{
			return s.substr(0, index + 1);
		}
	}
	return s;
}
std::string Strip(const std::string& s)
{
	string newString = Lstrip(s);
	return Rstrip(newString);
}
std::string StripQuote(const std::string& src)
{
	if (StartsWith(src, "\"") && EndsWith(src, "\""))
	{
		return src.substr(1, src.size() - 2);
	}
	return src;
}

std::vector<std::string> Split(const std::string& s, const std::string& separator)
{
	vector<string> result;
	int pos;
	string temp = s;
	while ((pos = temp.find_first_of(separator)) != temp.npos)
	{
		if (pos > 0)
		{
			result.push_back(temp.substr(0, pos));
		}
		temp = temp.substr(pos + separator.length());
	}
	if (temp.length() > 0)
	{
		result.push_back(temp);
	}
	return std::move(result);
}
std::vector<std::string> Split(const std::string& s, char separator)
{
	vector<string> result;
	int pos;
	string temp = s;
	while ((pos = temp.find_first_of(separator)) != temp.npos)
	{
		if (pos > 0)
		{
			result.push_back(temp.substr(0, pos));
		}
		temp = temp.substr(pos + 1);
	}
	if (temp.length() > 0)
	{
		result.push_back(temp);
	}
	return std::move(result);
}


std::string GetParamString(const std::string& src, size_t& endIndex)
{
	int start = 0;
	for (size_t index = 0; index < src.size(); index++)
	{
		if (src[index] == '(')
		{
			start = index + 1;
			break;
		}
	}
	auto count = 1u;
	for (size_t index = start + 1; index < src.size(); index++)
	{
		if (src[index] == '(')
		{
			count++;
			continue;
		}
		if (src[index] == ')')
		{
			count--;
			if (count == 0)
			{
				endIndex = index;
				break;
			}
			continue;
		}
	}
	return src.substr(start, endIndex - start);
}
std::string GetNextNodeString(const std::string& src, size_t& endIndex, char op)
{
	if (StartsWith(src, "$STEP"))
	{
		endIndex = src.find(op, 1);
		return src.substr(0, endIndex);
	}
	if (StartsWith(src, "$"))
	{
		GetParamString(src, endIndex);
		endIndex += 1;
		return src.substr(0, endIndex);
	}
	endIndex = src.find(op);
	return src.substr(0, endIndex);
}
std::string GetTopLevelNextNodeString(const std::string& src, size_t& endIndex)
{
	return GetNextNodeString(src, endIndex, '$');
}
std::string GetParamNextNodeString(const std::string& src, size_t& endIndex)
{
	return GetNextNodeString(src, endIndex, ',');
}

void ParseParam(std::string src, Node* parent)
{
	size_t index;
	while (!src.empty())
	{
		Node* node = new Node();
		parent->Children.push_back(node);
		auto dest = GetParamNextNodeString(src, index);
		ParseNode(dest, node);
		if (index == src.npos || index >= src.size())
		{
			src = "";
		}
		else
		{
			src = src.substr(index + 1);
			src = Lstrip(src);
		}
	}
}
void ParseNode(std::string src, Node* node)
{
	src = Strip(src);
	src = StripQuote(src);
	if (StartsWith(src, "$STEP"))
	{
		node->NodeType = NodeType::FIELD;
		node->NodeName = src.substr(1);
	}
	else if (StartsWith(src, "$"))
	{
		node->NodeType = NodeType::FUNCTION;
		auto index = src.find('(');
		node->NodeName = src.substr(1, index - 1);
		size_t endIndex;
		auto paramString = GetParamString(src, endIndex);
		ParseParam(paramString, node);
	}
	else
	{
		node->NodeType = NodeType::CONST_VALUE;
		node->NodeName = src;
	}
}
std::string ParseSystemInfo(std::string src)
{
	std::vector<Node*> headNodes;
	size_t index;
	src = Strip(src);
	while (src.size() > 0)
	{
		auto dest = GetTopLevelNextNodeString(src, index);
		src = src.substr(index);

		Node* head = new Node();
		ParseNode(dest, head);
		headNodes.push_back(head);
	}
	for (auto node : headNodes)
	{
		PrintNode(node, 0);
	}

	string result = "";
	for (auto node : headNodes)
	{
		result += node->GetValue();
	}
	return result;
}

main.cpp

#include <iostream>
#include "ParseSystemInfo.h"


using namespace std;

int main()
{
    Init();
    string src = R"(HDQQ:$STRING("IIP:", $STEP_IP, " ;" , $IFNULL($STEP_IP, $STEP_IP, "NA"))$STRING("MAC:", $IFNULL($STEP_IIP,  $STEP_IIP, "NA"), $STEP_LOCAL_MAC, "; ",1))";
    cout << src << endl;
    cout << ParseSystemInfo(src) << endl;
}

輸出信息:

HDQQ:$STRING("IIP:", $STEP_IP, " ;" , $IFNULL($STEP_IP, $STEP_IP, "NA"))$STRING("MAC:", $IFNULL($STEP_IIP,  $STEP_IIP, "NA"), $STEP_LOCAL_MAC, "; ",1)
NodeType[0], NodeName[HDQQ:]
NodeType[2], NodeName[STRING]
--NodeType[0], NodeName[IIP:]
--NodeType[1], NodeName[STEP_IP]
--NodeType[0], NodeName[ ;]
--NodeType[2], NodeName[IFNULL]
----NodeType[1], NodeName[STEP_IP]
----NodeType[1], NodeName[STEP_IP]
----NodeType[0], NodeName[NA]
NodeType[2], NodeName[STRING]
--NodeType[0], NodeName[MAC:]
--NodeType[2], NodeName[IFNULL]
----NodeType[1], NodeName[STEP_IIP]
----NodeType[1], NodeName[STEP_IIP]
----NodeType[0], NodeName[NA]
--NodeType[1], NodeName[STEP_LOCAL_MAC]
--NodeType[0], NodeName[; ]
--NodeType[0], NodeName[1]
HDQQ:IIP:192.168.6.78 ;192.168.6.78MAC:NAF4-8E-38-83-E2-4E; 1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章