首页 > 其他分享 >编译原理PL0语法分析实验1

编译原理PL0语法分析实验1

时间:2024-04-28 14:22:05浏览次数:14  
标签:ch 语法分析 PL0 ++ void syn break 编译 token

编译原理PL0语法分析实验1

1,待分析的简单语言的词法
相同点:都是分析种别码
不同点:词法分析器分析的是字符串中的单词的种别码(单词)
语法分析器分析的是字符串的文法是否正确(句子)
待分析的简单语言的语法

BNF:
(1)<程序>::=begin<语句串>end
(2)<语句串>::=<语句>{;<语句>}
(3)<语句>::=<赋值语句>
(4)<赋值语句>::=ID:=<表达式>
(5)<表达式>::=<项>{+<项>|-<项>}
(6)<项>::=<因子{*<因子>|/<因子>}

语法分析程序的功能
输入一个c语言的字符串,以#号结束,如果是文法正确的句子,那么程序就会输出成功信息;如果是文法错误的句子,那么程序就会输出错误的信息以及提示出错点在哪里
正确的文法:begin BNF文法 end#

【例1】
给定一个字符串,判断语法是否正确:
输入:begin a:=9;x:=2*3;b:=a+x end#
输出:成功!
输入:begin x:=a+b*c end
输出:错误!“end”后出错了
输入:begin x:=a+b*c
输出:错误!缺少“end”
输入:x:=a+b*c end#
输出:错误!缺少begin
程序验证代码(语法分析程序)

#include <studio.h>
#include <string.h>
void scaner();
void sentence();
void statement();
void expression();
void term();
void factor();
char *key[0]={"begin","if","then","while","do","end"},ch[100];
int p=0,kk=0,q,syn;
int main()
{
  printf("输入:\n");
  gets(ch);
  sentence();
  return 0;
}

void scanner()
{
  char token[100] = {};
  q = 0;
  while(ch[p] == ' ') p++;
  if((ch[p] >= 'a' && ch[p] <= 'z')||(ch[p] >= 'A' && ch[p] <= 'Z')
  {
        token[q++] = ch[p];
        p++;
        while((ch[p] >= '0' && ch[p] <= '9')||(ch[p] >= 'a' && ch[p] <= 'z') ||(ch[p] >= 'A' && ch[p] <= 'Z')) 
            token[q++] = ch[p++];

     syn = 10;
     token[q] = '\0';
     for(int n = 0;n < 6;n++)
        {
            if(strcmp(token,key[n]) == 0)
          {
               syn = n + 1;
             break;
          }
        }
    }
   else if(ch[p] >= '0' && ch[p] <= '9')
    {
        token[q++] = ch[p];
     p++;
     while(ch[p] >= '0' && ch[p] <= '9') 
            token[q++] = ch[p++];

     syn = 11;
    }
    else switch(ch[p])
    {
        case '<':
            token[q++] = ch[p++];
          if(ch[p] == '>')
          {
               syn = 21;
            token[q++] = ch[p++];
          }  
          else if(ch[p] == '=')
          {
            syn = 22;
                token[q++] = ch[p++];
          }
          else 
                syn = 23;
          break;
     case '>':
            token[q++] = ch[p++];
          if(ch[p] == '>')
            {
                syn = 24;
                token[q++] = ch[p++];
         }
            else 
                syn = 20;

            break;

        case ':':
            token[q++] = ch[p++];
            if(ch[p] == "="){
                syn = 18;
                token[q++] = ch[p++];
            }
            else 
                syn = 17;
            token[q++] = ch[p++];
            break;
        case '*':
            syn = 13;
            token[q++] = ch[p++];
            break;
        case '/':
            syn = 14;
            token[q++] = ch[p++];
            break;
        case '+':
            syn = 15;
            token[q++] = ch[p++];
            break;
        case '-':
            syn = 16;
            token[q++] = ch[p++];
            break;
        case '=':
            syn = 25;
            token[q++] = ch[p++];
            break;
        case ';':
            syn = 26;
            token[q++] = ch[p++];
            break;
        case '(':
            syn = 27;
            token[q++] = ch[p++];
            break;
        case ')':
            syn = 28;
            token[q++] = ch[p++];
            break;
        case '#':
            syn = 0;
            token[q++] = ch[p++];
            break;
        case '\n':
            syn = -2;
            break;
        default:
            syn = -1;
            break;
    }
}

void sentence()
{
    scaner();
    if(syn == 1)
    {
        statement();
        while(syn == 26) statement();
        if(syn == 6)
        {
            scaner();
            if(syn == 0) printf("成功!\n");
            else printf("错误!“end”后出错。\n");
        }
        else
        {
            printf("错误!缺少“end”。\n");
            kk = 1;
        }
    }
    else
    {
        printf("错误!缺少“begin”。\n");
        kk = 1;
    }
}

void statement()
{
    scaner();
    if(syn == 10)
    {
        scaner();
        if(syn == 18)
        {
            scaner();
            expression();
        }
        else
        {
            printf("错误!“:=”出错。\n");
            kk = 1;
        }
    }
    else    
    {
        printf("错误!句子出错。\n");
        kk = 1;
    }
    return;
}

void expression()
{
    term();
    while((syn == 13)||(syn == 14))
    {
        scaner();
        term();
    }
    return;
}

void term()
{
  factor();
  while((syn == 15)||(syn == 16))
  {
    scaner();
    factor();
  }  
    return;
}

void factor()
{
    if((syn == 10)||(syn == 11)) scaner();
    else if(syn == 27)
    {
        scaner();
        expression();
        if(syn == 28) scaner();
        else
        {
            printf("错误!“(”出错。\n");
            kk = 1;
        }
    }
    else
    {
        printf("错误!\n");
        kk = 1;
    }
    return;
}

//begin a:=9;x:=2*3;b:=a+x end#
//begin x:a+b*c en

————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

 

原文链接:https://blog.csdn.net/qq_44709970/article/details/121804295

标签:ch,语法分析,PL0,++,void,syn,break,编译,token
From: https://www.cnblogs.com/djcsch2001/p/18163614

相关文章

  • pl0词法分析器
    pl/0词法分析器下面是这个分析器的功能:1、待分析的简单语言的词法(1)关键字:beginifthenwhiledoend所有关键字都是小写。(2)运算符和界符::=+–*/<<=<>>>==;()#(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter|digit)*NUM=digitd......
  • openGauss MOT查询原生编译_JIT
    MOT查询原生编译(JIT)MOT使您可以在执行之前以原生格式(使用PREPARE语句)准备并分析预编译的完整查询。这种本机格式以后可以更有效地执行(使用EXECUTE命令)。这种类型的执行效率要高得多,因为在执行期间,本机格式绕过了多个数据库处理层。这种分工避免了重复的解析分析操作。LiteExecu......
  • openGauss 轻量版安装包编译
    轻量版安装包编译使用build/script/cmake_package_mini.sh脚本构建openGauss轻量版安装包。前提条件已按照搭建编译环境的要求准备好相关软硬件,并且已参考代码下载下载了代码。已完成开源软件编译构建,具体请参见开源软件编译构建。了解cmake_package_mini.sh脚本的参数选项......
  • 编译执行和解释执行有什么区别?
    编译执行和解释执行是两种不同的程序执行方式。编译执行是将源代码一次性编译成机器码,然后直接执行机器码。而解释执行是将源代码逐行解释执行,每执行一行就翻译成机器码并执行。编译执行的程序运行速度更快,但需要先编译,而解释执行的程序则无需编译,但运行速度较慢。解释执行不需要......
  • 04_Linux下把驱动编译进内核
    Linux下把驱动编译进内核需求:把前面课程学习的helloworld驱动编译到内核。例子:source"drivers/redled/Kconfig"configLED_4412 tristate"LedSupportforGPIOLed" dependsonLEDSCLASS help Thisoptionenablesupportforled说明:1.source“drivers/redled......
  • IDEA中springboot项目编译两次的问题
    原因:因为在导入项目的之后,项目无法运行,问题1:显示缺少org.springbootframe的依赖,不知道怎么解决,网上搜了个方法,就是勾选下图的选项,意思是把build操作由IDEA交给Maven,勾选之后确实可以启动项目了但是后面在执行Mybatis时,问题2:我发现无论如何都会报一个唯一键值重复的错误,思考原因......
  • window下使用vscode和cmake开发编译cpp代码
    window下使用vscode和cmake开发编译cpp代码1.先准备cpp编译环境还是要先使用vscode和mingw搭建好cpp开发环境,因为cmake不是一个编译工具,它只不过是根据CMakeLists.txt文件生成Makefile文件,Makefile文件再通过make规则使用gcc、g++等工具去实践编译代码。使用vscode和mingw......
  • C# 引用程序集编译在非同级目录实现
    情景:A项目是主项目,B项目是引用程序集,众所周知C#项目引用程序集编译时会生成在同一目录如果想让A.exe和B.dll生成不在统一目录,但是又存在依赖关系应该怎么做呢?实现原理分为两步1、配置生成逻辑2、动态加载DLL1、配置生成逻辑:打开A.csproj文件,找到<ProjectReferenceInclude......
  • Qt静态编译后使用QtCipherSqlitePlugin静态编译库
       Qt静态编译后使用QtCipherSqlitePlugin静态编译库  语文功底不好,标题起的有点绕口,解释一下:   就是我使用的Qt是Qt5.15.2静态编译包(要Qt静态编译文件这里下载:QT5.15.2静态编译包下载-koomee-博客园(cnblogs.com)),  先入正题讲解决办法(12345走起):   ......
  • 编译用于Qt的opencv问题解决
    CMakewasunabletofindabuildprogramcorrespondingto"MinGWMakefiles"解释:这个错误表明CMake无法找到用于生成Makefiles的构建程序。在使用CMake生成项目文件时,如果指定了"MinGWMakefiles",CMake需要一个Make工具来构建项目,而这个工具通常是由MinGW提供的。如......