【问题标题】:Ragel, final states, and EOFRagel、最终状态和 EOF
【发布时间】:2013-07-25 04:20:40
【问题描述】:

我不明白 Ragel 认为什么是“最终”状态。 IIRC 用户指南说,在机器简化之前是最终状态的状态在之后仍然是最终状态。 什么时候是最终状态,如何识别?


应用:

我正在使用状态机语法来实现一个字符串查找器——查找长度大于 n 的 ASCII 字符串,并打印它们。这意味着实现最大长度匹配器,如下所示。

尽管点输出没有显示最终状态,但 EOF 转换的行为会有所不同,具体取决于使用的 {$%@}eof 的风格。我不明白为什么会这样。例如,在下面的 has_string 状态中,使用 %eof 而不是 @eof 会导致从终止匹配状态的生成/合成状态之一调用 commit_nonstring_eofcommit_string_eof 操作。

这是一个工作状态机。请注意,最右侧的节点退出操作只有一个操作:commit_nonstring_eof

这是一个损坏的状态机。请注意,最右侧的节点退出操作同时调用 commit_string_eofcommit_nonstring_eof

action commit_string { }
action commit_string_eof { }
action commit_nonstring_eof { }
action set_mark { }

action reset {
   /* Force the machine back into state 1. This happens after
    * an incomplete match when some graphical characters are
    * consumed, but not enough for use to keep the string. */
    fgoto start;
 }

 # Matching classes union to 0x00 .. 0xFF
 graphic = (0x09 | 0x20 .. 0x7E);
 non_graphic =  (0x00 .. 0x08 | 0x0A .. 0x1F | 0x7F .. 0xFF);

 collector = (

 start: (
     # Set the mark if we have a graphic character,
     # otherwise go to non_graphic state and consume input
     graphic @set_mark -> has_glyph |
     non_graphic -> no_glyph
 ) $eof(commit_nonstring_eof),

 no_glyph: (
     # Consume input until a graphic character is encountered
     non_graphic -> no_glyph |
     graphic @set_mark -> has_glyph
 ) $eof(commit_nonstring_eof),

 has_glyph: (
      # We already matched one graphic character to get here
      # from start or no_glyph. Try to match N-1 before allowing
      # the string to be committed. If we don't get to N-1,
      # drop back to the start state
      graphic{3} $lerr(reset) -> has_string
  ) @eof(commit_nonstring_eof),

  has_string: (
      # Already consumed our quota of N graphic characters;
      # consume input until we run out of graphic characters
      # then reset the machine. All exiting edges should commit
      # the string. We differentiate between exiting on a non-graphic
      # input that shouldn't be added to the string and exiting
      # on a (graphic) EOF that should be added.
      graphic* non_graphic -> start
  ) %from(commit_string) @eof(commit_string_eof) // okay
 #) %from(commit_string) %eof(commit_string_eof) // bad

); #$debug;

main := (collector)+;

【问题讨论】:

    标签: state-machine ragel


    【解决方案1】:

    认为对于连接的机器a.b,当从a 转换到b 的第一个字符时,a 出现最终状态。 (参见手册中的“Regular Language Operators / Concatenation”)。

    尽管点输出没有显示最终状态

    点输出显示了许多最终状态。例如,从 7 到 6 的过渡使 7 成为最终的。从 6 到 1 的过渡使 6 成为最终的,依此类推。

    【讨论】:

    • 通常,点输出显示最终状态的双圆圈。我想缺乏这一点让我感到困惑。
    • 关于点输出,Ragel 的手册不是很有帮助。我以前见过的所有像这样的图表,双圆圈表示最终状态。上图中箭头末端的小圆圈和点到底是什么意思?就此而言,在我的图表中,许多箭头标记为“0 / do_date,69:6”。我知道 0 表示转换没有消耗输入字符,并且 do_date 是我分配的操作。但是“69:6”是什么意思?
    • 69:6 是字符代码。您必须将 -p 选项传递给 ragel 才能看到字符。小圆圈和圆点大概是出口,但如果没有一个我更熟悉的例子,我不能肯定地说。
    • 其实,从阅读Ragel源码(手册真的需要工作),69:6表示.rl文件中确定转换动作的行和列, 对于没有名称的操作(例如 %{fhold})。这些小点在源代码中被称为伪状态,包括图表的条目、带有 EOF 操作的最终状态以及默认操作出错的状态。双圈确实标记了整个机器的最终状态。在示例a.ba 的最终状态通常在连接期间不再是最终状态。
    • 更正:小点在源中被称为伪状态,包括图形的条目和带有 EOF 动作的最终状态。小圆圈是默认操作出错的状态的伪状态。
    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 2013-12-24
    • 1970-01-01
    相关资源
    最近更新 更多