编译原理 SysY语言的词法分析程序

Posted Ice丨shine

tags:

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

  1. 实验目的与内容
    对SysY语言进行词法分析,可以查出语言中可能包含的词法错误。
    从控制台输入字符串,如有出错则输出错误,没有错误则按照二元组的方式输出
  2. 设计方法
    对SysY语法进行分析如下:
    (1) 保留字: if else for while do continue return break int const main void
      注意:所有关键词都是小写的。
    (2) 标识符ID,与标准C语言一致,即:以下划线或字母开头的字母数字下划线组成的符号串。
    (3)运算符和分界符: +、-、*、/、% 、==、!=、<、>、<=、>= 、!、&&、|| 、(、)、{、}、[、]。
    (4) 空白符包括空格、制表符和换行符,用于分割标识符、保留字、运算符和分界符,词法分析阶段要忽略空白符。
    本程序使用Java编写
    程序启动输入后,字符串保留在instr中。先对字符串进行预处理,去除两个词之间多余的空格,再按空格进行切割。切割完成后逐个单词进行判断,分别判断是否属于保留字、数字、运算符和分界符等等,如果匹配成功则输出。每次判断时使用token逐个读取字符串的各个字符直到一个单词结束并且进行判断。
package cn.hdu;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Word {//1.词法分析程序


    public static boolean IsLetter(char ch){
        if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'))
            return true;
        return false;
    }

    //判断是否为数字
    public static boolean IsDigit(char ch)
    {
        if (ch >= '0'&&ch <= '9')
            return true;
        return false;
    }

    //判断是否为分界符
    public static int IsSymbol(char ch)
    {
        char symbol[]= { '(',')',',',';','<','>','{','}','[',']'};
        for (int i = 0; i < 8; i++)
        {
            if (ch == symbol[i])
                return i;
        }
        return -1;
    }

    //判断是否为关键字
    public static int IsKeyword(String str)
    {
        String keyword[] = {"if","else","for","while","do", "continue", "return", "break" ,"int", "const", "main", "void" };
        for (int i = 0; i < keyword.length; i++)
        {
            if (str.equals(keyword[i]) )
            {
                return i;
            }
        }
        //不是关键字即为标识符
        return 30;
    }


    public static boolean IsRight(String str)
    {
        char[] chars = str.toCharArray();
       // System.out.println(chars.length);
        int f = 0;
        //for (int i = 0; i < str.length()-1; i++)
        //{
           /* if (IsLetter(chars[i]) ||"_".equals( chars[i]))
                f=1;*/
                if (IsDigit(chars[0]))
                if (IsLetter(chars[1]) || chars[1] == '_')
                return false;
        //}
       /* if(f==0) return true;
        if(!(IsLetter(chars[0])||chars[0]=='_')) return false;
        for (int i = 0; i < str.length(); i++)
        {
            if (!(IsDigit(chars[i])||IsLetter(chars[i]) ||"_".equals( chars[i])))
                    return false;
        }*/
        return true;
    }
    //多余空格处理
     public static String HandleSpace(String str)
    {
        int j = 0;
        char[] word=new char[255];
        boolean temp = false;
        char[] a = str.toCharArray();
        for (int i = 0; i < a.length; i++)
        {

            if (a[i] != ' ' && a[i] != '\\t')
            {
                word[j++] = a[i];
                temp = false;
            }
            else
            {

                if (!temp&&a[i] != '\\t')
                {
                    word[j++] = a[i];
                    temp = true;
                }

            }

        }
        char[] ans = new char[j];
        for (int i = 0; i < j; i++) {
            ans[i]=word[i];
        }
         return String.valueOf(ans);
    }
   public static void main(String[] args) {
        String token= new String();//存放字符串
        String[] str;
       String instr;
       boolean flag=false;
        int k=0;
       Map<Integer,String> identifiers= new HashMap<>();
        Scanner sc = new Scanner(System.in);
        while(sc.hasNextLine()){
            instr = sc.nextLine();
            if(instr.equals("")) break;
            str = HandleSpace(instr).split(" ");//处理多余空格后按空格分隔
            for (int j = 0; j < str.length; j++) {
                //System.out.println(i+str[i]);
                char[] strtemp = str[j].toCharArray();//将分隔好的字符串装换为字符数组
                if (!IsRight(str[j]))
                {
                    System.out.println(str[j]+" 为非法输入");
                    break;
                }
                for (int i = 0; i<strtemp.length&&strtemp[i]!=' '; i++) {

                    //标识符,关键词
                    if ((IsLetter((strtemp[i])) || (strtemp[i]) == '_') && !flag)
                    {
                        while (i<strtemp.length&&(IsLetter(strtemp[i]) || IsDigit(strtemp[i]) || strtemp[i] == '_'))
                        {
                            //System.out.println("strtemp:"+strtemp[i]);
                            token += strtemp[i];
                            i++;
                        }
                        i--;
                        //System.out.println("token"+token);
                        //System.out.println("istoken"+IsKeyword(token));
                        if (IsKeyword(token) != 30)
                        {
                            System.out.println("(<保留字>"+token+")");

                        }

                        else{

                            if(identifiers.containsKey(token)){
                                System.out.println("(<标识符>,"+token+")");
                            }else{
                                identifiers.put(k,token);
                                System.out.println("(<标识符>,"+token+")");
                                k++;
                            }
                        }
                        token = "";
                    }
                    else if (IsDigit(strtemp[i]) && !flag)
                    {
                        while (i<strtemp.length&&IsDigit(strtemp[i]))
                        {
                            token +=strtemp[i];
                            i++;
                        }
                        i--;
                        System.out.println("(<数字> "+token+")");

                        token = "";
                    }

                    //<,<=,<>
                    else if (strtemp[i] == '<' && !flag)
                    {
                        if (i+1<strtemp.length&&strtemp[i+1] == '=')
                        {
                            System.out.println("(<运算符> <=)");

                        }
                        else if (i+1<strtemp.length&&strtemp[i+1] == '>')
                        {
                            System.out.println("(<运算符> <>)");

                        }
                        else
                        {
                            System.out.println("(<运算符> < )");

                        }
                    }
                    //>,>=
                    else if (strtemp[i] == '>' && !flag)
                    {
                        if (i+1<strtemp.length&&strtemp[i+1] == '=')
                        {
                            System.out.println("(<运算符> >=)");
                            i++;
                        }
                        else
                        {
                            System.out.println("(<运算符> >)");

                        }
                    }
                    //!,!=
                    else  if (strtemp[i] == '!' && !flag)
                    {
                        if (i+1<strtemp.length&&strtemp[i+1] == '=')
                        {
                            System.out.println("(<运算符> !=)");

                            i++;
                        }
                        else
                        {
                            System.out.println("(<运算符> !)");

                        }
                    }
                    //+,++
                    else if (strtemp[i] == '+' && !flag)
                    {
                        if (i+1<strtemp.length&&strtemp[i+1] == '+')
                        {
                            System.out.println("(<运算符> ++)");
                            i++;
                        }
                        else
                        {
                            System.out.println("(<运算符> +)");

                        }
                    }
                    //-,--
                    else if (strtemp[i] == '-' && !flag)
                    {
                        if (i+1<strtemp.length&&strtemp[i+1] == '-')
                        {
                            System.out.println("(<运算符> --)");
                            i++;
                        }
                        else
                        {
                            System.out.println("(<运算符> -)");

                        }
                    }
                    else if (strtemp[i] == '*' && !flag)
                    {
                        System.out.println("(<运算符> * )");

                    }

                    else if (strtemp[i] == '/' && !flag)
                    {
                        System.out.println("(<运算符> / )");


                    }
                    //=,==
                    else if (strtemp[i] == '=' && !flag)
                    {
                        if (i+1<strtemp.length&&strtemp[i+1] == '=')
                        {
                            System.out.println("(<运算符> ==)");
                            i++;
                        }
                        else
                        {
                            System.out.println("(<运算符> =)");

                        }


                    }
                    //余下定界符等
                    else if (IsSymbol(strtemp[i]) != -1 && !flag)
                    {
                        System.out.println("(<分界符> "+strtemp[i]+")");

                    }
                    else if(!flag)
                    {
                        System.out.println(str[j]+"为非法标识符");
                        break;
                    }
                }

            }



        }


    }
}

  1. 程序测试
    1.输入:
    int main(){
    return 0;
    }
    输出:
    (<保留字>int)
    (<保留字>main)
    (<分界符> ()
    (<分界符> ))
    (<分界符> {)
    (<保留字>return)
    (<数字> 0)
    (<分界符> 😉
    (<分界符> })
    2.输入:
    int a;
    int main(){
    a=10;
    return 0;
    }
    输出:
    (<保留字>int)
    (<标识符>,a)
    (<分界符> 😉
    (<保留字>int)
    (<保留字>main)
    (<分界符> ()
    (<分界符> ))
    (<分界符> {)
    (<标识符>,a)
    (<运算符> =)
    (<数字> 10)
    (<分界符> 😉
    (<保留字>return)
    (<数字> 0)
    (<分界符> 😉
    (<分界符> })
    3.输入:
    int main(){
    int 4a;
    }
    输出:
    (<保留字>int)
    (<保留字>main)
    (<分界符> ()
    (<分界符> ))
    (<分界符> {)
    (<保留字>int)
    4a; 为非法输入
    (<分界符> })
    4.输入:
    int ifElse() {
    int a;
    a = 5;
    if (a == 5) {
    a = 25;
    } else {
    a = a * 2;
    }
    return (a);
    }
    4.int main() {
    return (ifElse());
    }
    输出:
    (<保留字>int)
    (<标识符>,ifElse)
    (<分界符> ()
    (<分界符> ))
    (<分界符> {)
    (<保留字>int)
    (<标识符>,a)
    (<分界符>;)
    (<标识符>,a)
    (<运算符> =)
    (<数字> 5)
    (<分界符>;)
    (<保留字>if)
    (<分界符> ()
    (<标识符>,a)
    (<运算符> ==)
    (<数字> 5)
    (<分界符> ))
    (<分界符> {)
    (<标识符>,a)
    (<运算符> =)
    (<数字> 25)
    (<分界符>;)
    (<标识符>,a)
    (<运算符> =)
    (<数字> 25)
    (<分界符>;)
    (<分界符> })
    (<保留字>else)
    (<分界符> {)
    (<标识符>,a)
    (<运算符> =)
    (<标识符>,a)
    (<运算符> * )
    (<数字> 2)
    (<分界符>;)
    (<分界符> })
    (<保留字>return)
    (<分界符> ()
    (<标识符>,a)
    (<分界符> ))
    (<分界符>;)
    (<分界符> })
    (<保留字>int)
    (<保留字>main)
    (<分界符> ()
    (<分界符> ))
    (<分界符> {)
    (<保留字>return)
    (<分界符> ()
    (<标识符>,ifElse)
    (<分界符> ()
    (<分界符> ))
    (<分界符> ))
    (<分界符>;)
    (<分界符> })

以上是关于编译原理 SysY语言的词法分析程序的主要内容,如果未能解决你的问题,请参考以下文章

编译原理 SysY语言的词法分析程序

编译原理 实验一 java语言实现对C语言词法分析

编译原理 实验一 java语言实现对C语言词法分析

编译原理 递归下降子程序的语法分析技术

编译原理 递归下降子程序的语法分析技术

编译原理 递归下降子程序的语法分析技术