编译原理 词法分析+语法分析

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;
        }
    }
}

 

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值