Пишу компилятор. Я на первом этапе, пытаюсь все токенизировать. Я все написал, но у меня ошибка. Я читал документы (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"
Ему не нравятся мои комментарии и мои строки. Спасибо за помощь.
EDIT: Вот мой обновленный файл lex. Я точно определил, где он ломается. Я прекрасно определяю начало нового комментария, он отлично переключается в состояние COMMENT, он прекрасно обнаруживает пробел после комментария, но затем он ломается, он никогда не доходит до точки, где он съедает int.