我想创建一个语法和词法分析器来解析下面的字符串:
100 reason phrase
正则表达式为:“\ d {3} [^ \ r \ n] *”
令牌定义:
template <typename Lexer>
struct custom_tokens : lex::lexer<Lexer>
{
custom_tokens()
{
this->self.add_pattern
("STATUSCODE", "\\d{3}")
("SP", " ")
("REASONPHRASE", "[^\r\n]*")
;
this->self.add
("{STATUSCODE}", T_STATUSCODE)
("{SP}", T_SP)
("{REASONPHRASE}", T_REASONPHRASE)
;
}
};
语法:
template <typename Iterator>
struct custom_grammar : qi::grammar<Iterator >
{
template <typename TokenDef>
custom_grammar(TokenDef const& tok)
: custom_grammar::base_type(start)
{
start = (qi::token(T_STATUSCODE) >> qi::token(T_SP) >> qi::token(T_REASONPHRASE));
}
qi::rule<Iterator> start;
};
然而,我意识到我无法定义标记“T_REASONPHRASE”,因为它将匹配包括“T_STATUSCODE”在内的所有内容。我能做的是
取消定义T_REASONPHRASE并使用qi :: lexeme在custom_grammar中编写规则?
我可以使用lex state来做到这一点吗?例如在第二个状态中定义“T_REASONPHRASE”,如果它在第一个状态中看到T_STATUSCODE然后将其余部分解析为第二个状态?请举个例子?
答案 0 :(得分:2)
我认为确实没有问题,因为令牌按照它们被添加到令牌定义的顺序“贪婪地”匹配(对于特定的词法分析器状态)。
所以,给定
this->self.add
("{STATUSCODE}", T_STATUSCODE)
("{SP}", T_SP)
("{REASONPHRASE}", T_REASONPHRASE)
;
T_STATUSCODE将在T_REASONPHRASE之前始终匹配(如果存在歧义)。
关于使用单独的Lexer状态,这里是我曾经在玩具项目中使用的标记器的摘录:
this->self = fileheader [ lex::_state = "GT" ];
this->self("GT") =
gametype_label |
gametype_63000 | gametype_63001 | gametype_63002 |
gametype_63003 | gametype_63004 | gametype_63005 |
gametype_63006 |
gametype_eol [ lex::_state = "ML" ];
this->self("ML") = mvnumber [ lex::_state = "MV" ];
this->self("MV") = piece | field | op | check | CASTLEK | CASTLEQ
| promotion
| Checkmate | Stalemate | EnPassant
| eol [ lex::_state = "ML" ]
| space [ lex::_pass = lex::pass_flags::pass_ignore ];
(如果您将GT
视为游戏类型,ML
:移动行和MV
,目的就会相对清晰: move ;请注意此处eol
和gametype_eol
的存在:Lex不允许向不同的州添加相同的令牌)