1

我正在尝试解析以下格式:(identifier/)?identifier(/keyword)?,带有第一个标识符以及可选的关键字。关键字不能用作标识符。例如,如果up是关键字,则:

  • simple匹配第二个标识符,
  • first/second匹配first作为第一个标识符,second作为第二个标识符,
  • second/upsecond作为第二个标识符和up关键字匹配。

Ragel与 Ruby 结合使用,我定义了以下 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 解决这个问题(即,这可以在没有前瞻的情况下解决)?

4

1 回答 1

0

试试这个作为你的主机:

two_idents = identifier >start_first %first_string . separator . (identifier >start_second %second_string);                             

main := (two_idents | identifier >start_first %first_string) . ( separator . keyword )?;

问题是“第一个标识符”与“第二个标识符”共享一个前缀,所以尝试做一个受保护的连接会捷径第一台机器。工会实际上描述了您要进行的比赛。

于 2012-10-10T19:23:01.407 回答