词法分析器
定义:
词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位,包括关键字、标识符、运算符、界符和常量等
(1) 关键字 是由程序语言定义的具有固定意义的标识符。例如,Pascal 中的begin,end,if,while都是保留字。这些字通常不用作一般标识符。
(2) 标识符 用来表示各种名字,如变量名,数组名,过程名等等。
(3) 常数 常数的类型一般有整型、实型、布尔型、文字型等。
(4) 运算符 如+、-、*、/等等。
(5) 界符 如逗号、分号、括号、等等。
输出:
词法分析器所输出单词符号常常表示成如下的二元式:
(单词种别,单词符号的属性值)
单词种别通常用整数编码。标识符一般统归为一种。常数则宜按类型(整、实、布尔等)分种。关键字可将其全体视为一种。运算符可采用一符一种的方法。界符一般用一符一种的方法。对于每个单词符号,除了给出了种别编码之外,还应给出有关单词符号的属性信息。单词符号的属性是指单词符号的特性或特征。
示例:
比如如下的代码段:
while(i>=j) i--
经词法分析器处理后,它将被转为如下的单词符号序列:
<while, _>
<(, _>
<id, 指向i的符号表项的指针>
<>=, _>
<id, 指向j的符号表项的指针>
<), _>
<id, 指向i的符号表项的指针>
<--, _>
<;, _>
词法分析分析器作为一个独立子程序
词法分析是编译过程中的一个阶段,在语法分析前进行。词法分析作为一遍,可以简化设计,改进编译效率,增加编译系统的可移植性。也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
正规表达式与正规集
正规表达式是说明单词的一种重要的表示法(记号),是定义正规集的工具。在词法分析中,正规表达式用来描述标示符可能具有的形式。
定义(正规式和它所表示的正规集):
设字母表为S,
1. e和Ø都是S上的正规式,它们所表示的正规集分别为{e}和{ };
2. 任何aÎ S,a是S上的一个正规式,它所表示的正规集为{a};
3. 假定U和V都是S上的正规式,它们所表示的正规集分别为L(U)和L(V),那么,(U), U|V, U·V, U*也都是正规式,它们所表示的正规集分别为L(U), L(U)ÈL(V), L(U)L(V)和(L(U))*;
4. 仅由有限次使用上述三步骤而定义的表达式才是S上的正规式,仅由这些正规式所表示的字集才是S上的正规集。
正规式的运算符的“½”读为“或” ,“· ”读为“连接”;“*”读为“闭包”(即,任意有限次的自重复连接)。
在不致混淆时,括号可省去,但规定算符的优先顺序为“(”、“)”、“*”、“· ”、“½” 。连接符“· ”一般可省略不写。
“*”、“· ”和“½” 都是左结合的。
例 令S={a,b}, S上的正规式和相应的正规集的例子有:
正规式 正规集
a {a}
a½b {a,b}
ab {ab}
(a½b)(a {aa,ab,ba,bb}
a * {e ,a,a, ……任意个a的串}
ba* {b, ba, baa, baaa, …}
(a½b)* {e ,a,b,aa,ab ……所有由a和b
组成的串}
(a½b)*(aa½bb)(a½b)* {S*上所有含有两个相继的a
或两个相继的b组成 的串}
关键字表package CompilePrograme;
import java.awt.List;
import java.util.Scanner;
public class Compile {
public static void main(String[] args) {
// TODO Auto-generated method stub
double startTime = System.currentTimeMillis();
final int MAX_LEN = 100;
Scanner input = new Scanner(System.in);
System.out.print("Please input a string <end with '#'>:");
String uString = input.nextLine();
input.close();
String[] keyWords = new String[] { "begin", "if", "then", "while", "do", "end" };
char[] analyseData = new char[MAX_LEN];
int index = 0, key = 0;
List list = new List();
do {
String compareStr = null;
char temp = uString.charAt(index);
list = extactCharacters(temp, analyseData, keyWords, uString, index, compareStr);
if (list.getItemCount() == 0) {
index++;
continue;
}
// 规定List的第一个元素为index,第二个元素为key
index = Integer.parseInt(list.getItem(0));
key = Integer.parseInt(list.getItem(1));
String words = list.getItem(2);
System.out.println("< " + key + " ," + words + " >");
} while (key != 0);
double endTime = System.currentTimeMillis();
System.out.println("\nProgram running time is :" + (endTime - startTime));
}
public static List extactCharacters(char temp, char[] analyseDate, String[] keywords, String uString, int index,
String compareStr) {
int keyID = -1, m = 0;
// index--;
List list = new List();
// 1.判断下一个读入的字符是否为空格,用while作为大循环,若读取到空格则跳出方法,提取下一个字符进行判断
while (temp != ' ') {
// 2.判断当前字符是字母或者数字和字母的组合
if (temp >= 'a' && temp <= 'z') {
m = 0;
// 当读取到不是大小写字母或者数字时候判断为一个单词读取完成
while (temp >= 'a' && temp <= 'z' || temp >= 'A' && temp <= 'Z' || temp >= '0' && temp <= '9') {
analyseDate[m++] = temp;
compareStr += temp + "";
temp = uString.charAt(++index);
}
compareStr = compareStr.substring(4);
// 与读取出来的字符判断是否为关键字
for (int i = 0; i < 6; i++) {
if (compareStr.equals(keywords[i])) {
keyID = i + 1;
list.add(index + "");
list.add(keyID + "");
list.add(compareStr);
return list;
}
}
// 不是关键字就当作为标识符
keyID = 10;
list.add(index + "");
list.add(keyID + "");
list.add(compareStr);
return list;
}
// 3,判断当前字符是数字?
else if (temp >= '0' && temp <= '9') {
m = 0;
String tempTokens = null;
// 对后面的字符进行判断是否为数字
while (temp >= '0' && temp <= '9') {
analyseDate[m++] = temp;
tempTokens += temp;
temp = uString.charAt(++index);
}
// 不是数字则返回种别码,结束当前方法
keyID = 11;
tempTokens = tempTokens.substring(4);
list.add(index + "");
list.add(keyID + "");
list.add(tempTokens + "");
return list;
}
m = 0;
// 4.判断当前字符是其他关系运算符
String token = null;
switch (temp) {
case '<':
// String token = null;
analyseDate[m++] = temp;
token += temp;
if (uString.charAt(++index) == '=') {
analyseDate[m++] = temp;
keyID = 22;
token += uString.charAt(index++);
} else if (uString.charAt(++index) == '>') {
analyseDate[m++] = temp;
keyID = 21;
token += uString.charAt(index++);
} else {
keyID = 23;
}
list.add(index + "");
list.add(keyID + "");
token = token.substring(4);
list.add(token);
return list;
case '>':
// String tokens = null;
analyseDate[m++] = temp;
token += temp;
if (uString.charAt(++index) == '=') {
keyID = 24;
analyseDate[m++] = temp;
token += uString.charAt(index++);
} else {
keyID = 20;
}
list.add(index + "");
list.add(keyID + "");
token = token.substring(4);
list.add(token);
return list;
case ':':
analyseDate[m++] = temp;
token += temp;
if (uString.charAt(++index) == '=') {
keyID = 18;
// analyseDate[m++] = temp;
analyseDate[m++] = uString.charAt(index);
token += uString.charAt(index++);
} else {
keyID = 17;
}
list.add(index + "");
list.add(keyID + "");
token = token.substring(4);
list.add(token);
return list;
case '*':
keyID = 13;
break;
case '/':
keyID = 14;
break;
case '+':
keyID = 15;
break;
case '-':
keyID = 16;
break;
case '=':
keyID = 25;
break;
case ';':
keyID = 26;
break;
case '(':
keyID = 27;
break;
case ')':
keyID = 28;
break;
case '#':
keyID = 0;
break;
default:
keyID = -1;
break;
}
analyseDate[m++] = temp;
list.add(++index + "");
list.add(keyID + "");
list.add(temp + "");
return list;
}
return list;
}
}运行结果
来源:https://www.cnblogs.com/jianzhihao/p/5924714.html