您的位置:首页 > 其它

编译器开发-----词法分析器

2009-06-16 01:59 218 查看
编译器开发——词法分析器
这周本应进入语法分析器设计的,但因上周种种原因没能完成词法分析器的构造,所以推到了今天才完成。下面详细介绍该词法分析器的构造思路:
引子:词法分析的主要作用是根据语言的词法规则对输入的源程序字符流进行分析,识别出一个个单词,再将各单词对应的词法记号依次提供给语法分析器,这些记号作为语言语法中的终结符。
因考虑到为MiniJOOL语言构造词法分析器的工作量比较大,所以自己理解了词法分析器构造的原理后,就使用Jflex为该语言构造词法分析器。使用该工具主要工作是编写Jflex词法规范描述文件即.flex文件,然后通过Jflex工具生成scanner.java词法分析器。实验中整个过程通过scanner.xml编译文件控制完成Jflex生成、编译、连接、运行词法分析器的过程。
具体步骤:
二、编写一个Symbol.java文件,其中包含词法记号定义的文件,生成的词法分析器sample.java要用到这个词法记号类。

public class Symbol {
/** 词法记号类别的个数 */
public static int counter = 0;
/** 需要忽略的字符 */
public static final int IGNORE = counter++;
/** 整数常量*/
public static final int INTEGER_LITERAL = counter++;
/** 标识符 */
public static final int IDENTIFIER = counter++;
public static final int CLASS = counter++;
public static final int STATIC = counter++;
public static final int MAIN = counter++;

/** 文件结尾符 */
public static final int EOF = counter++;
/** true 或 false */
public static final int BOOLEAN_LITERAL = counter++;
/** /r|/n|/r/n */
public static final int LINETERMINATOR = counter++;

/** final */
public static final int FINAL = counter++;
/** extends */
public static final int EXTENDS = counter++;
/** void */
public static final int VOID = counter++;
/** int */
public static final int INT = counter++;
/** boolean */
public static final int BOOLEAN = counter++;
/** String */
public static final int STRING = counter++;
/** if */
public static final int IF = counter++;
/** else */
public static final int ELSE = counter++;
/** while */
public static final int WHILE = counter++;
/** break */
public static final int BREAK = counter++;
/** continue */
public static final int CONTINUE = counter++;
/** return */
public static final int RETURN = counter++;
/** print */
public static final int PRINT = counter++;
/** read */
public static final int READ = counter++;
/** this */
public static final int THIS = counter++;
/** super */
public static final int SUPER = counter++;
/** new */
public static final int NEW = counter++;
/** delete */
public static final int DELETE = counter++;
/** instanceof */
public static final int INSTANCEOF = counter++;
/** "null" */
public static final int NULL_LITERAL = counter++;

/** + */
public static final int PLUS = counter++;
/** - */
public static final int MINUS = counter++;
/** <code>*</code> */
public static final int MULT = counter++;
/** / */
public static final int DIV = counter++;
/** ( */
public static final int LPAREN = counter++;
/** ) */
public static final int RPAREN = counter++;
/** = */
public static final int EQ = counter++;
/** ; */
public static final int SEMICOLON = counter++;
/** { */
public static final int LBRACE = counter++;
/** } */
public static final int RBRACE = counter++;
/** [ */
public static final int LBRACK = counter++;
/** ] */
public static final int RBRACK = counter++;
/** , */
public static final int COMMA = counter++;
/** . */
public static final int DOT = counter++;
/** ! */
public static final int NOT = counter++;
/** % */
public static final int MOD = counter++;
/** < */
public static final int LT = counter++;
/** > */
public static final int GT = counter++;
/** <= */
public static final int LTEQ = counter++;
/** >= */
public static final int GTEQ = counter++;
/** == */
public static final int EQEQ = counter++;
/** != */
public static final int NOTEQ = counter++;
/** && */
public static final int ANDAND = counter++;
/** || */
public static final int OROR = counter++;
/** *= */
public static final int MULTEQ = counter++;
/** /= */
public static final int DIVEQ = counter++;
/** %= */
public static final int MODEQ = counter++;
/** += */
public static final int PLUSEQ = counter++;
/** -= */
public static final int MINUSEQ = counter++;
/** ~ */
public static final int TILDE = counter++;

/** 双引号包含的字符序列 */
public static final int STRING_LITERAL = counter++;

//请在以下的空当加入新的词法记号:

/** 词法记号的类型,即类别编码 */
private int type;
/** 词法记号的串值,即单词文本 */
private String token;
/** 词法记号在源文件中的行号 */
private int line;
/** 词法记号在源文件中的列号 */
private int column;

/**
* 词法记号的构造器,给出类型、串值、所在行号和列号,产生一个相应的Symbol对象。
* @param type 词法记号的类型,如{@link #PLUS}, {@link #MINUS}等等。
* @param token 词法记号的串值
* @param line 词法记号所在的行号,用于调试和检查输出。
* @param column 词法记号所在的列号,用于调试和检查输出。
*/
public Symbol(int type, String token, int line, int column) {
this.type = type;
this.token = token;
this.line = line;
this.column = column;
}

/**
* 词法记号的复制构造器,它复制出一个与输入词法记号完全一样的Symbol对象。
* @param sym 待复制的Symbol对象。
*/
public Symbol(Symbol sym) {
this.type = sym.type;
this.token = sym.token;
this.line = sym.line;
this.column = sym.column;
}

/**
* 返回当前词法记号的类型。
* @return 这个符号的类型
*/
public int getType() {
return type;
}

/**
* 输出当前词法记号的信息,包括类型、串值、行号和列号。
* @return 字符串表示的词法记号信息
*/
public String toString() {
return type + " " + token + " (" + line + ", " + column + ")";
}

/**
* 返回当前词法记号对应的串值,即单词文本
* @return 符号的单词文本
*/
public String getLexeme(){
return token;
}
}
二、编写词法规范描述文件sample.flex.
%%
%line //把行列计数打开
%column
%public //生成的类为public访问权限
%class SampleLexer //指定生成词法分析器的类名
%type Symbol //词法记号类

%eofval{
return symbol(Symbol.EOF); //这段代码是在分析器遇到文件末尾时候执行的。
%eofval}

%{
public static void main(String argv[]) {
if (argv.length != 1) {
System.out.println ("Usage: java SampleLexer inputfile");
}
else {
SampleLexer l =null;
try {
l = new SampleLexer(new java.io.FileReader(argv[0]));
Symbol s = l.yylex();
while (s.getType() != Symbol.EOF) {
System.out.println(s);
s = l.yylex();
}
} catch (Exception e) {
System.out.println("Unexpected exception:"); //此段代码将被直接复制到生成的词法分析器类中
e.printStackTrace();
}
}
}

private Symbol symbol(int type) {
return new Symbol(type, yytext(), yyline, yycolumn);
}
%}

%%
<YYINITIAL> "void" { return symbol(Symbol.VOID); }
<YYINITIAL> "main" { return symbol(Symbol.MAIN); }
<YYINITIAL> "final" { return symbol(Symbol.FINAL); }
<YYINITIAL> "static" { return symbol(Symbol.STATIC); }
<YYINITIAL> "final" { return symbol(Symbol.FINAL); }
<YYINITIAL> "class" { return symbol(Symbol.CLASS); }
<YYINITIAL> "extends" { return symbol(Symbol.EXTENDS); }
<YYINITIAL> "int" { return symbol(Symbol.INT); }
<YYINITIAL> "boolean" { return symbol(Symbol.BOOLEAN); }
<YYINITIAL> "String" { return symbol(Symbol.STRING); }
<YYINITIAL> "if" { return symbol(Symbol.IF); }
<YYINITIAL> "else" { return symbol(Symbol.ELSE); }
<YYINITIAL> "while" { return symbol(Symbol.WHILE); }
<YYINITIAL> "continue" { return symbol(Symbol.CONTINUE); }
<YYINITIAL> "break" { return symbol(Symbol.BREAK); }
<YYINITIAL> "return" { return symbol(Symbol.RETURN); }
<YYINITIAL> "print" { return symbol(Symbol.PRINT); }
<YYINITIAL> "read" { return symbol(Symbol.READ); }
<YYINITIAL> "this" { return symbol(Symbol.THIS); }
<YYINITIAL> "super" { return symbol(Symbol.SUPER); }
<YYINITIAL> "new" { return symbol(Symbol.NEW); }
<YYINITIAL> "delete" { return symbol(Symbol.DELETE); }
<YYINITIAL> "instanceof" { return symbol(Symbol.INSTANCEOF); }

"+" { return symbol(Symbol.PLUS); }
"-" { return symbol(Symbol.MINUS); }
"(" { return symbol(Symbol.LPAREN); }
")" { return symbol(Symbol.RPAREN); }
"=" { return symbol(Symbol.EQ); }
";" { return symbol(Symbol.SEMICOLON); }
"{" { return symbol(Symbol.LBRACE); }
"}" { return symbol(Symbol.RBRACE); }
"[" { return symbol(Symbol.LBRACK); }
"]" { return symbol(Symbol.RBRACK); }
"," { return symbol(Symbol.COMMA); }
"." { return symbol(Symbol.DOT); }
"!" { return symbol(Symbol.NOT); }
"%" { return symbol(Symbol.MOD); }
"<" { return symbol(Symbol.LT); }
">" { return symbol(Symbol.GT); }
"<=" { return symbol(Symbol.LTEQ); }
"==" { return symbol(Symbol.EQEQ); }
"!=" { return symbol(Symbol.NOTEQ); }
"&&" { return symbol(Symbol.ANDAND); }
"||" { return symbol(Symbol.OROR); }
"*=" { return symbol(Symbol.MULTEQ); }
"/=" { return symbol(Symbol.DIVEQ); }
"%=" { return symbol(Symbol.MODEQ); }
"+=" { return symbol(Symbol.PLUSEQ); }
"-=" { return symbol(Symbol.MINUSEQ); }
"~" { return symbol(Symbol.TILDE); }

"//" [^/r/n]* /r|/n|/r/n { }
"/*" [^*] ~"*/" | "/*" "*"+ "/" { }
0|[1-9][0-9]* { return symbol(Symbol.INTEGER_LITERAL); }
[:jletter:][:jletterdigit:]* { return symbol(Symbol.IDENTIFIER); }

三、对sample.flex运行Jflex,产生词法分析器的JAVA源代码,接着编译这个词法分析器,再运行这个词法分析器进行测试。

感想:由于第一次用自动生成工具,加上死死的盯着实验指导书,花了很多时间也还是没看明白词法规范文件中的词法规则。网上搜了N多,也还是没找到太多关于Jflex的介绍,没办法,自己一气之下,到了官网下了份手册,英文的。看了会就豁然开朗了,嗨~早知道,就不屑网上那些浅显的介绍了。记得上两周做解释器遇到问题也是看英文文档才解决的,这次经历更让我认识到英语的重要性和计算机专业的特殊性。或许查阅英文文献慢慢就会变成我的一种习惯~~~~~从明天起,开始语法分析器设计,加油!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: