试图理解标准ML(ml-lex)的Lex语法

时间:2014-04-10 04:00:10

标签: compiler-construction token sml lex smlnj

我正在编写一个编译器。我正处于第一阶段,试图将一切都标记出来。我把它全部写完了,但是我收到了一个错误。我已经阅读了三次或四次文档(smlnj),并且错误信息量不大。

我认为我必须弄乱程序的状态更改方面,它对于刚创建令牌的事情很好,但是当我使用YYBEGIN更改为状态时,它会爆炸。

这是我的lex文件:

type pos = int;
type lexresult = Tokens.token;

val lineNum = ErrorMsg.lineNum;
val linePos = ErrorMsg.linePos;
val commentDepth = ref 0;

fun incCom(cmDepth) = cmDepth := !cmDepth + 1;
fun decCom(cmDepth) = cmDepth := !cmDepth - 1;

fun err(p1,p2) = ErrorMsg.error p1;

fun eof() = let val pos = hd(!linePos) in Tokens.EOF(pos,pos) end;



%% 
digits=[0-9]+;

%s COMMENT STRING;

%%

<INITIAL,COMMENT>\n         => (lineNum := !lineNum+1; linePos := yypos :: !linePos; continue());
<INITIAL>"type"             => (Tokens.TYPE(yypos, yypos+4));
<INITIAL>"var"              => (Tokens.VAR(yypos,yypos+3));
<INITIAL>"function"         => (Tokens.FUNCTION(yypos, yypos+8));
<INITIAL>"break"            => (Tokens.BREAK(yypos, yypos+5));
<INITIAL>"of"               => (Tokens.OF(yypos, yypos+2));
<INITIAL>"end"              => (Tokens.END(yypos, yypos+3));
<INITIAL>"in"               => (Tokens.IN(yypos, yypos+2));
<INITIAL>"nil"              => (Tokens.NIL(yypos, yypos+3));
<INITIAL>"let"              => (Tokens.LET(yypos, yypos+3));
<INITIAL>"do"               => (Tokens.DO(yypos, yypos+2));
<INITIAL>"to"               => (Tokens.TO(yypos, yypos+2));
<INITIAL>"for"              => (Tokens.FOR(yypos, yypos+3));
<INITIAL>"while"            => (Tokens.WHILE(yypos, yypos+5));
<INITIAL>"else"             => (Tokens.ELSE(yypos, yypos+4));
<INITIAL>"then"             => (Tokens.THEN(yypos, yypos+4));
<INITIAL>"if"               => (Tokens.IF(yypos, yypos+2));
<INITIAL>"array"            => (Tokens.ARRAY(yypos, yypos+5));
<INITIAL>":="               => (Tokens.ASSIGN(yypos, yypos+2));
<INITIAL>"|"                => (Tokens.OR(yypos, yypos+1));
<INITIAL>"&"                => (Tokens.AND(yypos, yypos+1));
<INITIAL>">="               => (Tokens.GE(yypos, yypos+2));
<INITIAL>">"                => (Tokens.GT(yypos, yypos+1));
<INITIAL>"<="               => (Tokens.LE(yypos, yypos+2));
<INITIAL>"<"                => (Tokens.LT(yypos, yypos+1));
<INITIAL>"<>"               => (Tokens.NEQ(yypos, yypos+2));
<INITIAL>"="                => (Tokens.EQ(yypos, yypos+1));
<INITIAL>"/"                => (Tokens.DIVIDE(yypos, yypos+1));
<INITIAL>"*"                => (Tokens.TIMES(yypos, yypos+1));
<INITIAL>"-"                => (Tokens.MINUS(yypos, yypos+1));
<INITIAL>"+"                => (Tokens.PLUS(yypos, yypos+1));
<INITIAL>"."                => (Tokens.DOT(yypos, yypos+1));
<INITIAL>"}"                => (Tokens.RBRACE(yypos, yypos+1));
<INITIAL>"{"                => (Tokens.LBRACE(yypos, yypos+1));
<INITIAL>"]"                => (Tokens.RBRACK(yypos, yypos+1));
<INITIAL>"["                => (Tokens.LBRACK(yypos, yypos+1));
<INITIAL>")"                => (Tokens.RPAREN(yypos, yypos+1));
<INITIAL>"("                => (Tokens.LPAREN(yypos, yypos+1));
<INITIAL>";"                => (Tokens.SEMICOLON(yypos, yypos+1));
<INITIAL>":"                => (Tokens.COLON(yypos, yypos+1));
<INITIAL>","                => (Tokens.COMMA(yypos,yypos+1));


<INITIAL>{digits}           => (Tokens.INT(valOf(Int.fromString(yytext)), yypos, yypos + (size yytext)));
<INITIAL>[a-z][a-z0-9_]*    => (Tokens.ID(yytext, yypos, yypos + (size yytext)));
<INITIAL>(").*(")           => (Tokens.STRING(yytext, yypos, yypos + (size yytext)));
<INITIAL>"\""               => (YYBEGIN STRING; continue());
<STRING>"\""                => (YYBEGIN INITIAL; continue());

<INITIAL>"/*"       => (incCom commentDepth; YYBEGIN COMMENT; continue());
<COMMENT>"/*"       => (incCom commentDepth; continue());
<COMMENT>"*/"       => (print "OTHER TRACE!\n"; decCom commentDepth; if !commentDepth <= 0 then YYBEGIN INITIAL else (); continue());

<INITIAL,COMMENT>[\ \t]+    => (print "TRACE 22222\n"; continue());
<INITIAL>.                  => (ErrorMsg.error yypos ("illegal character " ^ yytext); continue());

这是我正在标记的源文件:

var , 123
/* some comment */
234 "d"

它不喜欢我的评论,也不喜欢我的字符串。谢谢你的帮助。

编辑:所以这是我更新的lex文件。我已经确定了它破裂的地方。我检测到新评论的开始就好了,它很好地切换到COMMENT状态,它在评论之后检测到空间就好了,但随后它中断了,它永远不会达到它吃掉int的程度。

1 个答案:

答案 0 :(得分:2)

评论由*/而不是*\终止。 (<COMMENT>"*\\" =>)。当然,您需要<COMMENT>.规则来处理评论本身。

我没有看到状态<STRING>的任何词汇规则;如果没有,那将是字符串的问题。否则,我认为这与这些规则有关。

根据编辑过的问题进行编辑(不是最好用的SO,恕我直言):

我不是SML lexing的专家,但在我看来,你需要一个规则来处理评论和字符串的内容(正如我在第一段中所述) 。换句话说,当遇到终止序列以外的字符时(或者,如果是注释,则为空格),没有适用于状态<COMMENT>或状态<STRING>的规则。