微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何递归地对具有多字母标识符和多位整数的字符列表进行词法分析SML 中的词法分析

如何解决如何递归地对具有多字母标识符和多位整数的字符列表进行词法分析SML 中的词法分析

我正在用 SML 编写词法分析器。这是我第一次使用全功能语言工作。一般递归是直观的,但我有一个嵌套的递归函数来标识字符串标识符,该标识符通过以字母 (isAlpha) 字符开头和连续的字母和数字来标识。我遇到的问题是第一个递归函数(词法分析器)每次都在下一个字符上递归,而不是在字符串之后的第一个字符上递归。到目前为止,我已经想到了两种方法:保持计数并消耗已经添加到字符串中的字符,或者添加一个参数来跟踪最后一个字符,如果两者都是 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,(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)

解决方法

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

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

一个非常简单的例子:

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,[]);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。