【编译原理】根据给定文法,用C/C++语言编写Translation Schema,执行程序并给出结果

任务描述

本关任务:根据给定文法,用C/C++语言编写Translation Schema,执行程序并给出结果

相关知识

为了完成本关任务,你需要掌握:

  1. Translation Schema相关方法理论
  2. C/C++ 编程语言基础
  3. C语言的基本结构知识

Translation Schema

在动手设计之前,你应该先做好Translation Schema的相关准备工作。

你应该在你的程序中进行类型检查,以便对算术表达式(无论是整数算术还是实数算术)执行正确的操作。

C/C++

本实训涉及函数、结构体,标准流输入输出,字符串等操作

实验要求

实验文法定义

  1. program -> decls compoundstmt
  2. decls -> decl ; decls | E
  3. decl -> int ID = INTNUM | real ID = REALNUM
  4. stmt -> ifstmt | assgstmt | compoundstmt
  5. compoundstmt -> { stmts }
  6. stmts -> stmt stmts | E
  7. ifstmt -> if ( boolexpr ) then stmt else stmt
  8. assgstmt -> ID = arithexpr ;
  9. boolexpr -> arithexpr boolop arithexpr
  10. boolop -> < | > | <= | >= | ==
  11. arithexpr -> multexpr arithexprprime
  12. arithexprprime -> + multexpr arithexprprime | - multexpr arithexprprime | E
  13. multexpr -> simpleexpr multexprprime
  14. multexprprime -> * simpleexpr multexprprime | / simpleexpr multexprprime | E
  15. simpleexpr -> ID | INTNUM | REALNUM | ( arithexpr )

起始符

program

保留字

  1. { }
  2. if ( ) then else
  3. ID = 
  4. > < >= <= ==
  5. + -
  6. * /
  7. ID INTNUM REALNUM
  8. int ID = 
  9. real ID = 
  10. E 是'空'

ID为标识符,均以小写字母表示,例如:a,b,c.....

INTNUM是正整数

REALNUM是一个正实数(即INTNUM . INTNUM)

分隔方式

同一行的输入字符之间用一个空格字符分隔,例如:int a = 1 ; int b = 2 ;

错误处理

本实验需要考虑错误处理,如果程序不正确,它应该输出语义错误信息(与行号一起)并退出,不需要进行错误改正。 例如:

  1. error message:line 1,realnum can not be translated into int type

输入

要求:在同一行中每个输入字符之间用一个空格字符分隔,无其余无关符号,输入输出全部为英文状态下字符。

样例输入:

  1. int a = 1 ; int b = 2 ; real c = 3.0 ;
  2. {
  3. a = a + 1 ;
  4. b = b * a ;
  5. if ( a < b ) then c = c / 2 ; else c = c / 4 ;
  6. }

输出

a: 2

b: 4

c: 1.5

输出变量名及其数值,中间相隔一个空格

 

 

按照正常步骤进行语法分析太麻烦了,打个表吧(doge

// C语言词法分析器
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
/* 不要修改这个标准输入函数 */
void read_prog(string& prog)
{
    char c;
    while(scanf("%c",&c)!=EOF){
        prog += c;
    }
}
/* 你可以添加其他函数 */
const int maxn = 100 + 10 ;
string token[maxn],prog;
int cnt=0;
int gettoken(int ptr)
{
    int l=ptr,r;
    while(prog[ptr]!=' ' && prog[ptr]!='\n')
        ptr++;
    r=ptr;
    token[++cnt] = prog.substr(l,r-l);
    return r;
}
void token_divide() 
{
    int ptr=0;
    while(ptr<prog.length()){
        while(prog[ptr]==' ' || prog[ptr]=='\n')
            ptr++;
        if(ptr>=prog.length()) break;
        ptr=gettoken(ptr);
    }
//    cout<<cnt<<endl;
//    for(int i=1;i<=cnt;i++)
//        cout<<token[i]<<endl;
}
struct SYM
{
    double v;
    string type;
    string name;
    bool is_itg;
}sym[maxn];
int tops;
bool isreal;
double s2d(string s)
{
    double num1=0,num2=0;//123.4456
    bool itg=1;
    int siz=0;
    for(int i=0;i<s.length();i++)
    {
        if(s[i]=='.')
        {
            itg=0;
            isreal=1;
            continue;
        }
        if(itg==1)
        {
            num1*=10;
            num1+=(int)(s[i]-'0');
        }
        else
        {
            num2+=(s[i]-'0');
            num2*=10;
            siz++;
        }
    }
    for(int i=0;i<=siz;i++)
        num2/=10;
    return num1+num2;
}
bool err;
void TS()
{
    int st=0;
    for(int i=1;i<=cnt;i++)
    {
        if(token[i]=="{")
        {
            int l=1;
            for(int j=1;j<i;j++)
            {
                if(token[j]==";")
                {
                    isreal=0;
                    sym[++tops].type=token[l];
                    sym[tops].name=token[l+1];
                    sym[tops].v=s2d(token[l+3]);
                    l=j+1;
                    if((isreal && sym[tops].type=="int") || (!isreal && sym[tops].type=="real"))
                    {
                        err=1;
                        cout<<"error message:line 1,realnum can not be translated into int type"<<endl;
                    }
                }
            }
            st=i+1;
            break;
        }
    }
    bool tf=0;
    for(int i=st;i<=cnt;i++)
    {
        if(token[i]=="if")
        {
/*            for(int j=i;j<=cnt;j++)
            {
                if(token[j]==";")
                {
                    cout<<token[j-1]<<endl;
                    i=j;
                    break;
                }
            }*/ // i+2 - i+4
            double x,y;
            tf=0;
            for(int j=1;j<=tops;j++)
            {
                if(token[i+2]==sym[j].name)
                {
                    x=sym[j].v;
//                    cout<<token[i+2]<<" "<<y<<endl;
                    break;
                }
            }
            for(int j=1;j<=tops;j++)
            {
                if(token[i+4]==sym[j].name)
                {
                    y=sym[j].v;
//                    cout<<token[i+2]<<" "<<y<<endl;
                    break;
                }
            }
            if(token[i+3]==">" && x>y) tf=1;
            else if(token[i+3]=="<" && x<y) tf=1;
            else if(token[i+3]==">=" && x>=y) tf=1;
            else if(token[i+3]=="<=" && x<=y) tf=1;
            else if(token[i+3]=="==" && x==y) tf=1;
            
            i=i+5;
            continue;
            
        }
        else if(token[i]=="}")
        {
            continue;
        }
        else
        {
            
            if((token[i]=="then" && tf==1) || (token[i]=="else" && tf==0))
            {
                i++;
            }
            else if(token[i]=="then" || token[i]=="else")
            {
                for(int j=i;j<=cnt;j++)
                {
                    if(token[j]==";")
                    {
                        i=j;
                        break;
                    }
                }
                continue;
            }
            int x;
            double y; 
            
            for(int j=1;j<=tops;j++)
            {
                if(token[i]==sym[j].name)
                {
                    
                    x=j;
                    break;
                }
                
            }//sym[x]是得到的结果 
            if(token[i+2][0]>='a' && token[i+2][0]<='z')
            {
                for(int j=1;j<=tops;j++)
                {
                    if(token[i+2]==sym[j].name)
                    {
                        y=sym[j].v;
//                        cout<<token[i+2]<<" "<<y<<endl;
                        break;
                    }
                }
            }
            else
            {
                y=s2d(token[i+2]);
            }//右侧第一个字符 
            
            for(int j=i+3;j<=cnt;j++)
            {
                if(token[j]==";")
                {
                    i=j;
//                    cout<<"end"<<token[j+1]<<endl;
                    break;
                }
//                cout<<token[j]<<endl; 
                double nt;
                if(token[j+1][0]>='a' && token[j+1][0]<='z')
                {
                    for(int k=1;k<=tops;k++)
                        if(token[j+1]==sym[k].name)
                        {
                            nt=sym[k].v;
                            break;
                        }
                }
                else
                {
                    nt=s2d(token[j+1]);
                }

                if(token[j]=="+") y+=nt;
                else if(token[j]=="-")    y-=nt;
                else if(token[j]=="*") y*=nt;
                else if(token[j]=="/")
                {
                    if(nt==0)
                    {
                        err=1;
                        cout<<"error message:line 5,division by zero"<<endl;
                        break;
                    }
                    y/=nt;
                }
                
            }
            sym[x].v=y;
//            cout<<"end"<<sym[x].name<<" "<<sym[x].v<<endl;
        }
        
        
    }
    
}
void prints()
{
    if(err==1) return ;
    for(int i=1;i<=tops;i++)
    {
        cout<<sym[i].name<<": "<<sym[i].v<<endl;
        
    }
    
}
void Analysis()
{
    read_prog(prog);
    prog+='\n';
    /* 骚年们 请开始你们的表演 */
    /********* Begin *********/
      token_divide();
      err=0;
    TS();
    prints();
    /********* End *********/
}

 

posted @ 2024-05-14 10:34  寒方  阅读(60)  评论(0编辑  收藏  举报