我在写编译器。我正处于第一阶段,试图把所有的东西都标记出来。我把这一切都写好了,但我犯了个错误。我读过三、四次文档(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文件。我已经找出了它的断裂点。我很好地检测到新注释的开头,它切换到注释状态很好,它检测到注释后的空间很好,但是它会中断,它永远不会达到耗尽int的程度。
发布于 2014-04-10 04:08:57
注释由*/而不是*\终止。(<COMMENT>"*\\" =>)。当然,您需要<COMMENT>.规则来处理评论本身。
我没有看到状态<STRING>的任何词法规则;如果没有,那么这就是字符串的问题所在。否则,我想这和那些规则有关。
编辑基于编辑的问题(不是SO的最佳使用,IMHO):
我不是SML词汇方面的专家,但在我看来,您需要一条规则来处理注释和字符串的内容(正如我在上文第一段中所说)。换句话说,当遇到终止序列以外的字符时,不存在适用于状态<COMMENT>或状态<STRING>的规则(或者,如果是注释,则是空格)。
https://stackoverflow.com/questions/22978391
复制相似问题