I am testing the lexical analysis of a compiler. I have the file minijava.jflex inside JFLEX. I have this code inside minijava.jflex:
import java_cup.runtime.*;
%%
%public
%class Scanner
%implements sym
%unicode
%line
%column
%cup
%debug
%{
StringBuffer string = new StringBuffer();
private Symbol symbol(int type) {
return new Symbol(type, yyline, yycolumn);
}
private Symbol symbol(int type, Object value) {
return new Symbol(type, yyline, yycolumn, value);
}
%}
/* main character classes */
LineTerminator = \r|\n|\r\n
InputCharacter = [^\r\n]
WhiteSpace = {LineTerminator} | [ \t\f]
/* comments */
Comment = {TraditionalComment} | {EndOfLineComment} |
{DocumentationComment}
TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/"
EndOfLineComment = "//" {InputCharacter}* {LineTerminator}?
DocumentationComment = "/*" "*"+ [^/*] ~"*/"
/* identifiers */
Identifier = [:jletter:][:jletterdigit:]*
/* integer literals */
DecIntegerLiteral = 0 | [1-9][0-9]*
/* floating point literals */
FloatLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}?
FLit1 = [0-9]+ \. [0-9]*
FLit2 = \. [0-9]+
FLit3 = [0-9]+
Exponent = [eE] [+-]? [0-9]+
/* string and character literals */
StringCharacter = [^\r\n\"\\]
SingleCharacter = [^\r\n\'\\]
%state STRING, CHARLITERAL
%%
<YYINITIAL> {
/* keywords */
"boolean" { return symbol(BOOLEAN); }
"char" { return symbol(CHAR); }
"class" { return symbol(CLASS); }
"else" { return symbol(ELSE); }
"extends" { return symbol(EXTENDS); }
"float" { return symbol(FLOAT); }
"int" { return symbol(INT); }
"new" { return symbol(NEW); }
"if" { return symbol(IF); }
"public" { return symbol(PUBLIC); }
"super" { return symbol(SUPER); }
"return" { return symbol(RETURN); }
"void" { return symbol(VOID); }
"while" { return symbol(WHILE); }
"this" { return symbol(THIS); }
/* boolean literals */
"true" { return symbol(BOOLEAN_LITERAL, new Boolean(true)); }
"false" { return symbol(BOOLEAN_LITERAL, new Boolean(false)); }
/* null literal */
"null" { return symbol(NULL_LITERAL); }
/* separators */
"(" { return symbol(LPAREN); }
")" { return symbol(RPAREN); }
"{" { return symbol(LBRACE); }
"}" { return symbol(RBRACE); }
"[" { return symbol(LBRACK); }
"]" { return symbol(RBRACK); }
";" { return symbol(SEMICOLON); }
"," { return symbol(COMMA); }
"." { return symbol(DOT); }
/* operators */
"=" { return symbol(EQ); }
">" { return symbol(GT); }
"<" { return symbol(LT); }
"!" { return symbol(NOT); }
"?" { return symbol(QUESTION); }
":" { return symbol(COLON); }
"==" { return symbol(EQEQ); }
"<=" { return symbol(LTEQ); }
">=" { return symbol(GTEQ); }
"!=" { return symbol(NOTEQ); }
"&&" { return symbol(ANDAND); }
"&" { return symbol(AT); }
"||" { return symbol(OROR); }
"+" { return symbol(PLUS); }
"-" { return symbol(MINUS); }
"*" { return symbol(MULT); }
"/" { return symbol(DIV); }
"%" { return symbol(MOD); }
/* string literal */
\" { yybegin(STRING); string.setLength(0); }
/* character literal */
\' { yybegin(CHARLITERAL); }
/* numeric literals */
{DecIntegerLiteral} { return symbol(INTEGER_LITERAL, new Integer(yytext())); }
{FloatLiteral} { return symbol(FLOATING_POINT_LITERAL, new Float(yytext().substring(0,yylength()))); }
/* comments */
{Comment} { /* ignore */ }
/* whitespace */
{WhiteSpace} { /* ignore */ }
/* identifiers */
{Identifier} { return symbol(IDENTIFIER, yytext()); }
}
<STRING> {
\" { yybegin(YYINITIAL); return symbol(STRING_LITERAL, string.toString()); }
{StringCharacter}+ { string.append( yytext() ); }
/* escape sequences */
"\\b" { string.append( '\b' ); }
"\\t" { string.append( '\t' ); }
"\\n" { string.append( '\n' ); }
"\\f" { string.append( '\f' ); }
"\\r" { string.append( '\r' ); }
"\\\"" { string.append( '\"' ); }
"\\'" { string.append( '\'' ); }
"\\\\" { string.append( '\\' ); }
/* error cases */
\\. { throw new RuntimeException("Illegal escape sequence \""+yytext()+"\""); }
{LineTerminator} { throw new RuntimeException("Unterminated string at end of line"); }
}
<CHARLITERAL> {
{SingleCharacter}\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character(yytext().charAt(0))); }
/* escape sequences */
"\\b"\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\b'));}
"\\t"\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\t'));}
"\\n"\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\n'));}
"\\f"\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\f'));}
"\\r"\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\r'));}
"\\\""\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\"'));}
"\\'"\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\''));}
"\\\\"\' { yybegin(YYINITIAL); return symbol(CHARACTER_LITERAL, new Character('\\')); }
/* error cases */
{LineTerminator} { throw new RuntimeException("Unterminated character literal at end of line"); }
}
/* error fallback */
.|\n { return symbol(ILLEGAL_CHARACTER, yytext());}
<<EOF>> { return symbol(EOF); }
Then I go to jflex and type browse and find this file minijava.jflex. I generate the code from it and the file Scanner is created at the same directory as miniflex.java. I put this file Scanner.java and sym.java inside src folder of JFLEX. Then I write these commands:
javac Scanner.java
javac sym.java
java Scanner example.java
At the end I find this error:
Could not find or load main class Scanner
I read somewhere I should modify the file sym.java and to insert a constant for each of terminals added at minijava.jflex, but I don't know how to apply that advice.