1

我正在 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);

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

4

1 回答 1

0

您需要的信息在随 SML 一起提供的文档中,可在各个地方找到。许多大学课程都有在线笔记,其中包含工作示例

从您的示例代码中首先要注意的是,您已经重载了名称alpha并使用它来命名状态模式。这可能不是一个好主意。模式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());

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

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

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

现在我们在ALPHA_STATE其中启用了为该状态定义的那些规则,这些规则启用了规则<ALPHA_STATE>{alphanum} =>。此规则上的操作切换回INITIAL状态并记录匹配。

有关使用状态(lex 而不是 ML-lex)的更长示例,您可以在此处查看我的答案:在 lex 中解析注释时出错

为了测试这个 ML-LEX 程序,我参考了这个有用的问题:使用 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
于 2015-04-30T11:01:23.440 回答