您需要的信息在随 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());
您可以看到我已添加ID
到lexresult
、 命名状态ALPHA_STATE
并添加了alphanum
模式。现在让我们看看状态代码是如何工作的:
在这个程序中有两个状态,它们被称为INITIAL
和ALPHA_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