词法分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了词法分析相关的知识,希望对你有一定的参考价值。

词法分析器
 
定义:
词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位,包括关键字、标识符、运算符、界符和常量等
(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; } }

运行结果
技术分享






 

以上是关于词法分析的主要内容,如果未能解决你的问题,请参考以下文章

词法分析

词法分析器代码复审

实验一 词法分析器+编译原理

Second-词法分析

词法分析器

js词法分析