使用spirit能很方便的解析自定义的语法规则,在他的文档中也说明了spirit与regex还有其他库的不同点。灵活,伸缩性好,可以用来搭建小的语法解析器也可以用来开发大型编译器等等。
定义语法规则之前首先要了解一下Extended Backus-Normal Form (EBNF)
EBNF可以定义一下生成合法字符串的公式,例如:
例1:
rule1 = "0" | "1" | "2" | "3".
rule2 = "4" | "5" | "6" | "7" | "8" | "9" | rule1.
字符 | 表示 或,则 rule2 可以表示0-9所有的数字;一个复杂点的例子:
例2:
expression = term { ("+" | "-") term} .
term = factor { ("*"|"/") factor} .
factor = constant | variable | "(" expression ")" .
variable = "x" | "y" | "z" .
constant = digit {digit} .
digit = "0" | "1" | "..." | "9" .
表示一个合法的数学计算公式。
使用EBNF表示的语法可以很方便地用boost spirit表示:
例3:
EBNF:
group ::= ‘(‘ expression ‘)‘
factor ::= integer | group
term ::= factor ((‘*‘ factor) | (‘/‘ factor))*
expression ::= term ((‘+‘ term) | (‘-‘ term))*
Boost Spirit:
group = ‘(‘ >> expression >> ‘)‘;
factor = integer | group;
term = factor >> *((‘*‘ >> factor) | (‘/‘ >> factor));
expression = term >> *((‘+‘ >> term) | (‘-‘ >> term));
其中 ::=
表示 被定义为
的意思,与=
号表示的意思相同,integer
表示所有整数,在例3中如下这些表达式都是合法的:
12345
-12345
+12345
1 + 2
1 * 2
1/2 + 3/4
1 + 2 + 3 + 4
1 * 2 * 3 * 4
(1 + 2) * (3 + 4)
(-1 + 2) * (3 + -4)
1 + ((6 * 200) - 20) / 6
(1 + (2 + (3 + (4 + 5))))
但是这些表达式则不合法:
1/2 +-+ 3/4
1 +/ 2 += 3 + 4
1 + 2 * 3.14 * 4
(1 + 2) .* (3 + 4)
直接上代码:
#include <...>
using namespace ...
int main()
{
std::string cmd_str = "$aaa[bbb]==ccc LINE 123"
std::vector<char> name1;
std::vector<char> name2;
std::vector<char> value;
int var=0;
std::string::iterator iter_begin = cmd_str.begin();
bool parse_ok = qi::phrase_parse(iter_begin, cmd_str.end(),
// Begin grammar
(
(‘$‘
>>(+(qi::char_ - ‘[‘))[boost::phoenix::ref( component_name ) = qi::_1] // 获得aaa
>> ‘[‘
>> (+(qi::char_ - ‘]‘))[boost::phoenix::ref( variable_name ) = qi::_1] // 获得bbb
>> ‘]‘
>> lit("==")
>> (+(qi::char_-lit("LINE")))[boost::phoenix::ref( target_value ) = qi::_1] // 获得ccc
^
(-(lit("LINE") >> qi::int_[boost::phoenix::ref(var) = qi::_1])) // 获得123
),
// End grammar
ascii::space // skip the space
);
// 判断是否符合语法规则
if (!parse_ok || iter_begin != cmd_str.end())
{
return -1
}
std::cout << std::string(name1.begin(), name1.end()) << std::endl;
std::cout << std::string(name2.begin(), name2.end()) << std::endl;
std::cout << std::string(value.begin(), value.end()) << std::endl;
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-07-31 22:53:46