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

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

时间:2024-05-14 10:44:54浏览次数:14  
标签:int C++ ptr token prog Translation include ID 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 *********/
}

 

标签:int,C++,ptr,token,prog,Translation,include,ID,Schema
From: https://www.cnblogs.com/hfang/p/18190796

相关文章

  • [19] C++网络通信开发
    Day1 通过引入路径找到类型根据角色进入方向开门(向量运算、几何概念、点乘)向量的减法:OtherActor->GetActorLocation()-GetActorLocation()这一部分是计算两个位置向量之间的差向量,即门的位置向量减去角色的位置向量,得到了一个从门指向角色的向量。向量的归一化:V1......
  • golang进程通过共享内存和C++进程进行通信
    目录serverclientserverC++可以使用POSIX共享内存API来创建和管理共享内存server.cpp#include<fcntl.h>#include<sys/mman.h>#include<sys/stat.h>#include<unistd.h>#include<cstring>#include<iostream>constchar*S......
  • c++ union
    在C++中,`union`是一种特殊的数据结构,它允许在同一内存空间中存储不同类型的数据。`union`允许您定义一个变量,但这个变量可以存储多种不同类型的值,而不是只能存储一种类型的值。在任何给定时间,`union`中只有一个成员可以有值,所有其他成员都将保持未定义的状态。`union`的声......
  • c++ true_type与false_type
    std::true_type和std::false_type实际上是类型别名是两个类型(类模板)注意区分true_type与false_type与true和false区别true_type,false_type代表类型true,false代表值nmsp1::FalseTypemyfunc1();//返回假这种含义nmsp1::TrueTypemyfunc2();//返回真这种含......
  • c++-----declval
    std::declval基本概念和常规实例std::decval–C++新标准中出现的函数模板,没有函数体(只有声明、没有实现),无法调用,一般用于与decltype,sizeof等关键字配合来进行类型推导、占用内存空间计算等查看源码: add_rvalue_reference:是C++标准库中的类模板,他的能力是给进一个类型,它......
  • C++:private继承
    平时我们使用类继承是这个画风:classchild:public::father{};表示子类child继承父类father,这里有个关键词"public",表示继承到的父类属性和方法为自己的public成员,这种情况下子类的对象或者说实例化是可以直接访问这些成员的 当改成classchild:private::father{};则......
  • c++踩方格-动态规划基础题
    有一个方格矩阵,矩阵边界在无穷远处。我们做如下假设:a、每走一步时,只能从当前方格移动一格,走到某个相邻的方格上;b、走过的格子立即塌陷无法再走第二次;c、只能向北、东、西三个方向走;请问:如果允许在方格矩阵上走n步,共有多少种不同的方案。2种走法只要有一步不一样,即被认为是不同......
  • C++类型转换
    一、整形提升整型提升是一种隐式类型转换,当涉及到小于int类型的整数(如char、short、bool等)时。整型提升的目的是确保所有的操作数在算术运算或比较操作中具有相同的类型,通常是int类型,如果int不能表示该值,则可能会提升到unsignedint或更大的整数类型。二、无符号数和带符号数进......
  • Effective C++:2.构造、析构、赋值函数
    几乎每个class都会有一个或者多个构造函数,一个析构函数,一个copyassignment函数,因此有必要加深理解1.条款05:了解C++默默编写并调用哪些函数如果你没有生成一下函数,那么C++会在需要的时候(被调用)帮你自动生成这些函数:default构造函数copy构造函数default析构函数copyassign......
  • 编程竞赛中 C/C++ I/O 的使用
    C的字符串读取scanf以空行为分割进行读取数据。get和fgets以\n为分割读取数据。读取输入直到遇到\n或\0才终止。C++读取字符串cin以空格为分割读取数据。getline默认以换行符为分割读取数据。在使用getline时,要注意处理多个\n连到一块的情况。当读取77\n\n77时,......