我正在尝试解析以下格式:(identifier/)?identifier(/keyword)?
,第一个标识符以及关键字optional。关键字不能用作标识符。例如,如果up
是关键字,则:
simple
匹配第二个标识符first/second
匹配first
作为第一个标识符,second
作为第二个标识符,second/up
匹配second
作为第二个标识符,up
作为关键字。在Ruby中使用Ragel,我定义了以下FSM:
%%{
machine simple;
keyword = "up";
separator = '/';
ident_char = any - separator;
identifier = ident_char+ - keyword;
action start_string { $start_string = p }
action first_string { puts "First: #{get_string(data, p)}" }
action second_string { puts "Second: #{get_string(data, p)}" }
action keyword_string { puts "Keyword: #{get_string(data, p)}" }
main := ( identifier >start_string %first_string separator )?
:> identifier >start_string %second_string
( separator keyword >start_string %keyword_string )?
;
}%%
%% write data;
def get_string(data, p)
data[$start_string...p].pack("c*")
end
def parse(data)
data = data.unpack("c*")
eof = pe = data.length
%% write init;
%% write exec;
end
parse("first/second")
puts("---")
parse("second/up")
这给出了以下输出:
$ ragel -R simple.rl ; ruby simple.rb
Second: first
---
Second: second
Keyword: up
这是不正确的,因为第一部分应该是First: first
Second: second
,但由于我已经给出了:>
优先级而预期。
我尝试了不同的优先级组合,但未能获得预期的结果。有没有办法用Ragel解决这个问题(也就是说这可以不用前瞻来解决)?
答案 0 :(得分:0)
尝试将此作为主机:
two_idents = identifier >start_first %first_string . separator . (identifier >start_second %second_string);
main := (two_idents | identifier >start_first %first_string) . ( separator . keyword )?;
问题是“第一个标识符”与“第二个标识符”共享一个前缀,因此尝试进行保护级联快捷方式是第一台机器。联盟实际上描述了你想要做的比赛。