Я пишу спецификацию лексера для Jflex, которая должна прочитать входной файл и вернуть токен.Я успешно завершаю эту часть, как показано ниже:
/*Super-FORTAN language lexer specification*/
%%
%public
%class LexicalAnalyser
%unicode
%line
%column
%type Symbol
%standalone
%{
private ArrayList<Symbol> tokens = new ArrayList<Symbol>();
public LexicalAnalyser() {
//ArrayList<Symbol> tokens = new ArrayList<Symbol>();
}
/**
* This method will be called as action to be taken in the rules and actions section
* of the lexer.
* @para m unit the lexical unit of the lexer
* @param value the matched input characters
* @return return an object of type symbol
*
*/
public Symbol symbol(LexicalUnit unit, Object value){
Symbol token = new Symbol(unit, yyline+1, yycolumn+1, value);
if(token != null) {
tokens.add(token); //add a token to the token list
//System.out.println("Token added && the size is: " + tokens.size()); //Checking whether a token has been successfully added
} else{
System.out.println("Failed to add token");
}
System.out.println(token); //print out the list of token to standard output
return token;
}
public ArrayList<Symbol> getTokens(){
System.out.println("In total " + tokens.size() + " tokens have been found");
return tokens;
}
public boolean isZzAtEOF() {
return zzAtEOF;
}
%}
%eofval{
return new Symbol(LexicalUnit.EOS, yyline, yycolumn);
%eofval}
/*Program Name */
ProgramName = [:uppercase:][:jletterdigit:]*[:lowercase:][:jletterdigit:]*
/*Variables names*/
VarName = [:lowercase:][a-z0-9]*
/*Carriage Return*/
EndLine = \r|\n|\r\n
/*Number*/
Number = [1-9][0-9]*
EOS = {EndLine} | [\t\f\b]
/*Input character*/
InputCharacter = [^\r|\n]
/*Comments*/
Shortcomment ="//"{InputCharacter}*{EndLine}?
Longcomment = "/*"[^'*']~"*/"
Comment = {Shortcomment}|{Longcomment}
FileMetaData ="rtf1"~"cf0 "
%state STRING, CHARLITERAL
%%
<YYINITIAL> {
/*Program Name*/
{ProgramName} {return symbol(LexicalUnit.PROGNAME, yytext());}
/* keywords */
"BEGINPROG" {return symbol(LexicalUnit.BEGINPROG, yytext());
}
"DO" {return symbol(LexicalUnit.DO, yytext());}
"ENDPROG" {return symbol(LexicalUnit.ENDPROG, yytext());}
"ENDIF" {return symbol(LexicalUnit.ENDIF, yytext());}
"ENDFOR" {return symbol(LexicalUnit.ENDFOR, yytext());}
"ENDWHILE" {return symbol(LexicalUnit.ENDWHILE, yytext());}
"ELSE" {return symbol(LexicalUnit.ELSE, yytext());}
"FOR" {return symbol(LexicalUnit.FOR, yytext());}
"IF" {return symbol(LexicalUnit.IF, yytext());}
"PRINT" {return symbol(LexicalUnit.PRINT, yytext());}
"THEN" {return symbol(LexicalUnit.THEN, yytext());}
"TO" {return symbol(LexicalUnit.TO, yytext());}
"READ" {return symbol(LexicalUnit.READ, yytext());}
"VARIABLES" {return symbol(LexicalUnit.VARIABLES, yytext());}
/*Binary operators */
"AND" {return symbol(LexicalUnit.AND, yytext());}
"OR" {return symbol(LexicalUnit.OR, yytext());}
/*operators */
"+" {return symbol(LexicalUnit.PLUS, yytext());}
"-" {return symbol(LexicalUnit.MINUS, yytext());}
"*" {return symbol(LexicalUnit.TIMES, yytext());}
"/" {return symbol(LexicalUnit.DIVIDE, yytext());}
/*Comparator */
"=" {return symbol(LexicalUnit.EQ, yytext());}
">=" {return symbol(LexicalUnit.GEQ, yytext());}
">" {return symbol(LexicalUnit.GT, yytext());}
"<=" {return symbol(LexicalUnit.LEQ, yytext());}
"<" {return symbol(LexicalUnit.LT, yytext());}
"NOT" {return symbol(LexicalUnit.NOT, yytext());}
"<>" {return symbol(LexicalUnit.NEQ, yytext());}
/* separators */
{EndLine} {return new Symbol(LexicalUnit.ENDLINE, yyline, yycolumn);}
"(" {return symbol(LexicalUnit.LPAREN, yytext());}
")" {return symbol(LexicalUnit.RPAREN, yytext());}
"," {return symbol(LexicalUnit.COMMA, yytext());}
/*Assignment */
":=" {return symbol(LexicalUnit.ASSIGN, yytext());}
/*identifiers*/
{VarName} {return symbol(LexicalUnit.VARNAME, yytext());}
/*numbers */
{Number} {return symbol(LexicalUnit.NUMBER, yytext());}
{Comment} {}
{FileMetaData} {}
}
Приведенная выше спецификация генерирует лексер, вызываемый при передаче его в качестве входных данных для Jflex.Проблема в том, что я создаю список массивов и пытаюсь добавить каждый символ в этот список, как показано ниже:
public Symbol symbol(LexicalUnit unit, Object value){
Symbol token = new Symbol(unit, yyline+1, yycolumn+1, value);
if(token != null) {
tokens.add(token); //add a token to the token list
//System.out.println("Token added && the size is: " + tokens.size()); //Checking whether a token has been successfully added
} else{
System.out.println("Failed to add token");
}
Используя оператор print в этом методе, я подтверждаю, что каждый объект успешно добавлен.Однако, когда я вызываю getTokens () из моего основного класса (как показано ниже).Я получаю пустой список:
public class Main{
/**
* Runs the scanner on input files.
*
* This is a standalone scanner, it will print any unmatched
* text to System.out unchanged.
*
* @param argv the command line, contains the filenames to run
* the scanner on.
*/
public static void main(String argv[]){
LexicalAnalyser lexer = new LexicalAnalyser();
lexer.main(argv);
System.out.println("\nIdentifiers");
ArrayList<Symbol> tokenList = lexer.getTokens(); //Retrieving the token list
System.out.println("Token added && the size is: " + tokenList.size());
for(Symbol tk: tokenList){
if(tk !=null){
if (tk.getType() == LexicalUnit.VARIABLES){
System.out.println(tk.getValue() + " " + tk.getLine() );
}
}
}
}
}
Я что-то упустил?единственный фрагмент кода, который я здесь не предоставляю, это класс объекта Symbol.Я хотел бы знать, какой момент я здесь скучаю.Большое вам спасибо.