1

次の形式を解析しようとしています: (identifier/)?identifier(/keyword)?、最初の識別子とオプションのキーワードを使用します。キーワードを識別子として使用することはできません。たとえば、upがキーワードの場合:

  • simple2 番目の識別子に一致し、
  • first/secondfirst最初の識別子として一致しsecond、2 番目の識別子として、
  • second/upsecond2 番目の識別子および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 で解決する方法はありますか (つまり、先読みなしで解決できますか)?

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 )?;

問題は、「最初の識別子」が「2 番目の識別子」とプレフィックスを共有しているため、保護された連結を実行しようとすると、最初のマシンがショートカットされることです。組合は、実際にあなたがやろうとしている試合を説明しています.

于 2012-10-10T19:23:01.407 に答える