package cn.menglangpoem.analyze;
public class Util {
//存储关键字
private static String[] keyWords = new String[]{"begin","if","then","while","do","end"};
//token字符对象,用于存储结果字符
private StringBuilder token = null;
private int syn;//种别码
private int pointer;//指针
private String source;//源代码
private boolean flag = true;
//设置位置
public void setPointer(int pointer) {
this.pointer = pointer;
}
//获取种别码
public int getSyn() {
return syn;
}
//获取定位
public int getPointer() {
return pointer;
}
//构造函数
public Util(String source){
this.source = source;
}
//获取token
public StringBuilder getToken() {
return token;
}
//存储运算符和界符
//: = + - * / < <= <> > >= = ; ( ) #
//判断是否为关键字
private int isKeyWords(String s)
{
//System.out.println("传进来->"+c);
for(int i = 0;i<keyWords.length;i++)
{
//查找成功
if(s.equals(keyWords[i])) return i+1;
}
//查找不成功
return -1;
}
//判断是否为字母
private boolean isCharacter(char c)
{
if((c>='a'&&c<='z') || (c>='A'&&c<='Z' ) || c=='_') return true;
else return false;
}
//判断是否为数字
private boolean isNum(char c)
{
if(c>='0' && c<='9') return true;
else return false;
}
//词法分析代码
public void scanner()
{
//用于存储单个字符
char ch;
//开始扫描
//赋初值
token = new StringBuilder();
ch = source.charAt(pointer);
//System.out.println(ch);
//空格后移
if (ch == ' ') pointer++;
//如果开头是字母
if (isCharacter(ch))
{
//扫描整个单词符号并存储
while (isCharacter(ch) || isNum(ch))
{
//System.out.println(ch);
//存储
token.append(ch);
// System.out.println(ch+"----"+pointer);
pointer++;
ch = source.charAt(pointer);
}
//判断是否为关键字
int x = isKeyWords(token.toString());
//如果是关键字
if (x != -1)
syn = x;
//如果不是关键字
else syn = 10;
}
//如果开头是数字
else if (isNum(ch))
{
//扫描整个单词并存储
while (isNum(ch))
{
token.append(ch);
pointer++;
ch = source.charAt(pointer);
}
//输出类型以及编码
syn = 11;
}
//判断运算符
else
{
if (ch == ' ')
{
scanner();
return;
}
//1.首先判断单个字符,且不会产生歧义的有 + - * / = ;( ) #
switch (ch)
{
case '+':
token.append('+');
syn = 13;
break;
case '-':
token.append('-');
syn = 14;
break;
case '*':
token.append('*');
syn = 15;
break;
case '/':
token.append('/');
syn = 16;
break;
case '=':
token.append('=');
syn = 25;
break;
case ';':
token.append(';');
syn = 26;
break;
case '(':
token.append('(');
syn = 27;
break;
case ')':
token.append(')');
syn = 28;
break;
case '#':
token.append('#');
syn = 0;
break;
}
//2.判断有歧义的运算符和界符
//(1) : :=
if (ch == ':')
{
//储存 :
token.append(ch);
//判断是否为 :=
//如果是 :=
if (source.charAt(pointer+1) == '=')
{
pointer++;
//储存 =
token.append(source.charAt(pointer));
syn = 18;
}
//如果不是
else
{
syn = 17;
}
}
//(2) < <> <=
if (ch == '<')
{
token.append(ch);
//判断是否为 <>
if (source.charAt(pointer+1) == '>')
{
pointer++;
token.append(source.charAt(pointer));
syn = 21;
}
//判断是否为 <=
else if (source.charAt(pointer+1) == '=')
{
pointer++;
token.append(source.charAt(pointer));
syn = 22;
}
//都不是,那就是<
else
{
syn = 20;
}
}
//(3) > >=
if (ch == '>')
{
//储存 :
token.append(ch);
//判断是否为 :=
//如果是 :=
if (source.charAt(pointer+1) == '=')
{
pointer++;
//储存 =
token.append(source.charAt(pointer));
syn = 24;
}
//如果不是
else
{
syn = 23;
}
}
//指针后移
pointer++;
}
}
//语法分析总控程序
public void run()
{
scanner();
parser();
}
//子递归程序
private void parser()
{
if (syn == 1)//判断是否为begin
{
scanner();//扫描下一个单词
yuju(); //对整个语句串进行分析
//判断是否为end
if (syn == 6)
{
scanner();
//判断是否为#并且没有出错
if (syn == 0 && flag)
{
System.out.println("success!");
}
//出错
else
{
System.err.println("error!");
}
}
}
//开头不是begin
else
{
flag = false;
System.err.println("error!开头没有begin");
}
}
//语句串分析函数
private void yuju()
{
//调用statement函数
statement();
//一条一条语句的分析
while(syn == 26)//分号
{
scanner();
if (syn != 6) //不是end(保证程序正常结束)
{
statement();//分析单条语句
}
}
}
//判断赋值语句前半部分
private void statement()
{
if (syn == 10) //开头必须为标识符
{
scanner();//读取下一个字符
if (syn == 18) //赋值语句必须含有 :=
{
scanner();//读取下一个字符
expression();//判断赋值语句后半部分
}
else //不是:=
{
flag = false;
System.err.println("error!没有:=");
}
}
//开头不是标识符
else
{
flag = false;
System.err.println("error!开头不是标识符");
}
}
//判断赋值语句后半部分
private void expression()
{
//先判断后半部分的开头是否为标识符或者常数或者左括号
term();
//判断是否含有+ -
while (syn == 13 || syn == 14)
{
scanner();//扫描后移
term();//判断+ - 后面跟的是不是标识符或者常数或者左括号
}
}
//判断赋值语句后半部分
private void term()
{
//先判断后半部分的开头是否为标识符或者常数或者左括号
facter();
//判断是否含有* /
while (syn == 15 || syn == 16)
{
scanner();//扫描后移
facter();//判断* / 后面跟的是不是标识符或者常数或者左括号
}
}
//判断是否含有标识符或者常数或者括号
private void facter()
{
//开头为常数或者标识符
if (syn == 10 || syn == 11)
{
scanner();
}
else if (syn == 27) //开头是左括号
{
scanner();//后移
expression();
if (syn == 28) //判断是不是以右括号结尾
{
scanner();
}
//报错
else
{
System.err.println("error!没有右括号");
flag = false;
}
}
//如果既不是括号,也不是标识符和常数
else
{
System.err.println("error!没有标识符或者常数或者括号");
flag = false;
}
}
}