功能概述:
根据简单语言的词法和各单词符号种别码表,编写C或C++语言源程序,实现针对该简单语言的词法分析器,然后构造语法分析器。
(1)文件struct.java定义单词符号的二元组结构、全局变量、关键字表的结束标志等。
(2)文件funs.java实现词法扫描算法scanner及其所需的各种基本操作算法。
(3)文件text.java调用scanner算法,实现词法分析器的功能。
所用知识:1.词法分析 2.语法分析
开发环境:Eclipse 2021 jdk1.8
//struct.java 将属性封装,可以用Java自带的集合ArrayList<>
package text;
public class struct {
private String word;
private int num;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
//funs.java 完成主要功能
package text;
import java.util.Scanner;
public class funs {
String keys[]= { "begin","if" ,"then","while","do","end","game over"};
int p_input=0,p_token=0,over=1,k=0,r=0,r1=0;
String input;
char b[]= new char[220],a[];
String e[]= new String[220];
int e1[]=new int[220];
char ch;
public void fun() {
@SuppressWarnings("resource")
Scanner in=new Scanner(System.in);
System.out.print("输入字符串#号结束:");
input =in.nextLine();
b=input.toCharArray();a=new char[b.length+1];
for(int u=0;u<=b.length-1;u++)
a[u]=b[u];
System.out.print(input+"\n");
struct s=new struct();
while(over<1000&&over!=-1) {
s=scanner(a[p_input]);
if(over<1000&&s.getNum()!=0) {
e[r1]=s.getWord();
e1[r1]=s.getNum();
r1++;
System.out.print("("+s.getNum()+","+s.getWord()+") ");
}
over=s.getNum();
}
}
public struct scanner(char a) {
struct myword=new struct();
char token[]= new char[220];
p_token=0;
a=get_ch(); //
String s="";int m=0;
if(numbers(a)==1) {
while(numbers(a)==1) {
merge(token);
a=get_ch();
m++;
}
restre();
myword.setNum(11);
for(int i=0;i<m;i++) s+=token[i];
myword.setWord(s);
return myword;}
else if(letters(a)==1) {
while(letters(a)==1||numbers(a)==1) {
m++;
merge(token);
a=get_ch();
}
restre();
for(int i=0;i<m;i++) s+=token[i];
myword.setNum(key(s));
myword.setWord(s);
return myword;
}
else switch (a) {
case '+':
myword.setNum(13);
myword.setWord("+");
return myword;
case '-':
myword.setNum(14);
myword.setWord("-");
return myword;
case '*':
myword.setNum(15);
myword.setWord("*");
return myword;
case '/':
myword.setNum(16);
myword.setWord("/");
return myword;
case ';':
myword.setNum(26);
myword.setWord(";");
return myword;
case ':':
a=get_ch();
if(a=='='){
myword.setNum(18);
myword.setWord(":=");
}
else {
myword.setNum(17);
myword.setWord(":");}
return myword;
case '(':
myword.setNum(27);
myword.setWord("(");
return myword;
case ')':
myword.setNum(28);
myword.setWord(")");
return myword;
case '#':
myword.setNum(0);
myword.setWord("#");
return myword;
case '=':
myword.setNum(25);
myword.setWord("=");
return myword;
case '>':
a=get_ch();
if (a == '=')
{
myword.setNum(24);
myword.setWord(">=");
return(myword);
}
myword.setNum(23);
myword.setWord(">");
return(myword);
case '<':
a=get_ch();
if (ch == '=')
{
myword.setNum(22);
myword.setWord("<=");
return(myword);
}
myword.setNum(20);
myword.setWord("<");
return(myword);
case '\0':
myword.setNum(1000);
myword.setWord("OVER");
return myword;
case ' ':
get_sp();
return myword;
default:
myword.setNum(-1);
myword.setWord("ERRO");
return myword;
}
}
public char get_ch() {//获取当前字符
ch=a[p_input];
p_input++;
return ch;
}
public void restre() {//往回走一个
p_input--;
}
public void get_sp() {//去掉空格
while(ch==' ' ||ch==10){
//if(p_input<=a.length-1) {
ch=a[p_input];
p_input++; //}
}p_input--;
}
public void merge(char[] token) {//合并
token[p_token]=ch;
p_token++;
}
public int letters(char a) {//识别数字
if(a<='Z'&&a>='A'||a<='z'&&a>='a') return 1;
return 0;
}
public int numbers(char a) {//识别字母
if(a>='0'&&a<='9') return 1;
return 0;
}
public int key(String s) {//识别关键字
int r=0,i;
for(i=0;i<=5;i++)
if(keys[i].equals(s)) {r++; break;}
if(r==1) return i+1;
else return 10;
}
void ex() {
te();
while(e1[r]==13||e1[r]==14)
{
r++;
te();
}
return;
}
void fa() {
if (e1[r]==10 || e1[r]== 11) r++;
else if (e1[r]== 27)
{
r++;
ex();
if (e1[r]== 28) r++;
else { System.out.print("\n)错误"); k = 1; }
}
else { System.out.print("\n表达式错误"); k = 1; }
return;
}
void te() {
fa();
while (e1[r]==15||e1[r]==16)
{
r++;
fa();
}
return;
}
void st() {
if (e1[r]==10)
{
r++;
if (e1[r] == 18)
{
r++;
if(e1[r]==6) System.out.print("\n;错误");
ex();
}
else { System.out.print("\n赋值号错误"); k = 1; }
}
else { System.out.print("\n输出于醋错误"); k = 1;}
return;
}
void yu() {
st();
while (e1[r]==26)//;
{
r++;
st();
}
return;
}
void lr() {
if (e1[r]== 1)//begin
{
r++;
yu();
if (e1[r] == 6) //end
{
r++;
if ( k == 0) System.out.print("\nsuccess");
}
else { if (k != 1) System.out.print("\nend错误"); k = 1; }
}
else System.out.print("\nbegin错误");
return;
}
}
package text;
public class test {
public static void main(String[] args) {
funs s=new funs();
s.fun(); s.lr();
}
}
运行结果:
|
| |
|
通过分析语法,知道‘;’只可能紧跟语句和end,而当end时即出现;错误,在st()函数调用ex()之前,单词往后走之后判断即可检查出具体错误,至于其他的具体错误此处未列出。