【问题标题】:How to use Start States in ML-Lex?如何在 ML-Lex 中使用起始状态?
【发布时间】:2015-04-30 21:25:24
【问题描述】:

我正在 ML-Lex 中创建一个标记器,其定义的一部分是

datatype lexresult = STRING
                     | STRINGOP
                     | EOF
val error = fn x => TextIO.output(TextIO.stdOut,x ^ "\n")
val eof = fn () => EOF

%%
%structure myLang
digit=[0-9];
ws=[\ \t\n];
str=\"[.*]+\";
strop=\[[0-9...?\^]\];
%s alpha;
alpha=[a-zA-Z];
%%

<alpha> {alphanum}+ => (ID);
. => (error ("myLang: ignoring bad character " ^ yytext); lex());

我希望类型 ID 仅在以“alpha”开头或在“alpha”之后被发现时才被检测到。我知道把它写成

{alpha}+ {alphanum}* => (ID);

是一个选项,但我需要学习使用启动状态以及其他一些目的。有人可以帮我吗?

【问题讨论】:

    标签: tokenize sml lex ml-lex


    【解决方案1】:

    您需要的信息在the documentation which comes with SML 中,可以在各个地方找到。许多university courses have online notes which contain working examples。

    您的示例代码首先要注意的是,您重载了名称alpha,并用它来命名state 和pattern。这可能不是一个好主意。模式alphanum 未定义,结果ID 未声明。在考虑使用状态或在此处发布问题之前,您可能应该修复一些基本错误。向具有如此明显错误的代码寻求帮助并不鼓励专家提供帮助。 :-)

    修复了这些错误之后,我们就可以开始使用状态了。这是我的代码版本:

    datatype lexresult = ID
                         | EOF
    val error = fn x => TextIO.output(TextIO.stdOut,x ^ "\n")
    val eof = fn () => EOF
    
    %%
    %structure myLang
    digit=[0-9];
    ws=[\ \t\n];
    str=\"[.*]+\";
    strop=\[[0-9...?\^]\];
    %s ALPHA_STATE;
    alpha=[a-zA-Z];
    alphanum=[a-zA-Z0-9];
    %%
    
    <INITIAL>{alpha} => (YYBEGIN ALPHA_STATE; continue());
    <ALPHA_STATE>{alphanum}+ => (YYBEGIN INITIAL; TextIO.output(TextIO.stdOut,"ID\n"); ID);
    
    . => (error ("myLang: ignoring bad character " ^ yytext); lex());
    

    您可以看到我已将ID 添加到lexresult,将状态命名为ALPHA_STATE 并添加了alphanum 模式。现在让我们看看状态代码是如何工作的:

    这个程序中有两个状态,它们被称为INITIAL和ALPHA_STATE(所有的lex程序都有一个INITIAL默认状态)。它总是在INITIAL 状态下开始识别。拥有规则&lt;INITIAL&gt;{alpha} =&gt; 表示如果您在初始状态(即不在ALPHA_STATE)中遇到一个字母,那么它是匹配的并且应该调用该操作。此规则的操作如下:

    YYBEGIN ALPHA_STATE;          (* Switch from INITIAL state to ALPHA_STATE *)
    continue()                    (* and keep going *)
    

    现在我们在ALPHA_STATE,它启用了为该状态定义的规则,从而启用了规则&lt;ALPHA_STATE&gt;{alphanum} =&gt;。对该规则的操作切换回INITIAL 状态并记录匹配。

    有关使用状态(lex 而不是 ML-lex)的更长示例,您可以在此处查看我的答案:Error while parsing comments in lex。

    为了测试这个 ML-LEX 程序,我引用了这个有用的问题:building a lexical analyser using ml-lex,并生成了以下 SML 程序:

    use "states.lex.sml";
    open myLang
    val lexer =
    let 
      fun input f =
          case TextIO.inputLine f of
            SOME s => s
          | NONE => raise Fail "Implement proper error handling."
    in 
      myLang.makeLexer (fn (n:int) => input TextIO.stdIn)
    end
    val nextToken = lexer();
    

    为了完整起见,它生成了以下显示匹配的输出:

    c:\Users\Brian>"%SMLNJ_HOME%\bin\sml" main.sml
    Standard ML of New Jersey v110.78 [built: Sun Dec 21 15:52:08 2014]
    [opening main.sml]
    [opening states.lex.sml]
    [autoloading]
    [library $SMLNJ-BASIS/basis.cm is stable]
    [autoloading done]
    structure myLang :
      sig
        structure UserDeclarations : <sig>
        exception LexError
        structure Internal : <sig>
        val makeLexer : (int -> string) -> unit -> Internal.result
      end
    val it = () : unit
    hello
    ID
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-15
      • 2019-10-22
      • 2019-10-30
      • 1970-01-01
      • 2021-11-05
      • 2017-06-06
      • 2018-03-24
      • 2019-04-12
      相关资源
      最近更新 更多