如何在不使规则过于贪婪的情况下在 PEG 中执行前瞻?
How to perform lookaheads in a PEG without making the rule too greedy?
我正在用 Parslet 编写解析器。在我要解析的文件中,我有以下结构:
Item #1
denis calls 20
anna raises 60
denis calls 40
Item #2
another player raises 60
anna calls 60
...
为了解析动作,我做了以下操作:
- 由于我的操作数量有限但未知,所以我制定了一个
action
规则,并重复了它
- 对于每个动作,我都会解析所有内容,直到达到有效动作(即 'raises'、'calls' 等),因为玩家名称基本上可以包含任何字符。这是玩家名
- 然后我解析有效的动作,然后是space
问题是玩家名规则太贪心了,所以,解析后得到这样的响应:
{
item: '1',
players: [
{ player: 'denis', action: 'calls 20' },
{ player: 'anna', action: 'raises 60' },
{ player: 'denis', action: 'calls 40' },
{ player: '\n\nItem #2\nanother player', action: 'raises 60' },
{ player: 'anna', action: 'calls 60' },
]
}
这是我正在使用的代码:
rule :game_actions do
game_action >> space
end
rule :game_action do
in_game_action_player >> str(': ') >> in_game_action.as(:action) >> space >> game_action.as(:next).maybe
end
rule :in_game_action_player do
((str(': ') >> in_game_action).absent? >> any).repeat(1).as(:player)
end
rule :in_game_action do
fold | check | call | bet | raises
end
所以,这似乎是我的想法的问题,而不是解析器的问题,这就是为什么我在这里而不是在论坛或类似的地方发帖。你们能帮我弄清楚我做错了什么吗?
看来你只需要说明名称不能以 '\n' 开头
把str ('\n ').absnt?
放在你命名规则的开头。
我正在用 Parslet 编写解析器。在我要解析的文件中,我有以下结构:
Item #1
denis calls 20
anna raises 60
denis calls 40
Item #2
another player raises 60
anna calls 60
...
为了解析动作,我做了以下操作:
- 由于我的操作数量有限但未知,所以我制定了一个
action
规则,并重复了它 - 对于每个动作,我都会解析所有内容,直到达到有效动作(即 'raises'、'calls' 等),因为玩家名称基本上可以包含任何字符。这是玩家名
- 然后我解析有效的动作,然后是space
问题是玩家名规则太贪心了,所以,解析后得到这样的响应:
{
item: '1',
players: [
{ player: 'denis', action: 'calls 20' },
{ player: 'anna', action: 'raises 60' },
{ player: 'denis', action: 'calls 40' },
{ player: '\n\nItem #2\nanother player', action: 'raises 60' },
{ player: 'anna', action: 'calls 60' },
]
}
这是我正在使用的代码:
rule :game_actions do
game_action >> space
end
rule :game_action do
in_game_action_player >> str(': ') >> in_game_action.as(:action) >> space >> game_action.as(:next).maybe
end
rule :in_game_action_player do
((str(': ') >> in_game_action).absent? >> any).repeat(1).as(:player)
end
rule :in_game_action do
fold | check | call | bet | raises
end
所以,这似乎是我的想法的问题,而不是解析器的问题,这就是为什么我在这里而不是在论坛或类似的地方发帖。你们能帮我弄清楚我做错了什么吗?
看来你只需要说明名称不能以 '\n' 开头
把str ('\n ').absnt?
放在你命名规则的开头。