Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion 如何使用多字母标识符和多位数整数递归地lex字符列表(SML中的lexing)_Recursion_Functional Programming_Nested_Sml_Lexer - Fatal编程技术网

Recursion 如何使用多字母标识符和多位数整数递归地lex字符列表(SML中的lexing)

Recursion 如何使用多字母标识符和多位数整数递归地lex字符列表(SML中的lexing),recursion,functional-programming,nested,sml,lexer,Recursion,Functional Programming,Nested,Sml,Lexer,我正在用SML编写一个lexer。这是我第一次使用全函数语言。一般的递归是直观的,但我有一个嵌套的递归函数来标识字符串标识符,它是通过以字母(isAlpha)字符和consequentive字母和数字开头来标识的。我遇到的问题是,第一个递归函数(lexer)每次都在下一个字符上递归,而不是在字符串后面的第一个字符上递归。到目前为止,我已经想到了两种方法:保持计数并使用已经添加到字符串中的字符,或者添加另一个参数来跟踪最后一个字符,如果这两个字符都是alpha,则以某种方式跟踪它们。这些措施显然既

我正在用SML编写一个lexer。这是我第一次使用全函数语言。一般的递归是直观的,但我有一个嵌套的递归函数来标识字符串标识符,它是通过以字母(isAlpha)字符和consequentive字母和数字开头来标识的。我遇到的问题是,第一个递归函数(lexer)每次都在下一个字符上递归,而不是在字符串后面的第一个字符上递归。到目前为止,我已经想到了两种方法:保持计数并使用已经添加到字符串中的字符,或者添加另一个参数来跟踪最后一个字符,如果这两个字符都是alpha,则以某种方式跟踪它们。这些措施显然既没有效率,也不是实现这一目标的正确方法。这让我发疯,我无法概念化或形象化解决方案。任何帮助都将不胜感激

exception LexerError;

datatype sign =
    Plus
  | Minus
;

datatype atom =
  T
| NIL
| Int of int
| Ident of string
;

datatype token =
  Lparen
| Rparen
| Dot
| Sign of sign
| Atom of atom
;


(* implement lexid *)

fun lexid (x::xs) = if Char.isAlpha(x) orelse Char.isDigit(x) then (String.str x) ^ lexid(xs)
                    else ""
  | lexid [] = ""
;




(* implement lexint NOT COMPLETED*)

fun lexint x = valOf(Int.fromString(String.str x))
;


(* complete implementation of lexer *)
fun  lexer (#"." :: t)  = Dot :: lexer(t)
 |   lexer (#"(" :: t) = Lparen :: lexer(t)
 |   lexer (#")" :: t) = Rparen :: lexer(t)
 |   lexer (#"p" :: #"l" ::  #"u" ::  #"s" :: t) = Sign(Plus) :: lexer(t)
 |   lexer (#"m" :: #"i" :: #"n" ::  #"u" ::  #"s" :: t) = Sign(Minus) :: lexer(t)
 |   lexer (#"T" :: t) = Atom(T) :: lexer(t)
 |   lexer (#"N" :: #"I" :: #"L" :: t) = Atom(NIL) :: lexer(t)
 |   lexer (#" " :: t) = lexer(t)
 |   lexer (#"\n" :: t) = lexer(t)
 |   lexer (#"\t" :: t) = lexer(t)
 |   lexer (#"\r" :: t) = lexer(t)
 |   lexer (h :: t) =
        if Char.isAlpha(h) then Atom(Ident((lexid (h::t)))) :: lexer(t)
        else if Char.isDigit(h) then Atom(Int((lexint h))) :: lexer(t)
        else Atom(Ident("test")) :: lexer(t)
 |   lexer [] = []
;

fun print_tokens [] = print("\n")
  | print_tokens (Lparen :: t) = (print("Lparen "); print_tokens(t))
  | print_tokens (Rparen :: t) = (print("Rparen "); print_tokens(t))
  | print_tokens (Dot :: t) = (print("Dot "); print_tokens(t))
  | print_tokens (Sign(Plus) :: t) = (print("Plus "); print_tokens(t))
  | print_tokens (Sign(Minus) :: t) = (print("Minus "); print_tokens(t))
  | print_tokens (Atom(a) :: t) =
  (case a of
   T => (print("Atom(T) "); print_tokens(t))
   | NIL => (print("Atom(NIL) "); print_tokens(t))
   | Int i => (print("Atom(Int(" ^ Int.toString(i) ^ ")) "); print_tokens(t))
   | Ident s => (print("Atom(Ident(" ^ s ^ ")) "); print_tokens(t)))
  ;


fun reader(copt: char option, is, l) =
  case copt of
    NONE    => (TextIO.closeIn is; l)
  | SOME(c) => reader (TextIO.input1 is, is, (l@[c]))
  ;

val args = CommandLine.arguments();
val ins = TextIO.openIn(hd(args));

print_tokens(lexer(reader(TextIO.input1 ins, ins, [])));

val _ = OS.Process.exit(OS.Process.success)

常见的解决方案是使用一个函数,该函数使用单个令牌并返回一对
(令牌,剩余)
,其中
剩余
是提取令牌之后的输入

然后可以在递归词法分析器中使用它

一个非常简单的例子:

fun lexer [] = []
  | lexer ts = let (t, rest) = token ts
               in
                   t :: lexer rest
               end;

fun  token (#"." :: t)  = (Dot, t)
 |   token (#"(" :: t) = (Lparen, t)
 |   token (#")" :: t) = (Rparen, t)
 |   token (#"p" :: #"l" ::  #"u" ::  #"s" :: t) = (Sign Plus, t)
  ...
 |   token (#" " :: t) = token t
 |   token (#"\n" :: t) = token t
 |   token (#"\t" :: t) = token t
 |   token (#"\r" :: t) = token t
 |   token (h :: t) =
     if Char.isAlpha h then lex_identifier (h::t)
     else if Char.isDigit h then lex_integer (h::t)
     else (Ident("test"), t)
 |   token [] = (Error, []);

请注意,我在孟菲斯上大学,由于缺水和极端的南方风暴,我们已经一个星期没有上课了,所以我非常渴望学习这些材料,非常担心我的班级落后。