I have to make a compiler for a subset of C and I decided to use JFlex and Cup. However, when I create my .jflex
file, it compiles fine with JFlex, but the output (.java file) will not compile.
Directory:
src:
Lexer.java
makefile
jflex.jar
cup.jar
tinyc.jflex
So the command I execute are the follwing:
jflex tinyc.jflex
javac -cp ".:cup.jar:jflex.jar" Lexer.java
I keep getting the following errors:
Lexer.java:640: error: cannot find symbol
{ return new symbol(sym.NOT);
^
symbol: class symbol
location: class Lexer
Lexer.java:640: error: cannot find symbol
{ return new symbol(sym.NOT);
^
symbol: variable sym
location: class Lexer
Basicly it doesn't know the sym
class, I suppose. I'm trying to get a basic version working by following examples but I just don't manage. Any pointers?
Edit:
I typed the example from the JFlex manual and tried to compile that one but it's giving me the same errors as well. So I must be doing something wrong. Any pointers?
tinyc.jflex:
import java_cup.runtime.*;
import java.io.FileInputStream;
import java.io.InputStream;
%%
%class Lexer
%cup
%line
%column
%unicode
%{
StringBuffer string = new StringBuffer();
private Symbol symbol(int type) {
return new Symbol(type, yyline, yycolumn);
}
private Symbol symbol(int type, Object val) {
return new Symbol(type, yyline, yycolumn, val);
}
%}
digit = [0-9]
alpha = [a-zA-Z_]
alphanum = [A-Za-z0-9]
symbol = [_]
identifier = {alpha}+({alphanum}|{symbol})*
sl_comment = "//".*
ml_comment = "/*"((.*?)|[\n]*)*"*/"
commment = {sl_comment} | {ml_comment}
%%
"int" { return new symbol(sym.INTEGER);}
"char" { return new symbol(sym.CHAR);}
"return" { return new symbol(sym.RETURN);}
"if" { return new symbol(sym.IF); }
"else" { return new symbol(sym.ELSE); }
"while" { return new symbol(sym.WHILE); }
"do" { return new symbol(sym.DO); }
"length" { return new symbol(sym.LENGTH); }
"write" { return new symbol(sym.WRITE); }
"read" { return new symbol(sym.READ); }
"," { return new symbol(sym.COMMA); }
";" { return new symbol(sym.SEMICOLON); }
"+" { return new symbol(sym.ADD); }
"-" { return new symbol(sym.MIN); }
"*" { return new symbol(sym.MUL); }
"/" { return new symbol(sym.DIV); }
"(" { return new symbol(sym.LPAR); }
")" { return new symbol(sym.RPAR); }
"[" { return new symbol(sym.LRBACK); }
"]" { return new symbol(sym.RBACK); }
"{" { return new symbol(sym.LBRACE); }
"}" { return new symbol(sym.RBRACE); }
">" { return new symbol(sym.GREATER); }
"<" { return new symbol(sym.LESS); }
"!=" { return new symbol(sym.NEQ); }
"==" { return new symbol(sym.EQU); }
"!" { return new symbol(sym.NOT); }
"=" { return new symbol(sym.ASSIGN); }
{identifier} { return new symbol(sym.NAME, yytext()); }
{digit}+ { return new symbol(sym.NUMBER, new Integer(Integer.parseInt(yytext()))); }
{commment} { yyline += countLines(yytext()); }
[\n] { ++yyline; }
[\r\t\f\ ]+ { }
. { System.err.println("unexpected char " + yytext() + " !\n"); System.exit(0); }
The sym
class is generally generated by CUP, not by JFlex. The symbols in the generated class are based off all of the terminals you define in your .cup file. To be able to use the sym
class, you'll either have to make the .cup file with all of the appropriate symbols, or just make the class manually for the time being.