zoukankan      html  css  js  c++  java
  • 作业十二——实验二 递归下降语法分析

    一、实验目的:

    利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

    编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

    二、实验原理

    每个非终结符都对应一个子程序。

    该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:

    • 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
    • 每遇到一个非终结符,则调用相应的子程序

    三、实验要求说明

    输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。

    例如:

    输入begin a:=9;x:=2*3;b:=a+x end #

    输出success

    输入x:=a+b*c  end #

    输出‘end' error

    四、实验步骤

    1.待分析的语言的语法(参考P90)

    2.将其改为文法表示,至少包含

    –语句

    –条件

    –表达式

    3. 消除其左递归

    4. 提取公共左因子

    5. SELECT集计算

    6. LL(1)文法判断

    7. 递归下降分析程序

    连接上次博客(https://www.cnblogs.com/a131452/p/11646345.html)中的代码进行改进:

    #include<conio.h>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>

    char duru[100], zuche[20];
    char ch;
    int fg,p,m,n,num; 
    char *index[35]={"begin","if","then","while","do","end","char","double","enum","float","int","long","short","signed",
    "struct","union","unsigned","void","for","break","continue","else","goto","switch","case","default",
    "return","auto","extern","register","static","const","sizeof","typedef","volatile"};


    void E();
    void T();
    void E1();
    void T1();
    void F();
    void error();

    void scaner(){
    for (n=0;n<20;n++)
    zuche[n]=NULL;
    m=0;
    num=0;
    ch=duru[p++];
    while(ch==' '){ //跳过空格
    ch=duru[p++];
    }
    if(ch>='a'&&ch<='z'){ //判断单词
    while(ch>='a'&&ch<='z'){
    zuche[m++]=ch;
    ch=duru[p++];
    }
    fg=10;
    p--;
    for(n=0;n<6;n++){
    if(strcmp(zuche,index[n])==0){
    fg=n+1;
    break;
    }
    }
    }
    else{ 
    if(ch>='0'&&ch<='9'){ //判断数字
    while(ch>='0'&&ch<='9'){
    num=num*10+(ch-'0');
    ch=duru[p++];
    }
    fg=11;
    p--;
    }
    else{
    switch(ch){
    case '<':
    zuche[m++]=ch;
    ch=duru[p++];
    if(ch=='>'){ //<>
    fg=22;
    zuche[m++]=ch;
    }
    else if(ch=='='){ //<=
    fg=21;
    zuche[m++]=ch;
    }
    else{ //<
    fg=20;
    p--;
    }
    break;

    case '>':
    m=0;
    zuche[m++]=ch;
    ch=duru[p++];
    if(ch=='='){ //>=
    fg=24;
    zuche[m++]=ch;
    }
    else{ //>
    fg=23;
    p--;
    }
    break;

    case ':':
    m=0;
    zuche[m++]=ch;
    ch=duru[p++];
    if(ch=='='){ //:=
    fg=18;
    zuche[m++]=ch;
    }
    else{ //:
    fg=17;
    p--;
    }
    break;

    case '+':fg=13;zuche[0]=ch;break;
    case '-':fg=14;zuche[0]=ch;break;
    case '*':fg=15;zuche[0]=ch;break;
    case '/':fg=16;zuche[0]=ch;break;
    case '=':fg=25;zuche[0]=ch;break;
    case ';':fg=26;zuche[0]=ch;break;
    case '(':fg=27;zuche[0]=ch;break;
    case ')':fg=28;zuche[0]=ch;break;
    case '#':fg=0;zuche[0]=ch;break;
    default:fg=-1;zuche[0]=ch;break;
    }
    }
    }
    }

    void E(){
    T();
    E1();
    }

    void E1(){
    if(fg==13){
    scaner();
    T();
    E1();
    }
    else if (fg==0||fg==28){
    }
    else
    error();
    }

    void T(){
    F();
    T1();
    }

    void T1(){
    if(fg==15){
    scaner();
    F();
    T1();
    }
    else if (fg==0||fg==28||fg==13){
    }
    else
    error();
    }

    void F(){
    if(fg==27){
    scaner();
    E();
    if(fg==28)
    scaner();
    else
    error();
    }
    else if (fg==11||fg==10)
    scaner();
    else
    error();
    }

    void error(){
    printf(" (%s,出错!)",zuche);
    }

    int main(){
    p=0;
    printf("请输入符号串(End with '#'): ");
    do
    {
    ch=getchar();
    duru[p++]=ch;
    }while(ch!='#');
    p=0;
    do
    {
    scaner();
    E();
    }while(fg!=0);


    getch(); //用于让程序停留在显示页面
    }

    结果截图:

     2、

    #include<conio.h>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>

    char duru[100], zuche[20];
    char ch;
    int fg,p,m,n,num; 
    char *index[35]={"begin","if","then","while","do","end","char","double","enum","float","int","long","short","signed",
    "struct","union","unsigned","void","for","break","continue","else","goto","switch","case","default",
    "return","auto","extern","register","static","const","sizeof","typedef","volatile"};
    int kk=0; //判断是否有错误

    void scaner();
    void panduan();
    void yinzi();
    void yuju();
    void yucuan();
    void tiaojian();
    void biaoda();
    void xiang();


    void scaner(){
    for (n=0;n<20;n++)
    zuche[n]=NULL;
    m=0;
    num=0;
    ch=duru[p++];
    while(ch==' '){ //跳过空格
    ch=duru[p++];
    }
    if(ch>='a'&&ch<='z'){ //判断单词
    while(ch>='a'&&ch<='z'){
    zuche[m++]=ch;
    ch=duru[p++];
    }
    fg=10;
    p--;
    for(n=0;n<6;n++){
    if(strcmp(zuche,index[n])==0){
    fg=n+1;
    break;
    }
    }
    }
    else{ 
    if(ch>='0'&&ch<='9'){ //判断数字
    while(ch>='0'&&ch<='9'){
    num=num*10+(ch-'0');
    ch=duru[p++];
    }
    fg=11;
    p--;
    }
    else{
    switch(ch){
    case '<':
    zuche[m++]=ch;
    ch=duru[p++];
    if(ch=='>'){ //<>
    fg=22;
    zuche[m++]=ch;
    }
    else if(ch=='='){ //<=
    fg=21;
    zuche[m++]=ch;
    }
    else{ //<
    fg=20;
    p--;
    }
    break;

    case '>':
    m=0;
    zuche[m++]=ch;
    ch=duru[p++];
    if(ch=='='){ //>=
    fg=24;
    zuche[m++]=ch;
    }
    else{ //>
    fg=23;
    p--;
    }
    break;

    case ':':
    m=0;
    zuche[m++]=ch;
    ch=duru[p++];
    if(ch=='='){ //:=
    fg=18;
    zuche[m++]=ch;
    }
    else{ //:
    fg=17;
    p--;
    }
    break;

    case '+':fg=13;zuche[0]=ch;break;
    case '-':fg=14;zuche[0]=ch;break;
    case '*':fg=15;zuche[0]=ch;break;
    case '/':fg=16;zuche[0]=ch;break;
    case '=':fg=25;zuche[0]=ch;break;
    case ';':fg=26;zuche[0]=ch;break;
    case '(':fg=27;zuche[0]=ch;break;
    case ')':fg=28;zuche[0]=ch;break;
    case '#':fg=0;zuche[0]=ch;break;
    default:fg=-1;zuche[0]=ch;break;
    }
    }
    }
    }
    //程序,判断是否以begin开始,end #结束
    void panduan(){
    if (fg==1) { //begin
    scaner();
    yucuan();
    if (fg==6) { //end
    scaner();
    if (fg==0 && kk==0){
    printf("success ");
    }
    }
    else {
    printf("error,lose 'end' ! ");
    kk=1;
    exit(0);
    }
    }
    else {
    printf("error,lose 'begin' ! ");
    kk=1;
    exit(0);
    }
    return;
    }
    //语句串 
    void yucuan() {
    yuju();
    while(fg==26) { 
    scaner();
    yuju();
    }
    return;
    }

    //语句
    void yuju(){
    if (fg==10) { //为标识符
    scaner();
    if (fg==18) { // :=
    scaner();
    biaoda();
    }
    else {
    printf("error!");
    kk=1;
    exit(0);
    }
    }
    else if(fg==2){ // if
    tiaojian();
    scaner();
    if(fg==3){
    yuju();
    }
    else{
    printf("error,lose 'then' ! ");
    kk=1;
    exit(0);
    }
    }
    else {
    printf("error!");
    kk=1;
    exit(0);
    }

    return;
    }
    //条件
    void tiaojian(){
    biaoda();
    if(fg==25||fg==0||fg==20||fg==21||fg==23||fg==24){
    scaner();
    }
    else{
    printf("error! ");
    kk=1;
    exit(0);
    }
    biaoda();
    return;
    }
    //表达式 
    void biaoda(){
    xiang();
    while(fg==13 || fg==14) {
    scaner();
    xiang();
    }
    return;
    }
    //项 
    void xiang(){
    yinzi();
    while(fg==15 || fg==16) {
    scaner();
    yinzi();
    }
    return;
    }
    //因子 
    void yinzi(){
    if(fg==10 || fg==11){
    scaner(); //为标识符或整常数时,读下一个单词符号
    }
    else if(fg==27) {
    scaner();
    biaoda();
    if(fg==28){
    scaner();
    }
    else {
    printf(" ')' 错误 ");
    kk=1;
    exit(0);
    }
    } else {
    printf("表达式错误 ");
    kk=1;
    exit(0);
    }
    return;
    }

    int main(void){
    p=0;
    int i;
    printf("请输入源程序: ");
    do {
    scanf("%c",&ch);
    duru[p++]=ch;
    } while(ch!='#');
    p=0;
    do{
    scaner();
    panduan();
    }while(fg!=0);
    printf("语法分析结束! ");

    }

    截图如下:

  • 相关阅读:
    例2-3
    例2-2
    例2-1
    p14
    第一次作业
    例1-1
    第二次作业(2)
    第二次作业
    第三章3-3
    第三章3-2
  • 原文地址:https://www.cnblogs.com/dianshuizheng/p/11960152.html
Copyright © 2011-2022 走看看