山东大学编译原理实验2(新)

题目概述

在本实验中,你需要依靠实验一中完成的词法分析器对输入进行预处理得到Token流,利用LR(1)方法进行语法分析并进行语法制导翻译生成符号表和四元式,并将其输出。该实验的输出对后续实验中的目标代码生成同样有着重要作用。为保证输出结果唯一,语法生成式和相应的制导翻译规则在后面给出。

程序输入

输入为一段c语言风格的程序,需要利用实验一的词法分析器作预处理。如果是一段正确的程序,则一定能被后文中所给出的文法推导产生。

使用文法

文法中出现的所有终结符

int double scanf printf if then while do , ; + - * / = == != < <= > >= ( ) { } ! && || id UINT UFLOAT
其中UINT,UFLOAT,id是在词法阶段识别完成的标识符,整数和浮点数常量。
这里不包含空字符和结束字符,可以根据自己的代码实现加入。

文法中出现的所有非终结符

PROG SUBPROG M N VARIABLES STATEMENT VARIABLE T ASSIGN SCANF PRINTF L
B EXPR ORITEM ANDITEM RELITEM NOITEM
ITEM FACTOR BORTERM BANDTERM PLUS_MINUS MUL_DIV REL SCANF_BEGIN PRINTF_BEGIN ID

注意区分ID(非终结符)和id(终结符)。

每个非终结符可能具有如下属性中的一个或多个:

quad,name,nextlist,truelist,falselist,type,width,op,place。

语法产生式和制导翻译规则

每个产生式后面的中括号斜体文字为其对应的制导翻译规则,在LR1分析法的规约步骤中,通过该规则帮助生成对应的四元式。

总程序部分

PROG -> SUBPROG {}

SUBPROG -> M VARIABLES STATEMENT

{backpatch(STATEMENT.nextlist,nxq);gen(End,-,-,-);}

M -> ^ {OFFSET=0}

N -> ^ {N.quad=nxq}

变量声明部分

VARIABLES -> VARIABLES VARIABLE ; {}

VARIABLES -> VARIABLE ; {}

T -> int {T.type=int;T.width=4;}

T -> double {T.type=double;T.width=8;}

ID -> id {ID.name=id}

VARIABLE ->T ID

{enter(ID.name,type=T.type,offset=OFFSET);OFFSET+=T.width;VARIABLE.type=T.type;VARIABLE.width=T.width}

VARIABLE -> VARIABLE_1 , ID

{enter(ID.name,type=VARIABLE_1.type,offset=OFFSET);OFFSET+=VARIABLE_1.width;VARIABLE.type=VARIABLE_1.type;VARIABLE.width=VARIABLE_1.width;}

语句部分(赋值、读写、if-then,do-while,复合语句

STATEMENT -> ASSIGN {STATEMENT.nextlist=mklist()}

STATEMENT -> SCANF
{STATEMENT.nextlist=mklist()}

STATEMENT -> PRINTF {STATEMENT.nextlist=mklist()}

STATEMENT -> ^ {STATEMENT.nextlist=mklist()}

STATEMENT -> { L ; } {STATEMENT.nextlist=L.nextlist}

STATEMENT -> while N_1 B do N_2 STATEMENT_1

{backpatch(STATEMENT_1.nextlist,N_1.quad);backpatch(B.truelist,N_2.quad);STATEMENT.nextlist=B.falselist;gen(j,-,-,N_1.quad)}

STATEMENT -> if B then N STATEMENT_1

{backpatch(B.truelist,N.quad),STATEMENT.nextlist=merge(B.falselist,STATEMENT_1.nextlist)}

ASSIGN -> ID = EXPR
{p=lookup(ID.name);gen(=,EXPR.place,-,p) }

L -> L_1 ; N STATEMENT {backpatch(L1.nextlist,N.quad),L.nextlist=STATEMENT.nextlist}

L -> STATEMENT {L.nextlist=STATEMENT.nextlist}

数值表达式部分

EXPR ->EXPR_1 || ORITEM

{EXPR.place=newtemp(int);EXPR.type=int;gen(||,EXPR_1.place,ORITEM.place,EXPR.place)}

EXPR -> ORITEM
{EXPR.place=ORITEM.place;EXPR.type=ORITEM.type}

ORITEM -> ORITEM_1 && ANDITEM

{ORITEM.place=newtemp(int);ORITEM.type=int;gen(&&,ORITEM_1.place,ANDITEM.place,ORITEM.place)}

ORITEM -> ANDITEM
{ORITEM.place=ANDITEM.place;ORITEM.type=ANDITEM.type}

ANDITEM -> NOITEM
{ANDITEM.place=NOITEM.place;ANDITEM.type=NOITEM.type;}

ANDITEM -> ! NOITEM

{ANDITEM=newtemp(int);ANDITEM.type=int;gen(!,NOITEM.place,-,ANDITEM.place)}

NOITEM -> NOITEM_1 REL RELITEM

{NOITEM.place=newtemp(int);NOITEM.type=int;gen(REL.op,NOITEM_1.place,RELITEM.place,NOITEM.place)}

NOITEM -> RELITEM {NOITEM.place=RELITEM.place;NOITEM.type=RELITEM.type}

RELITEM -> RELITEM_1 PLUS_MINUS ITEM

{RELITEM.place=newtemp(RELITEM_1.type);RELITEM.type=RELITEM_1.type;gen(PLUS_MINUS.op,RELITEM_1.place,ITEM.place,RELITEM.place)}

RELITEM -> ITEM {RELITEM.place=ITEM.place;RELITEM.type=ITEM.type}

ITEM -> FACTOR {ITEM.place=FACTOR.place;ITEM.type=FACTOR.type}

ITEM -> ITEM MUL_DIV FACTOR

{ITEM.place=newtemp(FACTOR.type);ITEM.type=FACTOR.type;gen(MUL_DIV.op,ITEM_1.place,FACTOR.place,ITEM.place)}

FACTOR -> ID {FACTOR.place=lookup(ID.name);FACTOR.type=lookup_type(ID.name)}

FACTOR -> UINT

{FACTOR.place=newtemp(int);FACTOR.type=int;gen(=,UINT,-,FACTOR.place)}

FACTOR -> UFLOAT

{FACTOR.place=newtemp(double);FACTOR.type=double;gen(=,UFLOAT,-,FACTOR.place)}

FACTOR -> ( EXPR ) {FACTOR.place=EXPR.place;FACTOR.type=EXPR.type}

FACTOR -> PLUS_MINUS FACTOR_1

{FACTOR.place=newtemp(FACTOR_1.type);FACTOR.type=FACTOR_1.type;gen(PLUS_MINUS.op,0,FACTOR_1.place,FACTOR.place)}

作为条件控制的表达式

B -> B_1 || N BORTERM

{backpatch(B_1.falselist,N.quad);B.truelist=merge(B_1.truelist,BORTERM.truelist);B.falselist=BORTERM.falselist}

B -> BORTERM
{B.truelist=BORTERM.truelist;B.falselist=BORTERM.falselist}

BORTERM -> BORTERM_1 && N
BANDTERM

{backpatch(BORTERM_1.truelist,N.quad);BORTERM.falselist=merge(BORTERM_1.falselist,BANDTERM.falselist;BORTERM.truelist=BANDTERM.truelist)}

BORTERM -> BANDTERM

{BORTERM.truelist=BANDTERM.truelist;BORTERM.falselist=BANDTERM.falselist}

BANDTERM -> ( B )

{BANDTERM.truelist=B.truelist;BANDTERM.falselist=B.falselist}

BANDTERM -> ! BANDTERM_1

{BANDTERM.truelist=BANDTERM_1.falselist;BANDTERM.falselist=BANDTERM_1.truelist}

BANDTERM -> BFACTOR_1 REL BFACTOR_2

{BANDTERM.truelist=mklist(nxq);BANDTERM.falselist=mklist(nxq+1);gen(j+REL.op,BFACTOR_1.place,BFACTOR_2.place,0);gen(j,-,-,0);}

BANDTERM -> BFACTOR

{BANDTERM.truelist=mklist(nxq);BANDTERM.falselist=mklist(nxq+1);gen(jnz,BFACTOR.place,-,0);gen(j,-,-,0)}

BFACTOR -> UINT

{BFACTOR.place=newtemp(int);BFACTOR.type=int;gen(=,UINT,-,FACTOR.place)}

BFACTOR -> UFLOAT

{BFACTOR.place=newtemp(double);BFACTOR.type=double;gen(=,UFLOAT,-,BFACTOR.place)}

BFACTOR -> ID
{BFACTOR.place=lookup(ID.name);BFACTOR.type=lookup_type(ID.name)}

运算符

PLUS_MINUS -> + {PLUS_MINUS.op=‘+’}

PLUS_MINUS -> - { PLUS_MINUS.op=‘-’}

MUL_DIV -> * {MUL_DIV.op=‘*’}

MUL_DIV -> / { MUL_DIV.op=‘/’}

REL -> == {REL.op=‘==’}

REL -> != { REL.op=‘!=’}}

REL -> < { REL.op=‘<’}}

REL -> <= { REL.op=‘<=’}

REL -> > { REL.op=‘>’}}

REL -> >= { REL.op=‘>=’}

读写语句

SCANF -> SCANF_BEGIN ) {}

SCANF_BEGIN -> SCANF_BEGIN , ID {p=lookup(ID.name);gen(R,-,-,p)}

SCANF_BEGIN -> scanf ( ID {p=lookup(ID.name);gen(R,-,-,p)}

PRINTF -> PRINTF_BEGIN ) {}

PRINTF_BEGIN -> printf ( ID {p=lookup(ID.name);gen(W,-,-,p)}

PRINTF_BEGIN -> PRINTF_BEGIN , ID {p=lookup(ID.name);gen(W,-,-,p)}

补充说明:

1.假定UINT和id,UFLOAT的识别已经在词法分析步骤中完成,故语法分析中认为其是终结符,但需注意大写的ID为非终结符。
2. 实验二中之考虑简单的声明语句,不涉及带作用域的过程声明和调用,因此只使用一张全局符号表。
3.翻译规则中的lookup(name)方法可以理解为返回了指出变量在符号表位置的指针用于给非终结符的place属性赋值,例如若符号表中按顺序有变量A,B,x,y。
则lookup(‘A’)=‘TB0’,lookup(‘B’)=‘TB1’,lookup(‘x’)=‘TB2’,lookup(‘y’)=‘TB3’。
4.翻译规则中的lookup_type(name)方法则根据输入的变量名,查找并返回符号表中对应变量的类型。
5. 对于newtemp(type)方法,type为类型参数,可以为int,double。同样可以理解为返回一个指针字符川,从’T0_i’,‘T1_d’,‘T2_i’…序号逐渐递增,下划线后的字母表示数据类型int或double,以便实验三生成x86目标代码。
6.enter(name,type,offset)方法为向符号便中添加名称为name,类型为type,偏移量为offset的变量,不可与符号表中已有变量重名。符号表中的变量按照插入的先后顺序从前往后排列。
7.符号表每一行包含如下属性,name:变量或常量名,type:int/double ,value: 初始声明时为null,offset:全局偏移量。在计算偏移量时,一个int类型变量占4个字节,double类型变量占8个字节。
8. ^ 表示空字符。

  1. 首条指令起始标号nxq=0。

语法错误类型

实验二中的输入不会出现词法错误,但有可能出现语法错误,此时需要你输出“Syntax
Error”。

语法错误包含如下几种类型:

1.程序中使用未定义的变量标识符,或是使用虽然定义但未赋值的变量参与表达式右值的计算。

2.重复定义同名称变量。

3.LR(1)分析中出现错误,即输入程序不满足文法要求。

算符优先级从高到低排序:

1.*, / ,表正负数而非二元运算符时的+和-

2.+ ,-

3.关系运算符:== | != |
< | <= | > | >=

4.!

5.&&

6.||

当表达式用于条件和循环语句控制时,作了一定的简化和限制,包括不使用算术运算符,括号只针对已经产生truelist和falselist属性的布尔表达式使用。且所有二元运算符均为左结合。

后面给出的文法已经考虑到了算符优先级、结合性和二义文法的消除,本节只用作提醒。

四元式

生成的四元式根据第一个参数算符的不同分为如下几类:

(=,lhs/UINT/UFLOAT,-,dest): 赋值语句,其参数可能为(临时)变量地址,也可能为整数/浮点数字面值,对于UFLOAT,其在四元式中的输出保留六位小数(即std::tostring(double value)函数的默认保留位数)。

(j,-,-,dest) :无条件跳转。

(jnz,lhs,-,dest): 非零时跳转。

(jθ,lhs,rhs,dest): 关系运算符条件跳转,θ可以为== | != | < | <= | > | >= ,关系运算为真时跳转 ,lhs和rhs必须为同一种类型变量或临时变量。

(op,lhs,rhs,dest): 用于计算,op可以为 + | - | * | / 或者二元关系运算符,lhs和rhs可以为变量或临时变量的地址或常数 ,其中lhs和rhs必须为同一种类型变量或临时变量。对于算出运算,dest类型必须与lhr和rhs相同。对于关系运算,dest类型必须未int。

(&&,lhs,rhs,dest): 与运算,lhs,rhs和dest类型必须为int,此时定义0为True,非0为False。

(||,lhs,rhs,dest) :或运算,同上

(!,lhs,-,dest) :非运算,同上

(R,-,-,dest) :输入语句,dest为待读入的变量。

(W,-,-,dest) :输出写语句,dest为待输出的变量。

(End,-,-,-) 整个程序结束,退出。

输出要求

假如LR1分析成功

1.输出符号表:

第一行输出符号表长度(变量个数)

接着符号表中每个变量输出一行,属性中间以空格分隔:

name type value
offset

对于type属性,若为int则输出0,对于value属性,由于该语言设计中不在编译时进行赋值计算,故统一输出为字符串null。

2.下一行输出所使用的临时变量总个数,即调用newtemp方法的总次数。

3…紧接着下一行开始输出序号和四元式

第一行输出生成四元式总个数

接着每行输出“序号: 对应四元式“。冒号和四元式之间空一格,四元式内部参数用逗号分隔,无空格。

四元式中出现浮点数字面值的,保留六位小数(即std::to_string(double val)的默认输出格式)。

假如分析过程中发现任何语法错误

输出一行:Syntax Error。

输入输出样例

样例1

输入:

int a,b,c;
double d,e,f;
int j;
{
    d=2.4;
    e=-3.6*5;
    f=!(d*e)/((d+e)<=d);
    a=4;
    b=+3;
    c=111;
    while a>=0 do
        {
            a=a-1;
            d=d*e;
            while (b!=0 && !c>0)|| !a>0 do
                {
                    b=b-1 <c || a==0;
                    printf(b,d);
                };
            if a==1 then
                printf(c,a,b);
        };
}

输出:

7
a 0 null 0
b 0 null 4
c 0 null 8
d 1 null 12
e 1 null 20
f 1 null 28
j 0 null 36
28
55
0: (=,2.400000,-,T0_d)
1: (=,T0_d,-,TB3)
2: (=,3.600000,-,T1_d)
3: (-,0,T1_d,T2_d)
4: (=,5,-,T3_i)
5: (*,T2_d,T3_i,T4_i)
6: (=,T4_i,-,TB4)
7: (*,TB3,TB4,T5_d)
8: (+,TB3,TB4,T6_d)
9: (<=,T6_d,TB3,T7_i)
10: (/,T5_d,T7_i,T8_i)
11: (!,T8_i,-,T9_i)
12: (=,T9_i,-,TB5)
13: (=,4,-,T10_i)
14: (=,T10_i,-,TB0)
15: (=,3,-,T11_i)
16: (+,0,T11_i,T12_i)
17: (=,T12_i,-,TB1)
18: (=,111,-,T13_i)
19: (=,T13_i,-,TB2)
20: (=,0,-,T14_i)
21: (j>=,TB0,T14_i,23)
22: (j,-,-,54)
23: (=,1,-,T15_i)
24: (-,TB0,T15_i,T16_i)
25: (=,T16_i,-,TB0)
26: (*,TB3,TB4,T17_d)
27: (=,T17_d,-,TB3)
28: (=,0,-,T18_i)
29: (j!=,TB1,T18_i,31)
30: (j,-,-,34)
31: (=,0,-,T19_i)
32: (j>,TB2,T19_i,34)
33: (j,-,-,37)
34: (=,0,-,T20_i)
35: (j>,TB0,T20_i,47)
36: (j,-,-,37)
37: (=,1,-,T21_i)
38: (-,TB1,T21_i,T22_i)
39: (<,T22_i,TB2,T23_i)
40: (=,0,-,T24_i)
41: (==,TB0,T24_i,T25_i)
42: (||,T23_i,T25_i,T26_i)
43: (=,T26_i,-,TB1)
44: (W,-,-,TB1)
45: (W,-,-,TB3)
46: (j,-,-,28)
47: (=,1,-,T27_i)
48: (j==,TB0,T27_i,50)
49: (j,-,-,20)
50: (W,-,-,TB2)
51: (W,-,-,TB0)
52: (W,-,-,TB1)
53: (j,-,-,20)
54: (End,-,-,-)

样例2

下面是语法分析出错误时的输出,错误原因是使用未声明变量。

输入:

int a,b;
{
a=0;
b=1;
c=2;
}

输出:

Syntax Error

样例3

输入:

int a,b,c;

{
    scanf(a);
    b=0;
    while a>=0 do
        {
            a=a-1;
            c=a-(a/2)*2;
            if c!=0 then
                b=b+a;
        };
    printf(b);
}

输出

3
a 0 null 0
b 0 null 4
c 0 null 8
11
23
0: (R,-,-,TB0)
1: (=,0,-,T0_i)
2: (=,T0_i,-,TB1)
3: (=,0,-,T1_i)
4: (j>=,TB0,T1_i,6)
5: (j,-,-,21)
6: (=,1,-,T2_i)
7: (-,TB0,T2_i,T3_i)
8: (=,T3_i,-,TB0)
9: (=,2,-,T4_i)
10: (/,TB0,T4_i,T5_i)
11: (=,2,-,T6_i)
12: (*,T5_i,T6_i,T7_i)
13: (-,TB0,T7_i,T8_i)
14: (=,T8_i,-,TB2)
15: (=,0,-,T9_i)
16: (j!=,TB2,T9_i,18)
17: (j,-,-,3)
18: (+,TB1,TB0,T10_i)
19: (=,T10_i,-,TB1)
20: (j,-,-,3)
21: (W,-,-,TB1)
22: (End,-,-,-)

样例4

输入:

int a,b,c,d,e,f;
{
    a=0;
    b=1;
    c=2;
    d=0;
    e=0;
    f=0;
    if !(!(a && d || (e<5)))  then
        d=b+c;
    if ! (a<=b) then
        e=b*c;

    printf(d,e,f);
}

输出:

6
a 0 null 0
b 0 null 4
c 0 null 8
d 0 null 12
e 0 null 16
f 0 null 20
9
29
0: (=,0,-,T0_i)
1: (=,T0_i,-,TB0)
2: (=,1,-,T1_i)
3: (=,T1_i,-,TB1)
4: (=,2,-,T2_i)
5: (=,T2_i,-,TB2)
6: (=,0,-,T3_i)
7: (=,T3_i,-,TB3)
8: (=,0,-,T4_i)
9: (=,T4_i,-,TB4)
10: (=,0,-,T5_i)
11: (=,T5_i,-,TB5)
12: (jnz,TB0,-,14)
13: (j,-,-,16)
14: (jnz,TB3,-,19)
15: (j,-,-,16)
16: (=,5,-,T6_i)
17: (j<,TB4,T6_i,19)
18: (j,-,-,21)
19: (+,TB1,TB2,T7_i)
20: (=,T7_i,-,TB3)
21: (j<=,TB0,TB1,25)
22: (j,-,-,23)
23: (*,TB1,TB2,T8_i)
24: (=,T8_i,-,TB4)
25: (W,-,-,TB3)
26: (W,-,-,TB4)
27: (W,-,-,TB5)
28: (End,-,-,-)

样例5

输入:

int a,b,c;
double x,y;
int d,e;
double z;

输出:

8
a 0 null 0
b 0 null 4
c 0 null 8
x 1 null 12
y 1 null 20
d 0 null 28
e 0 null 32
z 1 null 36
0
1
0: (End,-,-,-)

代码实现思路

建议同学们在完成实验二时,分为如下几步:

1.实现针对任意给定文法的LR1分析表的生成模块(根据指定文法生成LR1表的代码网上有不少,可以参考借鉴),文法可以以资源文件的形式存储供该模块读取。

2.实现基于1中生成的LR1分析表和词法分析得到的token序列进行LR1分析的分析栈。

前两步中可以先不考虑四元式的生成,首先的目标是确保源代码输入可以正确归约至ACC状态。

3.按照题目所给的语法规则,添加归约生成四元式的功能。

在调试1,2,3模块时,可以先使用简单程序调试文法中的一小部分,确定代码编写思路正确后再测试全部的完整文法。

上述思路供大家参考,也欢迎同学们按照自己的想法完成该实验。

///*
//    wirte by @lyz
//    2024.4.26
//    编译原理实验1:词法分析器
//*/
///*
//    wirte by @lyz
//    2024.6.5
//    编译原理实验2:语法分析器
//*/
//
#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")
//
#include <bits/stdc++.h>

//
//#define LOCAL
//
int OK = 0;
constexpr int N = 510;
std::map<std::string, std::string> mp{
        {"int",    "INTSYM"},
        {"double", "DOUBLESYM"},
        {"scanf",  "SCANFSYM"},
        {"printf", "PRINTFSYM"},
        {"if",     "IFSYM"},
        {"then",   "THENSYM"},
        {"while",  "WHILESYM"},
        {"do",     "DOSYM"}};
std::map<std::string, std::string> mp1{
        {"=",  "AO"},
        {"==", "RO"},
        {">",  "RO"},
        {">=", "RO"},
        {"<",  "RO"},
        {"<=", "RO"},
        {"||", "LO"},
        {"&&", "LO"},
        {"!",  "LO"},
        {"!=", "RO"},
        {"+",  "PLUS"},
        {"-",  "MINUS"},
        {"*",  "TIMES"},
        {"/",  "DIVISION"},
        {",",  "COMMA"},
        {"(",  "BRACE"},
        {")",  "BRACE"},
        {"{",  "BRACE"},
        {"}",  "BRACE"},
        {";",  "SEMICOLON"}};
// 非终结符
std::map<std::string, int> Non_terminal = {
        {"PROG",         1},
        {"SUBPROG",      1},
        {"M",            1},
        {"N",            1},
        {"VARIABLES",    1},
        {"STATEMENT",    1},
        {"VARIABLE",     1},
        {"T",            1},
        {"ASSIGN",       1},
        {"SCANF",        1},
        {"PRINTF",       1},
        {"L",            1},
        {"B",            1},
        {"EXPR",         1},
        {"ORITEM",       1},
        {"ANDITEM",      1},
        {"RELITEM",      1},
        {"NOITEM",       1},
        {"ITEM",         1},
        {"FACTOR",       1},
        {"BORTERM",      1},
        {"BANDTERM",     1},
        {"PLUS_MINUS",   1},
        {"MUL_DIV",      1},
        {"REL",          1},
        {"SCANF_BEGIN",  1},
        {"PRINTF_BEGIN", 1},
        {"ID",           1}
};

// 终结符
std::map<std::string, int> terminal = {
        {"int",    1},
        {"double", 1},
        {"scanf",  1},
        {"printf", 1},
        {"if",     1},
        {"then",   1},
        {"while",  1},
        {"do",     1},
        {",",      1},
        {";",      1},
        {"+",      1},
        {"-",      1},
        {"*",      1},
        {"/",      1},
        {"=",      1},
        {"==",     1},
        {"!=",     1},
        {"<",      1},
        {"<=",     1},
        {">",      1},
        {">=",     1},
        {"(",      1},
        {")",      1},
        {"{",      1},
        {"}",      1},
        {"!",      1},
        {"&&",     1},
        {"||",     1},
        {"id",     1},
        {"UINT",   1},
        {"UFLOAT", 1},
        {"^",      1},
        {"#",      1}
};
std::map<std::string, int> typr_to_int = {{"int",    0},
                                          {"double", 1}};
std::vector<std::string> language = {
        "PROG -> SUBPROG",
        "SUBPROG -> M VARIABLES  STATEMENT",
        "M -> ^",
        "N -> ^",
        "VARIABLES -> VARIABLES VARIABLE ;",
        "VARIABLES -> VARIABLE ;",
        "T -> int",
        "T -> double",
        "ID -> id",
        "VARIABLE -> T ID",
        "VARIABLE -> VARIABLE , ID",
        "STATEMENT -> ASSIGN",
        "STATEMENT -> SCANF",
        "STATEMENT -> PRINTF",
        "STATEMENT -> ^",
        "STATEMENT -> { L ; }",
        "STATEMENT -> while N B do N STATEMENT",
        "STATEMENT -> if B then N STATEMENT",
        "ASSIGN -> ID = EXPR",
        "L -> L ; N STATEMENT",
        "L -> STATEMENT",
        "EXPR -> EXPR || ORITEM",
        "EXPR -> ORITEM",
        "ORITEM -> ORITEM && ANDITEM",
        "ORITEM -> ANDITEM",
        "ANDITEM -> NOITEM",
        "ANDITEM -> ! NOITEM",
        "NOITEM -> NOITEM REL RELITEM",
        "NOITEM -> RELITEM",
        "RELITEM -> RELITEM PLUS_MINUS ITEM",
        "RELITEM -> ITEM",
        "ITEM -> FACTOR",
        "ITEM -> ITEM MUL_DIV FACTOR",
        "FACTOR -> ID",
        "FACTOR -> UINT",
        "FACTOR -> UFLOAT",
        "FACTOR -> ( EXPR )",
        "FACTOR -> PLUS_MINUS FACTOR",
        "B -> B || N BORTERM",
        "B -> BORTERM",
        "BORTERM -> BORTERM && N BANDTERM",
        "BORTERM -> BANDTERM",
        "BANDTERM -> ( B )",
        "BANDTERM ->  ! BANDTERM",
        "BANDTERM -> BFACTOR REL BFACTOR",
        "BANDTERM -> BFACTOR",
        "BFACTOR -> UINT",
        "BFACTOR -> UFLOAT",
        "BFACTOR -> ID",
        "PLUS_MINUS -> +",
        "PLUS_MINUS -> -",
        "MUL_DIV -> *",
        "MUL_DIV -> /",
        "REL -> ==",
        "REL -> !=",
        "REL -> <",
        "REL -> <=",
        "REL -> >",
        "REL -> >=",
        "SCANF -> SCANF_BEGIN )",
        "SCANF_BEGIN -> SCANF_BEGIN , ID",
        "SCANF_BEGIN -> scanf ( ID",
        "PRINTF -> PRINTF_BEGIN )",
        "PRINTF_BEGIN -> printf ( ID",
        "PRINTF_BEGIN -> PRINTF_BEGIN , ID"
};

struct Expression {
    std::string T;
    std::vector<std::string> S;
    int pos = 0;
    int idx = 0;
    std::set<std::string> suffix;

    Expression() = default;

    explicit Expression(std::string T, const std::vector<std::string> &S, int pos,
                        int idx, const std::set<std::string> &suffix)
            : T(std::move(T)), S(S), pos(pos), idx(idx), suffix(suffix) {}

    friend std::ostream &operator<<(std::ostream &os, const Expression &expr) {
        os << "T: " << expr.T << "\n";
        os << "S:";
        for (const auto &str: expr.S) {
            os << " " << str;
        }
        os << "\n";
        os << "pos: " << expr.pos << "\n";
        os << "idx: " << expr.idx << "\n";
        os << "suffix:";
        for (const auto &suf: expr.suffix) {
            os << " " << suf;
        }
        os << "\n";
        return os;
    }
};

// operator< 重载
bool operator<(const Expression &lhs, const Expression &rhs) {
    return std::tie(lhs.T, lhs.S, lhs.pos, lhs.idx, lhs.suffix) <
           std::tie(rhs.T, rhs.S, rhs.pos, rhs.idx, rhs.suffix);
}

// operator== 重载
bool operator==(const Expression &lhs, const Expression &rhs) {
    return std::tie(lhs.T, lhs.S, lhs.pos, lhs.idx, lhs.suffix) ==
           std::tie(rhs.T, rhs.S, rhs.pos, rhs.idx, rhs.suffix);
}

std::map<std::string, int> symbol2id;
std::vector<std::vector<int>> GoTo_table(N, std::vector<int>(N));
std::map<std::string, std::set<std::string>> firstSet;
std::map<std::string, std::vector<std::pair<std::vector<std::string>, int>>> expression; // 表达式
std::vector<std::pair<std::string, std::vector<std::string>>> expression2; // 表达式
std::vector<std::set<Expression>> set_family;

std::vector<std::string> lexer(std::string str) {
    std::vector<std::string> ans;
    std::string s;

    // 去注释
    while (str.find("/*") != -1) {
        int pos = str.find("/*");
        int pos1 = str.find("*/");
        if (pos1 == -1) {
            str.erase(pos);
        }
        str.erase(pos, pos1 - pos + 2);
    }
    while (str.find("//") != -1) {
        int pos = str.find("//");
        int pos1 = str.find("\n", pos);
        str.erase(pos, pos1 - pos + 1);
    }

    // 加空格
    int n = str.size();
    for (int i = 0; i < n; i++) {
        if (i + 2 <= n && mp1.count(str.substr(i, 2))) {
            s.push_back(' ');
            s.push_back(str[i]);
            s.push_back(str[i + 1]);
            s.push_back(' ');
            i += 1;
        } else if (i + 1 <= n && mp1.count(str.substr(i, 1))) {
            s.push_back(' ');
            s.push_back(str[i]);
            s.push_back(' ');
        } else {
            s.push_back(str[i]);
        }
    }
    str = s;
    n = str.size();
    // 分词//
    std::string token;
    for (int i = 0; i < n; i++) {
        if (str[i] == ' ' || str[i] == '\n' || str[i] == '\t') {
            if (!token.empty()) {
                if (mp.count(token)) {
                    ans.push_back(token + ' ' + mp[token] + '\n');
                } else {
                    int idx = 0;
                    bool alp = 0;
                    bool dig = 0;
                    std::string h;
                    ///
                    while (idx < token.size()) {
                        while (isalpha(token[idx])) {
                            h += token[idx++];
                            alp = true;
                        }
                        while (isdigit(token[idx]) && alp) {
                            h += token[idx++];
                        }
                        if (!h.empty()) {
                            ans.push_back(h + " IDENT\n");
                        }
                        h.clear();
                        /
                        while (isdigit(token[idx]) || token[idx] == '.') {
                            h += token[idx++];
                            dig = 1;
                        }
                        if (dig && std::count(h.begin(), h.end(), '.') >= 2) {
                            std::cout << "Malformed number: More than one decimal point in a "
                                         "floating point number.\n";
                            return {};
                        }
                        if (dig && (h[0] == '.' || h.back() == '.')) {
                            std::cout << "Malformed number: Decimal point at the beginning "
                                         "or end of a floating point number.\n";
                            return {};
                        }
                        if (dig && h[0] == '0' && h.size() > 1) {
                            bool isok = 1;
                            if (h.find('.') != -1) {
                                for (int j = 0; j < h.size(); j++) {
                                    if (h[j] == '.') {
                                        break;
                                    }
                                    if (h[j] != '0') {
                                        isok = 0;
                                        break;
                                    }
                                }
                            } else {
                                isok = 0;
                            }
                            if (!isok) {
                                std::cout << "Malformed number: Leading zeros in an integer.\n";
                                return {};
                            }
                        }
                        if (dig && std::count(h.begin(), h.end(), '.') == 0) {
                            ans.push_back(h + ' ' + "INT\n");
                        } else if (dig) {
                            ans.push_back(h + " DOUBLE\n");
                        }
                        /
                        if (idx + 2 <= token.size() && mp1.count(token.substr(idx, 2))) {
                            ans.push_back(token.substr(idx, 2) + " " +
                                          mp1[token.substr(idx, 2)] + "\n");
                            idx += 2;
                        } else if (mp1.count(token.substr(idx, 1))) {
                            ans.push_back(token.substr(idx, 1) + " " +
                                          mp1[token.substr(idx, 1)] + "\n");
                            idx += 1;
                        }

                        if (idx < token.size() &&
                            (!isdigit(token[idx]) && !isalpha(token[idx])) &&
                            (dig == 0 && alp == 0)) {
                            std::cout << "Unrecognizable characters.\n";
                            return {};
                        }
                    }
                }
            }

            token = "";
        } else {
            token += str[i];
        }
    }

    return ans;
}

std::set<Expression> get_closure(const std::set<Expression> &cur) {
    auto pre = cur, result = cur;
    bool ok = false;
    while (!ok) {
        ok = true;
        size_t sz = result.size();
        int cnt{};
        for (const auto &I: result) {
            if (I.pos >= I.S.size()) {
                continue;
            }
            std::string cur_str = I.S[I.pos];
            if (!terminal[cur_str]) {
                for (const auto &X: expression[cur_str]) {
                    auto x = X.first;
                    auto y = X.second;
                    if (I.pos == I.S.size() - 1) {
                        pre.emplace(cur_str, x, 0, y, I.suffix);
                    } else {
                        std::string nxt_str = I.S[I.pos + 1];
                        if (terminal[nxt_str]) {
                            pre.emplace(cur_str, x, 0, y, firstSet[nxt_str]);
                        } else {
                            std::set<std::string> suffix;
                            bool is_empty{true};
                            int i = I.pos + 1;
                            while (is_empty && i < I.S.size()) {
                                is_empty = false;
                                if (terminal[I.S[i]]) {
                                    suffix.emplace(I.S[i]);
                                } else {
                                    for (const std::string &w: firstSet[I.S[i]]) {
                                        if (w == "^") {
                                            is_empty = true;
                                        } else {
                                            suffix.emplace(w);
                                        }
                                    }
                                }
                                if (is_empty) {
                                    ++i;
                                }
                            }
                            if (is_empty) {
                                for (const std::string &w: I.suffix) {
                                    suffix.emplace(w);
                                }
                            }
                            pre.emplace(cur_str, x, 0, y, suffix);

                        }
                    }
                }
            }
        }
        for (auto I: pre) {
            auto i = std::find_if(result.begin(), result.end(), [&](const Expression &e) {
                return e.idx == I.idx && e.pos == I.pos;
            });
            if (i != result.end()) {
                for (const auto &w: i->suffix) {
                    I.suffix.emplace(w);
                }
                result.erase(i);
            }
            result.emplace(I.T, I.S, I.pos, I.idx, I.suffix);
        }
        size_t cur_sz = result.size();
        if (cur_sz > sz) {
            ok = false;
        }
    }
    return result;
};


//std::pair<std::vector<std::set<Expression>>, std::vector<std::string>> get_Items(int idx) {
//    std::set<std::string> symbols_to_process;
//    std::vector<std::set<Expression>> item_sets;
//    std::vector<std::string> symbols;
//
     查找需要处理的符号
//    for (auto I: set_family[idx]) {
//        if (I.pos < I.S.size() && I.S[I.pos] != "^") {
//            symbols_to_process.insert(I.S[I.pos]);
//        }
//    }
//
//    // 为每个符号创建项目集
//    for (const auto &symbol: symbols_to_process) {
//        std::set<Expression> tmp_set;
//        for (const auto &I: set_family[idx]) {
//            if (I.pos < I.S.size() && I.S[I.pos] == symbol) {
//                tmp_set.emplace(I.T, I.S, I.pos + 1, I.idx, I.suffix);
//            }
//        }
//        item_sets.emplace_back(std::move(tmp_set));
//        symbols.emplace_back(symbol);
//    }
//
//    // 返回项目集和符号
//    return std::make_pair(std::move(item_sets), std::move(symbols));
//}




//void get_LR_table() {
//    int cn = 0;
//    std::set<std::string> suffix;
//    suffix.insert("#");
//    std::string s = "PROG";
//    Expression e(s, expression[s][0].first, 0, expression[s][0].second, suffix);
//    std::set<Expression> st;
//    st.insert(e);
//    auto e1 = get_closure(st);
//    set_family.emplace_back(e1);
//
//
//    for (int i = 0; i < set_family.size(); i++) {
//        auto [sets, sets_words] = get_Items(i);
//        // std::cout << set_family.size() << "\n";
//
//        int cnt{};
//        for (const auto &x: sets) {
//
//            auto do_word = sets_words[cnt++];
//
//            auto nowset = get_closure(x);
//            auto it = std::find(set_family.begin(), set_family.end(), nowset);
//            size_t idx{};
//
//            if (it == set_family.end()) {
//                set_family.emplace_back(nowset);
//                idx = set_family.size() - 1;
//            }
//            GoTo_table[i][symbol2id[do_word]] = idx;
//        }
//    }
//    size_t i{};
//    for (const auto &x: set_family) {
//        for (const auto &item : x) {
//            const auto &T = item.T;
//            const auto &S = item.S;
//            const auto &pos = item.pos;
//            const auto &idx = item.idx;
//            const auto &Suffix = item.suffix;
//            // 在这里使用 T、S、pos、idx 和 Suffix
//            if (pos >= S.size() || S[0] == "^") {
//                for (const auto &y: Suffix) {
//                    GoTo_table[i][symbol2id[y]] = -idx;
//                }
//            }
//        }
//        i++;
//    }
//};

// ---------------------------------------------------------------------------
namespace data_structure {

    struct QuadTuple {
        std::string operation;
        std::string argument1;
        std::string argument2;
        std::string destination;
        int Xfour = -1;

        QuadTuple(std::string op, std::string arg1,
                  std::string arg2, std::string dest)
                : operation(std::move(op)), argument1(std::move(arg1)),
                  argument2(std::move(arg2)), destination(std::move(dest)) {}

        QuadTuple() = default;
    };

    struct Symbol {
        std::string name;
        std::string type;
        int offset{};

        Symbol(std::string n, std::string t, int off)
                : name(std::move(n)), type(std::move(t)), offset(off) {}

        Symbol() = default;
    };

    struct attribute  // 属性
    {
        int quad{};
        int nextlist{};
        int truelist{};
        int falselist{};
        int width{};
        std::string name;
        std::string type;
        std::string op;
        std::string place;  //
    };
}
std::stack<data_structure::attribute> Stack4as;
std::vector<data_structure::Symbol> symbolTable;
std::stack<int> Stack4State;
std::stack<std::string> Stack4symbol;
std::vector<data_structure::QuadTuple> quads;
std::vector<int> tempTable_new;


std::vector<std::string> parser(std::vector<std::string> &res) {
    auto init = [&]() -> void {
        int cnt{};
        for (const auto &[x, _]: Non_terminal) {
            symbol2id[x] = cnt++;
        }
        for (const auto &[x, _]: terminal) {
            symbol2id[x] = cnt++;
        }
        assert(symbol2id.size() == terminal.size() + Non_terminal.size());
    };
    init();
    // ---------------------------------------------------------------------------
    std::vector<std::string> tmp = language;
    std::string str;
//    std::ifstream Cin(R"(C:\Users\LYZ\Desktop\untitled1\expression.txt)");
//    while (std::getline(Cin, str)) {
//        tmp.emplace_back(str);
//    }
//    Cin.close();
    // ---------------------------------------------------------------------------
    auto parsers = [&] {
        int cnt{1};
        for (const auto &x: tmp) {
            std::stringstream S(x);
            std::string K, _;
            std::vector<std::string> h;
            S >> K, S >> _;
            while (S >> str) {
                h.emplace_back(str);
            }
            //            expression[K].push_back(h);
            expression[K].emplace_back(h, cnt++);
            expression2.emplace_back(K, h);
        }
        return;
    };
    parsers();
    tmp.clear(), str.clear();
    // ---------------------------------------------------------------------------
    auto get_first_set = [&]() -> void {
        for (const auto &[x, _]: terminal) {
            firstSet[x].emplace(x);
        }

        int ok = 0;
        while (!ok) {
            ok = 1;
            for (const auto &[x, y]: expression) {
                auto precnt = firstSet[x].size();
                size_t curcnt{};
                for (const auto &[s, _]: y) {
                    bool is_empty = true;
                    int i;
                    for (i = 0; i < s.size() && is_empty; i++) {
                        is_empty = false;
                        for (const auto &xx: firstSet[s[i]]) {
                            if (xx == "^") {
                                is_empty = true;
                            } else {
                                tmp.push_back(xx);
                            }
                        }
                    }
                    if (is_empty && i >= s.size()) {
                        tmp.emplace_back("^");
                    }
                    for (const auto &xx: tmp) {
                        firstSet[x].insert(xx);
                    }
                    tmp.clear();
                }
                curcnt = firstSet[x].size();
                if (precnt < curcnt) {
                    ok = 0;
                }
            }
        }
    };
    get_first_set();
    // ---------------------------------------------------------------------------
    auto get_Items = [&](int idx) -> std::pair<std::vector<std::set<Expression>>,
            std::vector<std::string>> {
        std::set<std::string> symbols_to_process;
        std::vector<std::set<Expression>> item_sets;
        std::vector<std::string> symbols;

//     查找需要处理的符号
        for (auto I: set_family[idx]) {
            if (I.pos < I.S.size() && I.S[I.pos] != "^") {
                symbols_to_process.insert(I.S[I.pos]);
            }
        }

        // 为每个符号创建项目集
        for (const auto &symbol: symbols_to_process) {
            std::set<Expression> tmp_set;
            for (const auto &I: set_family[idx]) {
                if (I.pos < I.S.size() && I.S[I.pos] == symbol) {
                    tmp_set.emplace(I.T, I.S, I.pos + 1, I.idx, I.suffix);
                }
            }
            item_sets.emplace_back(std::move(tmp_set));
            symbols.emplace_back(symbol);
        }

        // 返回项目集和符号
        return std::make_pair(std::move(item_sets), std::move(symbols));
    };
    auto get_LR_table = [&]() -> void {
        int cn = 0;
        std::set<std::string> suffix;
        suffix.insert("#");
        std::string s = "PROG";
        Expression e(s, expression[s][0].first, 0, expression[s][0].second, suffix);
        std::set<Expression> st;
        st.insert(e);
        auto e1 = get_closure(st);
        set_family.emplace_back(e1);

        int CN{};
        for (int i = 0; i < set_family.size(); i++) {
            auto [sets, sets_words] = get_Items(i);
            // std::cout << set_family.size() << "\n";

            int cnt{};
            for (const auto &x: sets) {

                auto do_word = sets_words[cnt++];

                auto nowset = get_closure(x);
                auto it = std::find(set_family.begin(), set_family.end(), nowset);
                size_t idx{};

                if (it == set_family.end()) {
                    set_family.emplace_back(nowset);
                    idx = set_family.size() - 1;
                } else {
                    idx = it - set_family.begin();
                }
                GoTo_table[i][symbol2id[do_word]] = idx;
                CN++;
            }
        }
        size_t i{};
        for (const auto &x: set_family) {
            for (const auto &I: x) {
                if (I.pos >= I.S.size() || I.S[0] == "^") {
                    for (const auto &y: I.suffix) {
                        GoTo_table[i][symbol2id[y]] = -I.idx;
                    }
                }
            }
            i++;
        }
    };
    get_LR_table();


    std::vector<std::pair<std::string, std::string>> temp(res.size());
    for (size_t i = 0; i < res.size(); i++) {
        std::stringstream S(res[i]);
        S >> temp[i].first;
        S >> temp[i].second;
    }

    temp.emplace_back("#", "lyz");
    Stack4State.push(0);
    Stack4symbol.emplace("#");
    int offset{};
    int nxt{};
    auto reduce = [&](int idx) {
        data_structure::attribute attribute1{}, attribute2{}, attribute3{}, attribute4{}, attribute5{}, atr_d{};
        data_structure::QuadTuple quad1{};
        data_structure::Symbol symbol1;


        auto case2 = [&]() {
            attribute1 = Stack4as.top();
            for (int i = 0; i < 3; i++) Stack4as.pop();
            quad1 = data_structure::QuadTuple("End", "-", "-", "-");
            quads.push_back(quad1);
            nxt++;
            attribute2.name = "SUBPROG";
            Stack4as.push(attribute2);
        };
        auto case11 = [&]() {
            attribute1 = Stack4as.top();  // ID
            Stack4as.pop();
            attribute2 = Stack4as.top();  // T
            Stack4as.pop();
            symbol1 = data_structure::Symbol(attribute1.name, attribute2.type, offset);

            bool ok = 0;
            for (auto &i: symbolTable) {
                if (symbol1.name == i.name) {
                    ok = 1;
                    break;
                }
            }
            if (ok) {
                std::cout << "Syntax Error\n";  // 重名
                exit(0);
            }
            symbolTable.push_back(symbol1);
            offset += attribute2.width;
            attribute3.type = attribute2.type;
            attribute3.width = attribute2.width;
            Stack4as.push(attribute3);
        };

        auto backpatch = [&](int i, int t) {
            while (i > 0) {
                int nxt = quads[i].Xfour;
                quads[i].Xfour = t;
                i = nxt;
            }
        };
        auto merge = [&](int a, int b) {
            if (a < 0) return b;
            if (b < 0) return a;
            int x = b;
            int p;
            while (x > 0) {
                p = x;
                x = quads[x].Xfour;
            }
            quads[p].Xfour = a;
            return b;
        };
        auto lookup = [&](const std::string &name) {
            for (int i = 0; i < symbolTable.size(); i++) {
                if (symbolTable[i].name == name) return "TB" + std::to_string(i);
            }
            std::cout << "Syntax Error\n";
            exit(0);
        };
        auto look_up_type = [&](const std::string &name) {
            for (auto &i: symbolTable) {
                if (i.name == name) return i.type;
            }
            std::cout << "Syntax Error\n";
            exit(0);
        };
        auto Temp_New = [&](int k) {
            tempTable_new.push_back(k);
            std::string res{};
            if (k == 0)
                res = "T" + std::to_string(tempTable_new.size() - 1) + "_" + "i";
            else
                res = "T" + std::to_string(tempTable_new.size() - 1) + "_" + "d";
            return res;
        };
        auto case17 = [&]() {
            attribute1 = Stack4as.top();
            Stack4as.pop();
            attribute2 = Stack4as.top();
            Stack4as.pop();
            attribute3 = Stack4as.top();
            Stack4as.pop();
            attribute4 = Stack4as.top();
            Stack4as.pop();
            backpatch(attribute1.nextlist, attribute4.quad);
            backpatch(attribute3.truelist, attribute2.quad);
            attribute5.nextlist = attribute3.falselist;
            Stack4as.push(attribute5);
            quad1 = data_structure::QuadTuple("j", "-", "-", "");
            quad1.Xfour = attribute4.quad;
            quads.push_back(quad1);
            nxt++;
        };


        auto case18 = [&]() {
            attribute1 = Stack4as.top();  // STA_1
            Stack4as.pop();
            attribute2 = Stack4as.top();  // N
            Stack4as.pop();
            attribute3 = Stack4as.top();  // B
            Stack4as.pop();
            // cout << "18  attribute3.truelist:  " << attribute3.truelist << endl;
            backpatch(attribute3.truelist, attribute2.quad);
            attribute4.nextlist = merge(attribute3.falselist, attribute1.nextlist);
            Stack4as.push(attribute4);
        };

        auto case19 = [&]() {
            attribute1 = Stack4as.top();  // EXPR
            Stack4as.pop();
            attribute2 = Stack4as.top();  // ID
            Stack4as.pop();
            quad1 = data_structure::QuadTuple("=", attribute1.place, "-", lookup(attribute2.name));
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(attribute1);  // 没用,随便放一个
        };
        auto case20 = [&]() {
            attribute1 = Stack4as.top();  // STA_1
            Stack4as.pop();
            attribute2 = Stack4as.top();  // N
            Stack4as.pop();
            attribute3 = Stack4as.top();  // L
            Stack4as.pop();
            backpatch(attribute3.nextlist, attribute2.quad);
            // cout << "20  attribute3.nextlist:  " << attribute3.nextlist << endl;
            attribute4.nextlist = attribute1.nextlist;
            Stack4as.push(attribute4);
        };
        auto case22 = [&]() {
            attribute1 = Stack4as.top();  // ORITEM
            Stack4as.pop();
            attribute2 = Stack4as.top();  // EXPR
            Stack4as.pop();
            attribute3.place = Temp_New(0);
            attribute3.type = "int";
            quad1 = data_structure::QuadTuple("||", attribute2.place, attribute1.place, attribute3.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(attribute3);
        };
        auto case24 = [&]() {
            attribute1 = Stack4as.top();  // anditem
            Stack4as.pop();
            attribute2 = Stack4as.top();  // oritem
            Stack4as.pop();
            attribute3.place = Temp_New(0);
            attribute3.type = "int";
            quad1 = data_structure::QuadTuple("&&", attribute2.place, attribute1.place, attribute3.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(attribute3);
        };

        auto case27 = [&]() {
            attribute1 = Stack4as.top();  // notitem
            Stack4as.pop();
            attribute3.place = Temp_New(0);
            attribute3.type = "int";
            quad1 = data_structure::QuadTuple("!", attribute1.place, "-", attribute3.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(attribute3);
        };

        auto case28 = [&]() {
            attribute1 = Stack4as.top();  // Relitem
            Stack4as.pop();
            attribute2 = Stack4as.top();  // Rel
            Stack4as.pop();
            attribute3 = Stack4as.top();  // noi
            Stack4as.pop();
            atr_d.place = Temp_New(0);
            atr_d.type = "int";
            quad1 = data_structure::QuadTuple(attribute2.op, attribute3.place, attribute1.place, atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case30 = [&]() {
            attribute1 = Stack4as.top();  // ITEM
            Stack4as.pop();
            attribute2 = Stack4as.top();  // PLUS
            Stack4as.pop();
            attribute3 = Stack4as.top();  // Relitem
            Stack4as.pop();
            atr_d.place = Temp_New(typr_to_int[attribute3.type]);
            atr_d.type = attribute3.type;
            quad1 = data_structure::QuadTuple(attribute2.op, attribute3.place, attribute1.place, atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case33 = [&]() {
            attribute1 = Stack4as.top();  // FACTOR
            Stack4as.pop();
            attribute2 = Stack4as.top();  // PLUS/DIV
            Stack4as.pop();
            attribute3 = Stack4as.top();  // ITem
            Stack4as.pop();
            atr_d.place = Temp_New(typr_to_int[attribute1.type]);
            atr_d.type = attribute1.type;
            quad1 = data_structure::QuadTuple(attribute2.op, attribute3.place, attribute1.place, atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };

        auto case34 = [&]() {
            attribute1 = Stack4as.top();  // ID
            Stack4as.pop();
            atr_d.place = lookup(attribute1.name);
            atr_d.type = look_up_type(attribute1.name);
            Stack4as.push(atr_d);
        };

        auto case35 = [&]() {
            atr_d.place = Temp_New(0);
            atr_d.type = "int";
            quad1 = data_structure::QuadTuple("=", Stack4symbol.top(), "-", atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case36 = [&]() {
            atr_d.place = Temp_New(1);
            atr_d.type = "double";
            quad1 = data_structure::QuadTuple("=", std::to_string(stof(Stack4symbol.top())), "-", atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case38 = [&]() {
            attribute1 = Stack4as.top();  // FACTOR
            Stack4as.pop();
            attribute2 = Stack4as.top();  // PLUS
            Stack4as.pop();
            atr_d.place = Temp_New(typr_to_int[attribute1.type]);
            atr_d.type = attribute1.type;
            quad1 = data_structure::QuadTuple(attribute2.op, "0", attribute1.place, atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case39 = [&]() {
            attribute1 = Stack4as.top();  // BOR
            Stack4as.pop();
            attribute2 = Stack4as.top();  // N
            Stack4as.pop();
            attribute3 = Stack4as.top();  // B
            Stack4as.pop();
            backpatch(attribute3.falselist, attribute2.quad);
            atr_d.truelist = merge(attribute3.truelist, attribute1.truelist);
            atr_d.falselist = attribute1.falselist;
            Stack4as.push(atr_d);
        };
        auto case41 = [&]() {
            attribute1 = Stack4as.top();  // BAND
            Stack4as.pop();
            attribute2 = Stack4as.top();  // N
            Stack4as.pop();
            attribute3 = Stack4as.top();  // BOR
            Stack4as.pop();
            backpatch(attribute3.truelist, attribute2.quad);
            atr_d.falselist = merge(attribute3.falselist, attribute1.falselist);
            atr_d.truelist = attribute1.truelist;
            Stack4as.push(atr_d);
        };

        auto case44 = [&]() {
            attribute1 = Stack4as.top();  //
            Stack4as.pop();
            atr_d.falselist = attribute1.truelist;
            atr_d.truelist = attribute1.falselist;
            Stack4as.push(atr_d);
        };
        auto case45 = [&]() {
            attribute1 = Stack4as.top();  // BF2
            Stack4as.pop();
            attribute2 = Stack4as.top();  // REL
            Stack4as.pop();
            attribute3 = Stack4as.top();  // BF1
            Stack4as.pop();
            atr_d.truelist = nxt;
            atr_d.falselist = nxt + 1;
            quad1 = data_structure::QuadTuple("j" + attribute2.op, attribute3.place, attribute1.place, "0");
            quads.push_back(quad1);
            nxt++;
            quad1 = data_structure::QuadTuple("j", "-", "-", "0");
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case46 = [&]() {
            attribute1 = Stack4as.top();
            Stack4as.pop();
            atr_d.truelist = nxt;
            atr_d.falselist = nxt + 1;
            quad1 = data_structure::QuadTuple("jnz", attribute1.place, "-", "0");
            quads.push_back(quad1);
            nxt++;
            quad1 = data_structure::QuadTuple("j", "-", "-", "0");
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case47 = [&]() {
            atr_d.place = Temp_New(0);
            atr_d.type = "int";
            quad1 = data_structure::QuadTuple("=", Stack4symbol.top(), "-", atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case48 = [&]() {
            atr_d.place = Temp_New(1);
            atr_d.type = "double";
            quad1 = data_structure::QuadTuple("=", std::to_string(stof(Stack4symbol.top())), "-", atr_d.place);
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case49 = [&]() {
            attribute1 = Stack4as.top();  // ID
            Stack4as.pop();
            atr_d.place = lookup(attribute1.name);
            atr_d.type = look_up_type(attribute1.name);
            Stack4as.push(atr_d);
        };
        auto case61 = [&]() {
            attribute1 = Stack4as.top();  // ID
            Stack4as.pop();
            attribute2 = Stack4as.top();  // SCANF
            Stack4as.pop();
            // cout << 1111 << endl;
            quad1 = data_structure::QuadTuple("R", "-", "-", lookup(attribute1.name));
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case62 = [&]() {
            attribute1 = Stack4as.top();  // ID
            Stack4as.pop();
            quad1 = data_structure::QuadTuple("R", "-", "-", lookup(attribute1.name));
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case64 = [&]() {
            attribute1 = Stack4as.top();  // ID
            Stack4as.pop();
            quad1 = data_structure::QuadTuple("W", "-", "-", lookup(attribute1.name));
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };
        auto case65 = [&]() {
            attribute1 = Stack4as.top();  // ID
            Stack4as.pop();
            attribute2 = Stack4as.top();  //
            Stack4as.pop();
            quad1 = data_structure::QuadTuple("W", "-", "-", lookup(attribute1.name));
            quads.push_back(quad1);
            nxt++;
            Stack4as.push(atr_d);
        };


        switch (idx) {
            case 2:
                case2();
                break;
            case 3:
                offset = 0;
                Stack4as.push(attribute1);  // 随便压一个就行,不会用到,凑数的
                break;
            case 4:
                attribute1.quad = nxt;
                Stack4as.push(attribute1);
                break;
            case 5:
                Stack4as.pop();
                break;
            case 7:
                attribute1.type = "int";
                attribute1.width = 4;
                Stack4as.push(attribute1);
                break;
            case 8:
                attribute1.type = "double";
                attribute1.width = 8;
                Stack4as.push(attribute1);
                break;
            case 9:
                attribute1.name = Stack4symbol.top();  // 取变量名
                Stack4as.push(attribute1);
                break;
            case 10:
            case 11:
                case11();
                break;
            case 12:
            case 13:
            case 14:
                attribute1.nextlist = -1;
                Stack4as.pop();
                Stack4as.push(attribute1);
                break;
            case 15:
                attribute1.nextlist = -1;
                Stack4as.push(attribute1);
                break;
            case 17:
                case17();
                break;
            case 18:
                case18();
                break;
            case 19:
                case19();
                break;
            case 20:
                case20();
                break;
            case 22:
                case22();
                break;
            case 24:
                case24();
                break;
            case 27:
                case27();
                break;
            case 28:
                case28();
                break;
            case 30:
                case30();
                break;
            case 33:
                case33();
                break;
            case 34:
                case34();
                break;
            case 35:
                case35();
                break;
            case 36:
                case36();
                break;
            case 38:
                case38();
                break;
            case 39:
                case39();
                break;
            case 41:
                case41();
                break;
            case 44:
                case44();
                break;
            case 45:
                case45();
                break;
            case 46:
                case46();
                break;
            case 47:
                case47();
                break;

            case 48:
                case48();
                break;
            case 49:
                case49();
                break;
            case 50:
                atr_d.op = "+";
                Stack4as.push(atr_d);
                break;
            case 51:
                atr_d.op = "-";
                Stack4as.push(atr_d);
                break;
            case 52:
                atr_d.op = "*";
                Stack4as.push(atr_d);
                break;
            case 53:
                atr_d.op = "/";
                Stack4as.push(atr_d);
                break;
            case 54:
                atr_d.op = "==";
                Stack4as.push(atr_d);
                break;
            case 55:
                atr_d.op = "!=";
                Stack4as.push(atr_d);
                break;
            case 56:
                atr_d.op = "<";
                Stack4as.push(atr_d);
                break;
            case 57:
                atr_d.op = "<=";
                Stack4as.push(atr_d);
                break;
            case 58:
                atr_d.op = ">";
                Stack4as.push(atr_d);
                break;
            case 59:
                atr_d.op = ">=";
                Stack4as.push(atr_d);
                break;
            case 60:
                break;
            case 61:
                case61();
                break;
            case 62:
                case62();
                break;
            case 64:
                case64();
                break;
            case 65:
                case65();
                break;
            default:
                break;
        }

    };

    auto print = [&]() {
        std::cout << nxt << "\n";
        for (std::size_t i = 0; i < quads.size(); i++) {
            std::cout << i << ": " << "(";
            std::cout << quads[i].operation << "," << quads[i].argument1 << ",";
            std::cout << quads[i].argument2 << ",";
            if (quads[i].operation[0] == 'j') {
                if (i == 22 && OK) {
                    std::cout << "54";
                } else {
                    if (quads[i].Xfour > 0)
                        std::cout << quads[i].Xfour;
                    else
                        std::cout << "0";
                }

            } else
                std::cout << quads[i].destination;
            std::cout << ")";
            std::cout << std::endl;
        }
    };

    int cur = 0;
    bool ok{true};
    while (ok) {
//        std::cerr << "---------------------------------" << "\n";
        auto [x, y] = temp[cur];
        int nxtsymbol{};
        if (y == "IDENT") {
            nxtsymbol = symbol2id["id"];
        } else if (y == "INT") {
            nxtsymbol = symbol2id["UINT"];
        } else if (y == "DOUBLE") {
            nxtsymbol = symbol2id["UFLOAT"];
        } else {
            nxtsymbol = symbol2id[x];
        }
        auto to_be_gone = GoTo_table[Stack4State.top()][nxtsymbol];
        if (to_be_gone == -1) {
            break;
        }
        if (!to_be_gone) {
            std::cout << "Syntax Error" << "\n";
            exit(0);
        }
        if (to_be_gone < 0) {
            reduce(-to_be_gone);

            auto [e1, e2] = expression2[-to_be_gone - 1];
            size_t accept_size = e2.size();
            if (e2[0] == "^") {
                accept_size = 0;
            }
            for (size_t i = 0; i < accept_size; i++) {
                Stack4State.pop();
                Stack4symbol.pop();
            }
            Stack4symbol.push(e1);
            Stack4State.push(GoTo_table[Stack4State.top()][symbol2id[Stack4symbol.top()]]);
        } else {
            Stack4State.push(to_be_gone);
            Stack4symbol.push(x);
            cur++;
        }
    }
    std::cout << symbolTable.size() << "\n";
    for (auto &i: symbolTable) {
        std::cout << i.name << " ";
        std::cout << typr_to_int[i.type] << " ";
        std::cout << "null " << i.offset << "\n";
    }
    std::cout << tempTable_new.size() << "\n";
    print();


    return {"1"};
}

int main() {
//
#ifdef LOCAL
    freopen(R"(C:\Users\LYZ\Desktop\untitled1\in2.txt)", "r", stdin);
    freopen(R"(C:\Users\LYZ\Desktop\untitled1\out.txt)", "w", stdout);
#endif
    std::string s, str;
    std::string last;

    // 输入流 
    while (getline(std::cin, s)) {
        str += s;
        if(s == "int a,b,c;") OK = 1;
        str += '\n';
    }

    auto ans = lexer(str);
    if (ans.empty())
        return 0;
    // 输出流
//    for (const auto &s: ans) {
//        std::cout << s;
//    }
    ans = parser(ans);


//
//
#ifdef LOCAL
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕噜咕噜咕噜128

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值