语法分析(3)

本文深入探讨了自底向上的语法分析技术,包括算符优先算法和LR分析法等,并详细介绍了SLR分析表的构造过程。通过具体示例说明了如何构建LR(0)项目闭包集合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   
语法分析(3)
--------自底向上的语法分析
自底向上的语法分析又叫移动归约分析, 其中一种最容易实现的算法叫做算符优先算符, 但是这种算法有很多缺陷. 更一般的移动归约分析法叫LR分析法, 其中包括SLR, LR,
LALR(参考龙书).
       一 LR分析模型.
       上面几种LR分析程序都是使用一种模型, 它是由输入, 输出, 栈, 驱动程序和包括动作
(action)和转移(goto)两部分的分析表构成(参看龙书):

 

其中输入是记号序列, 栈中保存的是文法符号以及状态, si是状态Xi是文法符号. 分析表由动作(action)和转移(goto)两部分组成, 其中action返回四种动作:
       移动
       归约
       接受
       错误
当action返回归约是, 使用goto获得归约后的状态.
分析的具体过程如下:
1) 当action[sm, ai] = “移动” 时, 将ai及其状态si(由action给出)压入栈中.
2) 当action[sm, ai] = “归约” 时, 将栈中弹出2n个符号(n个状态, n个文法符号, n是由action
提供), 然后将action提供的产生式左部A压入栈中, 再将状态sA(由goto提供)压入栈中.
3) 当action[sm, ai] = “接受” 时, 分析完成.
4) 当action[sm, ai] = “错误” 时, 调用错误处理函数.
SLR, LR, LALR都使用这个模型, 只是分析表action和goto不同.
 
       二 构造SLR分析表
       SLR分析表的构造过程是先求出文法的LR(0)项目闭包集合, 然后通过该集合与follow集合就可以确定SLR分析表(参考龙书).
       对于文法的LR(0)项目就是在产生式右部某处加点. 如产生式为A->XYZ则LR(0)项目:
A->.XYZ
A->X.YZ
A->XY.Z
A->XYZ.
此外还要对文法进行扩展, 加入A是文法的开始符号, 这扩展为A’->A
LR(0)项目闭包集合的求法是:
1) 初时集合包含开始符号的LR(0)项目闭包运算.
2) 如果集合中存在产生式A->X.YZ, 且存在产生式Y->U, Y->.U不在该集合中时, 将
Y->.U加入该集合.
3) 当一个集合I0完成后求它的状态转换集合, 对于产生式A->X.YZ当遇到Y时状态转换成
  A->XY.Z, 对于集合I0的所有产生式求它的所有的状态转换集合.
重复执行制导不再有新的状态集合产生.
例如龙书上的例子:
E’-> E
E-> E+T | T
T-> T*F | F
F-> (E) | id
 
首先初始化集合
I0 = { E’-> .E}
根据2)将E-> .E+T 和 E-> .T 加入到I0中于是有:
I0 = {
E’-> .E
E-> .E+T
E-> .T
}
重复应用2)最后集合I0:
I0 = {
E’-> .E
E-> .E+T
E-> .T
T-> .T*F
T-> .F
F-> .(E)
F-> .id
}
0完成, 根据3)求的I0的状态转换集合
I0 –E-> 表示I0 遇到E后转换的集合.
I1 = I0 –E-> = {
E’-> E.
E-> E.+T
}
I2 = I0 –T-> = {
E-> T.
T-> T.*F
}
I3 = I0 –F-> = {
T-> F.
}
I4 = I0 –(-> = {
F-> (.E)
E-> .E+T
E-> .T
T-> .T*F
T-> .F
F-> .(E)
F-> .id
}
I5 = I0 –id-> = {
F-> id.
}
然后再从I1开始求状态转换集合, 如此循环直到没有新的状态集合出现, 最后的结果是:
I6 = I1-+-> = {
E-> E+.T
T-> .T*F
T-> .F
F-> .(E)
F-> .id
}
I7 = I2-*-> = {
T-> T*.F
F-> .(E)
F-> .id
}
I8 = I4-E-> = {
F-> (E.)
E-> E.+T
}
I4 –T-> = I2
I4 –F-> = I3
I4 –(-> = I4
I4 –id-> = I5
I9 = I6 –T-> = {
E-> E+T.
T-> T.*F
}
I6 –F-> = I3
I6 –(-> = I4
I6 –id-> = I5
I10 = I7 –F-> = {
T-> T*F.
}
I7 –(-> = I4
I7 –id-> = I5
I11 = I8 -)-> = {
F-> (E).
}
I8 -+-> = I6
I9 -*-> = I7
goto(I, X)定义为状态I遇到X后转换的状态.其中各个集合的转换关系就构成了goto函数,
如I8 -+-> = I6则goto(I8, +) = I6
根据上面的规则对于TINY的扩展上下文无关文法:
PROGRAM'-> PROGRAM
PROGRAM-> STMT-SEQUENCE
STMT-SEQUENCE-> STMT-SEQUENCE ; STATEMENT | STATEMENT
STATEMENT-> IF-STMT | REPEAT-STMT | ASSIGN-STMT | READ-STMT | WRITE-STMT
IF-STMT-> if EXP then STMT-SEQUENCE end
         | if EXP then STMT-SEQUENCT else STMT-SEQUENCE end
REPEAT-STMT-> repeat STMT-SEQUENCE until EXP
ASSIGN-STMT-> identifier := EXP
READ-STMT-> read identifier
WRITE-STMT-> write EXP
EXP-> SIMPLE-EXP COMPARISON-OP SIMPLE-EXP | SIMPLE-EXP
COMPARISON-OP-> < | =
SIMPLE-EXP-> SIMPLE-EXP ADDOP TERM | TERM
ADDOP-> + | -
TERM-> TERM MULOP FACTOR | TERM
MULOP-> * | /
FACTOR-> (EXP) | number | identifier
 
可以求出LR(0)项目闭包集合:
I0 = {
PROGRAM'-> .PROGRAM
PROGRAM-> .STMT-SEQUENCE
STMT-SEQUENCE-> .STMT-SEQUENCE ; STATEMENT
STMT-SEQUENCE-> .STATEMENT
STATEMENT-> .IF-STMT
STATEMENT-> .REPEAT-STMT
STATEMENT-> .ASSIGN-STMT
STATEMENT-> .READ-STMT
STATEMENT-> .WRITE-STMT
IF-STMT-> .if EXP then STMT-SEQUENCE end
IF-STMT-> .if EXP then STMT-SEQUENCE else STMT-SEQUENCE end
REPEAT-STMT-> .repeat STMT->SEQUENCE until EXP
ASSIGN-STMT-> .identifier := EXP
READ-STMT-> .read identifier
WRITE-STMT-> .write EXP
}
I1 = {
PROGRAM'-> PROGRAM.
}
I2 = {
PROGRAM-> STMT-SEQUENCE.
STMT-SEQUENCE-> STMT-SEQUENCE .; STATEMENT
}
I3 = {
STMT-SEQUENCE-> STATEMENT.
}
I4 = {
STATEMENT-> IF-STMT.
}
I5 = {
STATEMENT-> REPEAT-STMT.
}
I6 = {
STATEMENT-> ASSIGN-STMT.
}
I7 = {
STATEMENT-> READ-STMT.
}
I8 = {
STATEMENT-> WRITE-STMT.
}
I9 = {
IF-STMT-> if .EXP then STMT-SEQUENCE end
IF-STMT-> if .EXP then STMT-SEQUENCE else STMT-SEQUENCE end
EXP-> .SIMPLE-EXP COMPARISON-OP SIMPLE-EXP
EXP-> .SIMPLE-EXP
SIMPLE-EXP-> .SIMPLE-EXP ADDOP TERM
SIMPLE-EXP-> .TERM
TERM-> .TERM MULOP FACTOR
TERM-> .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I10 = {
REPEAT-STMT-> repeat .STMT-SEQUENCE until EXP
STMT-SEQUENCE-> .STMT-SEQUENCE ; STATEMNT
STMT-SEQUENCE-> .STATEMENT
STATEMENT-> .IF-STMT
STATEMENT-> .REPEAT-STMT
STATEMENT-> .ASSIGN-STMT
STATEMENT-> .READ-STMT
STATEMENT-> .WRITE-STMT
IF-STMT-> .if EXP then STMT-SEQUENCE end
IF-STMT-> .if EXP then STMT-SEQUENCE else STMT-SEQUENCE end
REPEAT-STMT-> .repeat STMT->SEQUENCE until EXP
ASSIGN-STMT-> .identifier := EXP
READ-STMT-> .read identifier
WRITE-STMT-> .write EXP
}
I11 = {
ASSIGN-STMT-> identifier .:= EXP
}
I12 = {
READ-STMT-> read .identifier
}
I13 = {
WRITE-STMT-> write .EXP
EXP-> .SIMPLE-EXP COMPARISON-OP SIMPLE-EXP
EXP-> .SIMPLE-EXP
SIMPLE-EXP-> .SIMPLE-EXP ADDOP TERM
SIMPLE-EXP-> .TERM
TERM-> .TERM MULOP FACTOR
TERM-> .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I14 = {
STMT-SEQUENCE-> STMT-SEQUENCE ; .STATEMENT
STATEMENT-> .IF-STMT
STATEMENT-> .REPEAT-STMT
STATEMENT-> .ASSIGN-STMT
STATEMENT-> .READ-STMT
STATEMENT-> .WRITE-STMT
IF-STMT-> .if EXP then STMT-SEQUENCE end
IF-STMT-> .if EXP then STMT-SEQUENCE else STMT-SEQUENCE end
REPEAT-STMT-> .repeat STMT->SEQUENCE until EXP
ASSIGN-STMT-> .identifier := EXP
READ-STMT-> .read identifier
WRITE-STMT-> .write EXP
}
I15 = {
IF-STMT-> if EXP .then STMT-SEQUENCE end
IF-STMT-> if EXP .then STMT-SEQUENCE else STMT-SEQUENCE end
}
I16 = {
EXP-> SIMPLE-EXP .COMPARISON-OP SIMPLE-EXP
EXP-> SIMPLE-EXP.
SIMPLE-EXP-> SIMPLE-EXP .ADDOP TERM
COMPARISON-OP-> .<
COMPARISON-OP-> .=
ADDOP-> .+
ADDOP-> .-
}
I17 = {
SIMPLE-EXP-> TERM.
TERM-> TERM .MULOP FACTOR
MULOP-> .*
MULOP-> ./
}
I18 = {
TERM-> FACTOR.
}
I19 = {
FACTOR-> (.EXP)
EXP-> .SIMPLE-EXP COMPARISON-OP SIMPLE-EXP
EXP-> .SIMPLE-EXP
SIMPLE-EXP-> .SIMPLE-EXP ADDOP TERM
SIMPLE-EXP-> .TERM
TERM-> .TERM MULOP FACTOR
TERM-> .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I20 = {
FACTOR-> identifier.
}
I21 = {
FACTOR-> number.
}
I22 = {
REPEAT-STMT-> repeat STMT-SEQUENCE .until EXP
STMT-SEQUENCE-> STMT-SEQUENCE .; STATEMNT
}
I23 = {
ASSIGN-STMT-> identifier := .EXP
EXP-> .SIMPLE-EXP COMPARISON-OP SIMPLE-EXP
EXP-> .SIMPLE-EXP
SIMPLE-EXP-> .SIMPLE-EXP ADDOP TERM
SIMPLE-EXP-> .TERM
TERM-> .TERM MULOP FACTOR
TERM-> .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I24 = {
READ-STMT-> read identifier.
}
I25 = {
WRITE-STMT-> write EXP.
}
I26 = {
STMT-SEQUENCE-> STMT-SEQUENCE ; STATEMENT.
}
I27 = {
IF-STMT-> if EXP then .STMT-SEQUENCE end
IF-STMT-> if EXP then .STMT-SEQUENCE else STMT-SEQUENCE end
STMT-SEQUENCE-> .STMT-SEQUENCE ; STATEMNT
STMT-SEQUENCE-> .STATEMENT
STATEMENT-> .IF-STMT
STATEMENT-> .REPEAT-STMT
STATEMENT-> .ASSIGN-STMT
STATEMENT-> .READ-STMT
STATEMENT-> .WRITE-STMT
IF-STMT-> .if EXP then STMT-SEQUENCE end
IF-STMT-> .if EXP then STMT-SEQUENCE else STMT-SEQUENCE end
REPEAT-STMT-> .repeat STMT->SEQUENCE until EXP
ASSIGN-STMT-> .identifier := EXP
READ-STMT-> .read identifier
WRITE-STMT-> .write EXP
}
I28 = {
EXP-> SIMPLE-EXP COMPARISON-OP .SIMPLE-EXP
SIMPLE-EXP-> .SIMPLE-EXP ADDOP TERM
SIMPLE-EXP-> .TERM
TERM-> .TERM MULOP FACTOR
TERM-> .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I29 = {
SIMPLE-EXP-> SIMPLE-EXP ADDOP .TERM
TERM-> .TERM MULOP FACTOR
TERM-> .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I30 = {
COMPARISON-OP-> <.
}
I31 = {
COMPARISON-OP-> =.
}
I32 = {
ADDOP-> +.
}
I33 = {
ADDOP-> -.
}
I34 = {
TERM-> TERM MULOP .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I35 = {
MULOP-> *.
}
I36 = {
MULOP-> /.
}
I37 = {
FACTOR-> (EXP.)
}
I38 = {
REPEAT-STMT-> repeat STMT-SEQUENCE until .EXP
EXP-> .SIMPLE-EXP COMPARISON-OP SIMPLE-EXP
EXP-> .SIMPLE-EXP
SIMPLE-EXP-> .SIMPLE-EXP ADDOP TERM
SIMPLE-EXP-> .TERM
TERM-> .TERM MULOP FACTOR
TERM-> .FACTOR
FACTOR-> .(EXP)
FACTOR-> .identifier
FACTOR-> .number
}
I39 = {
ASSIGN-STMT-> identifier := EXP.
}
I40 = {
IF-STMT-> if EXP then STMT-SEQUENCE .end
IF-STMT-> if EXP then STMT-SEQUENCE .else STMT-SEQUENCE end
STMT-SEQUENCE-> STMT-SEQUENCE .; STATEMNT
}
I41 = {
EXP-> SIMPLE-EXP COMPARISON-OP SIMPLE-EXP.
SIMPLE-EXP-> SIMPLE-EXP .ADDOP TERM
ADDOP-> .+
ADDOP-> .-
}
I42 = {
SIMPLE-EXP-> SIMPLE-EXP ADDOP TERM.
TERM-> TERM .MULOP FACTOR
MULOP-> .*
MULOP-> ./
}
I43 = {
TERM-> TERM MULOP FACTOR.
}
I44 = {
FACTOR-> (EXP).
}
I45 = {
REPEAT-STMT-> repeat STMT-SEQUENCE until EXP.
}
I46 = {
IF-STMT-> if EXP then STMT-SEQUENCE end.
}
I47 = {
IF-STMT-> if EXP then STMT-SEQUENCE else .STMT-SEQUENCE end
STMT-SEQUENCE-> .STMT-SEQUENCE ; STATEMNT
STMT-SEQUENCE-> .STATEMENT
STATEMENT-> .IF-STMT
STATEMENT-> .REPEAT-STMT
STATEMENT-> .ASSIGN-STMT
STATEMENT-> .READ-STMT
STATEMENT-> .WRITE-STMT
IF-STMT-> .if EXP then STMT-SEQUENCE end
IF-STMT-> .if EXP then STMT-SEQUENCE else STMT-SEQUENCE end
REPEAT-STMT-> .repeat STMT->SEQUENCE until EXP
ASSIGN-STMT-> .identifier := EXP
READ-STMT-> .read identifier
WRITE-STMT-> .write EXP
}
I48 = {
IF-STMT-> if EXP then STMT-SEQUENCE else STMT-SEQUENCE .end
STMT-SEQUENCE-> STMT-SEQUENCE .; STATEMNT
}
I49 = {
IF-STMT-> if EXP then STMT-SEQUENCE else STMT-SEQUENCE end.
}
同时求出goto集合:
goto(I0, PROGRAM) = I1
goto(I0, STMT-SEQUENCE) = I2
goto(I0, STATEMENT) = I3
goto(I0, IF-STMT) = I4
goto(I0, REPEAT-STMT) = I5
goto(I0, ASSIGN-STMT) = I6
goto(I0, READ-STMT) = I7
goto(I0, WRITE-STMT) = I­8
goto(I0, if) = I9
goto(I0, repeat) = I10
goto(I0, ifentifier) = I11
goto(I0, read) = I12
goto(I0, write) = I13
goto(I2, ;) = I14
goto(I9, EXP) = I15­
goto(I9, SIMPLE-EXP) = I16
goto(I9, TERM) = I17
goto(I9, FACTOR) = I18
goto(I9, () = I19
goto(I9, identifier) = I20
goto(I9, number) = I21
goto(I10, STMT-SEQUENCE) = I22
goto(I10, STATEMENT) = I3
goto(I10, IF-STMT) = I4
goto(I10, REPEAT-STMT) = I5
goto(I10, ASSIGN-STMT) = I6
goto(I10, READ-STMT) = I7
goto(I10, WRITE-STMT) = I8
goto(I10, if) = I9
goto(I10, repeat) = I10
goto(I10, identifier) = I11
goto(I10, read) = I12
goto(I10, write) = I13
goto(I11, :=) = I23
goto(I12, identifier) = I24
goto(I13, EXP) = I25
goto(I13, SIMPLE-EXP) = I16
goto(I13, TERM) = I17
goto(I13, FACTOR) = I18
goto(I13, () = I19
goto(I13, identifier) = I20
goto(I13, number) = I21
goto(I14, STATEMENT) = I26
goto(I14, IF-STMT) = I4
goto(I14, REPEAT-STMT) = I5
goto(I14, ASSIGN-STMT) = I6
goto(I14, READ-STMT) = I7
goto(I14, WRITE-STMT) = I8
goto(I14, if) = I9
goto(I14, repeat) = I10
goto(I14, identifier) = I11
goto(I14, read) = I12
goto(I14, write) = I13
goto(I15, then) = I27
goto(I16, COMPARISON-OP) = I28
goto(I16, ADDOP) = I29
goto(I16, <) = I30
goto(I16, =) = I31
goto(I16, +) = I32
goto(I16, -) = I33
goto(I17, MULOP) = I34
goto(I17, *) = I35
goto(I17, /) = I36
goto(I19, EXP) = I37
goto(I19, SIMPLE-EXP) = I16
goto(I19, TERM) = I17
goto(I19, () = I19
goto(I19, identifier) = I20
goto(I19, number) = I21
goto(I22, until) = I38
goto(I22, ;) = I14
goto(I23, EXP) = I39
goto(I23, SIMPLE-EXP) = I16
goto(I23, TERM) = I17
goto(I23, FACTOR) = I18
goto(I23, () = I19
goto(I23, identifier) = I20
goto(I23, number) = I21
goto(I27, STMT-SEQUENCE) = I40
goto(I27, STATEMENT) = I3
goto(I27, IF-STMT) = I4
goto(I27, REPEAT-STMT) = I5
goto(I27, ASSIGN-STMT) = I6
goto(I27, READ-STMT) = I7
goto(I27, WRITE-STMT) = I8
goto(I27, if) = I9
goto(I27, repeat) = I10
goto(I27, identifier) = I11
goto(I27, read) = I12
goto(I27, write) = I13
goto(I28, SIMPLE-EXP) = I41
goto(I28, TERM) = I17
goto(I28, () = I19
goto(I28, identifier) = I20
goto(I28, number) = I21
goto(I29, TERM) = I42
goto(I29, () = I19
goto(I29, identifier) = I20
goto(I29, number) = I21
goto(I34, FACTOR) = I43
goto(I34, () = I19
goto(I34, identifier) = I20
goto(I34, number) = I21
goto(I37, )) = I44
goto(I38, EXP) = I45
goto(I38, SIMPLE-EXP) = I16
goto(I38, TERM) = I17
goto(I38, FACTOR) = I18
goto(I38, () = I19
goto(I38, identifier) = I20
goto(I38, number) = I21
goto(I40, end) = I46
goto(I40, else) = I47
goto(I40, ;) = I14
goto(I41, ADDOP) = I29
goto(I41, +) = I32
goto(I41, -) = I33
goto(I42, MULOP) = I34
goto(I42, *) = I35
goto(I42, /) = I36
goto(I47, STMT-SEQUENCE) = I48
goto(I47, STATEMENT) = I3
goto(I47, IF-STMT) = I4
goto(I47, REPEAT-STMT) = I5
goto(I47, ASSIGN-STMT) = I6
goto(I47, READ-STMT) = I7
goto(I47, WRITE-STMT) = I8
goto(I47, if) = I9
goto(I47, repeat) = I10
goto(I47, identifier) = I11
goto(I47, read) = I12
goto(I47, write) = I13
goto(I48, end) = I49
goto(I48, ;) = I14
 
 
2. 构造SLR分析表
       根据龙书上的构造SLR分析表的算法, 很容易构造出SLR分析表.
       3. 错误处理
       SLR分析程序的错误处理采用短语级错误处理, 对每一种状态和当前输入记号进行分析, 分析在语言的使用中最常犯的错误, 然后根据具体错误进行处理.
       4. 构造语法树
       因为SLR语法分析是自下而上的, 那么语法树的子节点先建立起来, 这样构造语法树就更加容易了, 只要将构造的语法树子节点保存在栈中, 当其父节点建立时弹出并与父节点关联, 然后再将父节点保存在栈中, 一直到分析结束.
       5. SLR分析源代码
parse_slr.c slr分析和错误处理以及语法树生成
/* error function for slr */
static TokenType slr_error(TokenType err_id, TokenType current_token);
 
TreeNode* parse_slr(void)
{
    int          count          = 0;
    int          i          = 0;
    TreeNode*     tree     = NULL;
    TreeNode*     tree_temp   = NULL;
    TokenType     bnf;
    TokenType     status_bnf;
    TokenType     token;
    TokenType     oper;
    TokenType     nes;
 
    init_slr_stack();
    init_tree_node_stack();
   
    token = get_token();
    oper = action(stack_top(), token, &status_bnf);
   
    while(oper != ACC)
    {
#ifdef TRACE_SLR_STACK
       trace_stack();
#endif
      
       switch(oper)
       {
       case MOVE:
           push(token);
           push(status_bnf);
 
           /* create id, num, comparison-op, mulop, addop node */
           switch(token)
           {
           case ID:
              tree = new_exp_node(KIND_ID);
              tree->attr.name = copy_string(token_string);
              child_stack_push(tree);
              break;
           case NUM:
              tree = new_exp_node(KIND_CONST);
              tree->attr.val = atoi(token_string);
              child_stack_push(tree);
              break;
           case LT:
           case EQ:
           case PLUS:
           case MINUS:
           case MULT:
           case DIV:
              tree = new_exp_node(KIND_OP);
              tree->attr.op = token;
              child_stack_push(tree);
              break;
           default:
              break;
           }
          
           token = get_token();
           break;
       case MERGER:
           bnf = status_bnf;
           nes = merger(status_bnf, &count);
           for(i = 0; i < 2*count; i++)
              pop();
           status_bnf = go_to(stack_top(), nes);
           push(nes);
           push(status_bnf);
 
           /* create stmt tree node */
           switch(bnf)
           {
           /* TERM-> TERM MULOP FACTOR */
           case BNF23:
           /* SIMPLE-EXP-> SIMPLE-EXP ADDOP TERM */
           case BNF19:
           /* EXP-> SIMPLE-EXP COMPARISON-OP SIMPLE-EXP */
           case BNF15:
              tree_temp = child_stack_pop();
              tree = child_stack_pop();
              tree->child[1] = tree_temp;
              tree->child[0] = child_stack_pop();
              child_stack_push(tree);
              break;
           /* WRITE-STMT-> write EXP */
           case BNF14:
              tree = new_stmt_node(KIND_WRITE);
              tree->child[0] = child_stack_pop();
              child_stack_push(tree);
              break;
           /* READ-STMT-> read identifier */
           case BNF13:
              tree = new_stmt_node(KIND_READ);
              tree_temp = child_stack_pop();
              tree->attr.name = copy_string(tree_temp->attr.name);
              destroy_tree_node(tree_temp);
              child_stack_push(tree);
              break;
           /* ASSIGN-STMT-> identifier := EXP */
           case BNF12:
              tree = new_stmt_node(KIND_ASSIGN);
              tree->child[0] = child_stack_pop();
              tree_temp = child_stack_pop();
              tree->attr.name = copy_string(tree_temp->attr.name);
              destroy_tree_node(tree_temp);
              child_stack_push(tree);
              break;
           /* REPEAT-STMT-> repeat STMT-SEQUENCE until EXP */
           case BNF11:
              tree = new_stmt_node(KIND_REPEAT);
              tree->child[1] = child_stack_pop();
              tree->child[0] = child_stack_pop();
              child_stack_push(tree);
              break;
           /* IF-STMT-> if EXP then STMT-SEQUENCE else STMT-SEQUENCE end */
           case BNF10:
              tree = new_stmt_node(KIND_IF);
              tree->child[2] = child_stack_pop();
              tree->child[1] = child_stack_pop();
              tree->child[0] = child_stack_pop();
              child_stack_push(tree);
              break;
           /* IF-STMT-> if EXP then STMT-SEQUENCE end */
           case BNF9:
              tree = new_stmt_node(KIND_IF);
              tree->child[1] = child_stack_pop();
              tree->child[0] = child_stack_pop();
              child_stack_push(tree);
              break;
           /* STMT-SEQUENCE-> STMT-SEQUENCE ; STATEMENT */
           case BNF2:
              tree_temp = child_stack_pop();
              tree = child_stack_top();
              while(tree->sibling != NULL)
                  tree = tree->sibling;
              tree->sibling = tree_temp;
              break;
           default:
              break;          
           }
          
           break;
       default:
           token = slr_error(oper, token);
           break;
       }
 
       oper = action(stack_top(), token, &status_bnf);
    }
 
    tree = child_stack_pop();
    return tree;
}
 
static TokenType slr_error(TokenType err_id, TokenType current_token)
{
    TokenType token = current_token;
   
    switch(err_id)
    {
    case E0001:
       fprintf(stderr, "syntax error(E0001) at line %d: "
                     "missing keyword /"if/"./n", line_no);
       token = get_token();  
       break;
    case E0002:
       fprintf(stderr, "syntax error(E0002) at line %d: "
                      "missing keyword /"repeat/"./n", line_no);
       token = get_token();
       break;
    case E0003:
       fprintf(stderr, "syntax error(E0003) at line %d: "
                     "unwanted symbol ", line_no);
       print_token_stack(current_token);
       fprintf(stderr, "/n");
       token = get_token();
       break;
    case E0004:
       fprintf(stderr, "warning : source file is empty./n");
       exit(-1);
       break;
    case E0201:
       fprintf(stderr, "syntax error(E0201) at line %d: "
                     "missing /";/"./n", line_no);
       /* add ; */
       unget_token();
       token = SEMI;
       break;
    case E0901:
       fprintf(stderr, "syntax error(E0901) at line %d: "
                     "missing operand./n", line_no);
       /* add 0 */
       unget_token();
       token = NUM;
       break;
    case E1001:
       fprintf(stderr, "syntax error(E1001) at line %d: "
                     "missing keyword /"until/" and expression./n", line_no);
       exit(-1);
       break;
    case E1101:
       fprintf(stderr, "syntax error(E1101) at line %d: "
                     "missing /":=/"./n", line_no);
       /* add := */
       unget_token();
       token = ASSIGN;
       break;
    case E1102:
       fprintf(stderr, "syntax error(E1102) at line %d: "
                     "missing /":=/" and expression./n", line_no);
       exit(-1);
       break;
    case E1201:
       fprintf(stderr, "syntax error(E1201) at line %d: "
                     "missing identifier./n", line_no);
       /* add a */
       unget_token();
       token = ID;
       break;
    case E1401:
       fprintf(stderr, "syntax error(E1401) at line %d: "
                     "unwanted symbol /";/"./n", line_no);
       exit(-1);
       break;
    case E1501:
       fprintf(stderr, "syntax error(E1501) at line %d: "
                     "missing keyword /"then/"./n", line_no);
       /* add then */
       unget_token();
       token = KEY_THEN;
       break;
    case E1502:
       fprintf(stderr, "syntax error(E1502) at line %d: "
                     "incomplete if statement./n", line_no);
       exit(-1);
       break;
    case E1601:
       fprintf(stderr, "syntax error(E1601) at line %d: "
                     "missing operator /"</" or /"=/"./n", line_no);
       /* add < */
       unget_token();
       token = LT;
       break;
    case E1701:
       fprintf(stderr, "syntax error(E1701) at line %d: "
                     "missing operator /"*/" or /"//"./n", line_no);
       /* add * */
       unget_token();
       token = MULT;
       break;
    case E1901:
       fprintf(stderr, "syntax error(E1901) at line %d: "
                     "missing expression and /")/"./n", line_no);
       exit(-1);
       break;
    case E2201:
       fprintf(stderr, "syntax error(E2201) at line %d: "
                     "missing keyword /"until/"./n", line_no);
       /* add until */
       unget_token();
       token = KEY_UNTIL;
       break;
    case E2701:
       fprintf(stderr, "syntax error(E2701) at line %d: "
                     "incomplete if statement./n", line_no);
       exit(-1);
       break;
    case E3701:
       fprintf(stderr, "syntax error(E3701) at line %d: "
                     "missing /")/"./n", line_no);
       /* add ) */
       unget_token();
       token = RPAREN;
       break;
    case E4001:
       fprintf(stderr, "syntax error(E4001) at line %d: "
                     "missing keyword /"end/"./n", line_no);
       exit(-1);
       break;
    case E4101:
       fprintf(stderr, "syntax error(E4101) at line %d: "
                     "missing operator /"+/" or /"-/"./n", line_no);
       /* add + */
       unget_token();
       token = PLUS;
       break;
    default:
       fprintf(stderr, "unknown error at line: %d/n", line_no);
       exit(-1);
       break;
    }
 
    return token;
}
 
parse_slr_set.c
action表和goto表初始化, 以及action函数和goto函数及其附属函数
struct bnf_node
{
    TokenType     nes; /* non end symbol */
    int          count;
}
TINY_BNF[] =
{
    /*
     * the BNF of TINY
     * 0)PROGRAM'-> PROGRAM
     * 1)PROGRAM-> STMT-SEQUENCE
     * 2)STMT-SEQUENCE-> STMT-SEQUENCE ; STATEMENT
     * 3)STMT-SEQUENCE-> STATEMENT
     * 4)STATEMENT-> IF-STMT
     * 5)STATEMENT-> REPEAT-STMT
     * 6)STATEMENT-> ASSIGN-STMT
     * 7)STATEMENT-> READ-STMT
     * 8)STATEMENT-> WRITE-STMT
     * 9)IF-STMT-> if EXP then STMT-SEQUENCE end
     * 10)IF-STMT-> if EXP then STMT-SEQUENCE else STMT-SEQUENCE end
     * 11)REPEAT-STMT-> repeat STMT-SEQUENCE until EXP
     * 12)ASSIGN-STMT-> identifier := EXP
     * 13)READ-STMT-> read identifier
     * 14)WRITE-STMT-> write EXP
     * 15)EXP-> SIMPLE-EXP COMPARISON-OP SIMPLE-EXP
     * 16)EXP-> SIMPLE-EXP
     * 17)COMPARISON-OP-> <
     * 18)COMPARISON-OP-> =
     * 19)SIMPLE-EXP-> SIMPLE-EXP ADDOP TERM
     * 20)SIMPLE-EXP-> TERM
     * 21)ADDOP-> +
     * 22)ADDOP-> -
     * 23)TERM-> TERM MULOP FACTOR
     * 24)TERM-> FACTOR
     * 25)MULOP-> *
     * 26)MULOP-> /
     * 27)FACTOR-> (EXP)
     * 28)FACTOR-> number
     * 29)FACTOR-> identifier
     */
    {NES_PROGRAM_, 1}, {NES_PROGRAM, 1}, {NES_STMT_SEQUENCE, 3},
    {NES_STMT_SEQUENCE, 1}, {NES_STATEMENT, 1}, {NES_STATEMENT, 1},
    {NES_STATEMENT, 1}, {NES_STATEMENT, 1}, {NES_STATEMENT, 1},
    {NES_IF_STMT, 5}, {NES_IF_STMT, 7}, {NES_REPEAT_STMT, 4},
    {NES_ASSIGN_STMT, 3}, {NES_READ_STMT, 2}, {NES_WRITE_STMT, 2},
    {NES_EXP, 3}, {NES_EXP, 1}, {NES_COMPARISON_OP, 1}, {NES_COMPARISON_OP, 1},
    {NES_SIMPLE_EXP, 3}, {NES_SIMPLE_EXP, 1}, {NES_ADDOP, 1}, {NES_ADDOP, 1},
    {NES_TERM, 3}, {NES_TERM, 1}, {NES_MULOP, 1}, {NES_MULOP, 1},
    {NES_FACTOR, 3}, {NES_FACTOR, 1}, {NES_FACTOR, 1}
};
static TokenType bnf_map[] =
{
    BNF0, BNF1, BNF2, BNF3, BNF4, BNF5, BNF6, BNF7, BNF8, BNF9, BNF10,
    BNF11, BNF12, BNF13, BNF14, BNF15, BNF16, BNF17, BNF18, BNF19, BNF20,
    BNF21, BNF22, BNF23, BNF24, BNF25, BNF26, BNF27, BNF28, BNF29
};
 
/* action table */
struct action_node
{
    TokenType token;
    TokenType action;
    TokenType next_status_bnf;
};
static struct action_node status_I0[] =
{
    {KEY_IF, MOVE, I9}, {KEY_REPEAT, MOVE, I10}, {KEY_READ, MOVE, I12},
    {KEY_WRITE, MOVE, I13}, {ID, MOVE, I11}
};
static struct action_node status_I1[] =
{
    {END_FILE, ACC, I1}
};
static struct action_node status_I2[] =
{
    {SEMI, MOVE, I14}, {END_FILE, MERGER, BNF1}
};
static struct action_node status_I3[] =
{
    {KEY_ELSE, MERGER, BNF3}, {KEY_END, MERGER, BNF3}, {KEY_UNTIL, MERGER, BNF3},
    {SEMI, MERGER, BNF3}, {END_FILE, MERGER, BNF3}
};
static struct action_node status_I4[] =
{
    {KEY_ELSE, MERGER, BNF4}, {KEY_END, MERGER, BNF4}, {KEY_UNTIL, MERGER, BNF4},
    {SEMI, MERGER, BNF4}, {END_FILE, MERGER, BNF4}
};
static struct action_node status_I5[] =
{
    {KEY_ELSE, MERGER, BNF5}, {KEY_END, MERGER, BNF5}, {KEY_UNTIL, MERGER, BNF5},
    {SEMI, MERGER, BNF5}, {END_FILE, MERGER, BNF5}
};
static struct action_node status_I6[] =
{
    {KEY_ELSE, MERGER, BNF6}, {KEY_END, MERGER, BNF6}, {KEY_UNTIL, MERGER, BNF6},
    {SEMI, MERGER, BNF6}, {END_FILE, MERGER, BNF6}
};
static struct action_node status_I7[] =
{
    {KEY_ELSE, MERGER, BNF7}, {KEY_END, MERGER, BNF7}, {KEY_UNTIL, MERGER, BNF7},
   {SEMI, MERGER, BNF7}, {END_FILE, MERGER, BNF7}
};
static struct action_node status_I8[] =
{
    {KEY_ELSE, MERGER, BNF8}, {KEY_END, MERGER, BNF8}, {KEY_UNTIL, MERGER, BNF8},
    {SEMI, MERGER, BNF8}, {END_FILE, MERGER, BNF8}
};
static struct action_node status_I9[] =
{
    {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I10[] =
{
    {KEY_IF, MOVE, I9}, {KEY_REPEAT, MOVE, I10}, {KEY_READ, MOVE, I12},
    {KEY_WRITE, MOVE, I13}, {ID, MOVE, I11}
};
static struct action_node status_I11[] =
{
    {ASSIGN, MOVE, I23}
};
static struct action_node status_I12[] =
{
    {ID, MOVE, I24}
};
static struct action_node status_I13[] =
{
    {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I14[] =
{
    {KEY_IF, MOVE, I9}, {KEY_REPEAT, MOVE, I10}, {KEY_READ, MOVE, I12},
    {KEY_WRITE, MOVE, I13}, {ID, MOVE, I11}
};
static struct action_node status_I15[] =
{
    {KEY_THEN, MOVE, I27}
};
static struct action_node status_I16[] =
{
    {KEY_THEN, MERGER, BNF16}, {KEY_ELSE, MERGER, BNF16}, {KEY_END, MERGER, BNF16},
    {KEY_UNTIL, MERGER, BNF16}, {SEMI, MERGER, BNF16}, {RPAREN, MERGER, BNF16},
    {END_FILE, MERGER, BNF16}, {LT, MOVE, I30}, {EQ, MOVE, I31}, {PLUS, MOVE, I32},
    {MINUS, MOVE, I33}
};
static struct action_node status_I17[] =
{
    {KEY_THEN, MERGER, BNF20}, {KEY_ELSE, MERGER, BNF20}, {KEY_END, MERGER, BNF20},
    {KEY_UNTIL, MERGER, BNF20}, {SEMI, MERGER, BNF20}, {RPAREN, MERGER, BNF20},
    {END_FILE, MERGER, BNF20}, {LT, MERGER, BNF20}, {EQ, MERGER, BNF20},
    {PLUS, MERGER, BNF20}, {MINUS, MERGER, BNF20}, {MULT, MOVE, I35},
    {DIV, MOVE, I36}
};
static struct action_node status_I18[] =
{
    {KEY_THEN, MERGER, BNF24}, {KEY_ELSE, MERGER, BNF24}, {KEY_END, MERGER, BNF24},
    {KEY_UNTIL, MERGER, BNF24}, {SEMI, MERGER, BNF24}, {RPAREN, MERGER, BNF24},
    {END_FILE, MERGER, BNF24}, {LT, MERGER, BNF24}, {EQ, MERGER, BNF24},
    {PLUS, MERGER, BNF24}, {MINUS, MERGER, BNF24}, {MULT, MERGER, BNF24},
    {DIV, MERGER, BNF24}
};
static struct action_node status_I19[] =
{
    {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I20[] =
{
    {KEY_THEN, MERGER, BNF29}, {KEY_ELSE, MERGER, BNF29}, {KEY_END, MERGER, BNF29},
    {KEY_UNTIL, MERGER, BNF29}, {SEMI, MERGER, BNF29}, {RPAREN, MERGER, BNF29},
    {END_FILE, MERGER, BNF29}, {LT, MERGER, BNF29}, {EQ, MERGER, BNF29},
    {PLUS, MERGER, BNF29}, {MINUS, MERGER, BNF29}, {MULT, MERGER, BNF29},
    {DIV, MERGER, BNF29}
};
static struct action_node status_I21[] =
{
    {KEY_THEN, MERGER, BNF28}, {KEY_ELSE, MERGER, BNF28}, {KEY_END, MERGER, BNF28},
    {KEY_UNTIL, MERGER, BNF28}, {SEMI, MERGER, BNF28}, {RPAREN, MERGER, BNF28},
    {END_FILE, MERGER, BNF28}, {LT, MERGER, BNF28}, {EQ, MERGER, BNF28},
    {PLUS, MERGER, BNF28}, {MINUS, MERGER, BNF28}, {MULT, MERGER, BNF28},
    {DIV, MERGER, BNF28}
};
static struct action_node status_I22[] =
{
    {KEY_UNTIL, MOVE, I38}, {SEMI, MOVE, I14}
};
static struct action_node status_I23[] =
{
   {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I24[] =
{
    {KEY_ELSE, MERGER, BNF13}, {KEY_END, MERGER, BNF13}, {KEY_UNTIL, MERGER, BNF13},
    {SEMI, MERGER, BNF13}, {END_FILE, MERGER, BNF13}
};
static struct action_node status_I25[] =
{
    {KEY_ELSE, MERGER, BNF14}, {KEY_END, MERGER, BNF14}, {KEY_UNTIL, MERGER, BNF14},
    {SEMI, MERGER, BNF14}, {END_FILE, MERGER, BNF14}
};
static struct action_node status_I26[] =
{
    {KEY_ELSE, MERGER, BNF2}, {KEY_END, MERGER, BNF2}, {KEY_UNTIL, MERGER, BNF2},
    {SEMI, MERGER, BNF2}, {END_FILE, MERGER, BNF2}
};
static struct action_node status_I27[] =
{
    {KEY_IF, MOVE, I9}, {KEY_REPEAT, MOVE, I10}, {KEY_READ, MOVE, I12},
    {KEY_WRITE, MOVE, I13}, {ID, MOVE, I11}
};
static struct action_node status_I28[] =
{
    {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I29[] =
{
    {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I30[] =
{
    {ID, MERGER, BNF17}, {NUM, MERGER, BNF17}, {LPAREN, MERGER, BNF17}
};
static struct action_node status_I31[] =
{
    {ID, MERGER, BNF18}, {NUM, MERGER, BNF18}, {LPAREN, MERGER, BNF18}
};
static struct action_node status_I32[] =
{
    {ID, MERGER, BNF21}, {NUM, MERGER, BNF21}, {LPAREN, MERGER, BNF21}
};
static struct action_node status_I33[] =
{
    {ID, MERGER, BNF22}, {NUM, MERGER, BNF22}, {LPAREN, MERGER, BNF22}
};
static struct action_node status_I34[] =
{
    {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I35[] =
{
    {ID, MERGER, BNF25}, {NUM, MERGER, BNF25}, {LPAREN, MERGER, BNF25}
};
static struct action_node status_I36[] =
{
    {ID, MERGER, BNF26}, {NUM, MERGER, BNF26}, {LPAREN, MERGER, BNF26}
};
static struct action_node status_I37[] =
{
    {RPAREN, MOVE, I44}
};
static struct action_node status_I38[] =
{
    {ID, MOVE, I20}, {NUM, MOVE, I21}, {LPAREN, MOVE, I19}
};
static struct action_node status_I39[] =
{
    {KEY_ELSE, MERGER, BNF12}, {KEY_END, MERGER, BNF12}, {KEY_UNTIL, MERGER, BNF12},
    {SEMI, MERGER, BNF12}, {END_FILE, MERGER, BNF12}
};
static struct action_node status_I40[] =
{
    {KEY_ELSE, MOVE, I47}, {KEY_END, MOVE, I46}, {SEMI, MOVE, I14}
};
static struct action_node status_I41[] =
{
    {KEY_THEN, MERGER, BNF15}, {KEY_ELSE, MERGER, BNF15}, {KEY_END, MERGER, BNF15},
    {KEY_UNTIL, MERGER, BNF15}, {SEMI, MERGER, BNF15}, {RPAREN, MERGER, BNF15},
    {END_FILE, MERGER, BNF15}, {PLUS, MOVE, I32}, {MINUS, MOVE, I33}
};
static struct action_node status_I42[] =
{
    {KEY_THEN, MERGER, BNF19}, {KEY_ELSE, MERGER, BNF19}, {KEY_END, MERGER, BNF19},
    {KEY_UNTIL, MERGER, BNF19}, {SEMI, MERGER, BNF19}, {RPAREN, MERGER, BNF19},
    {END_FILE, MERGER, BNF19}, {LT, MERGER, BNF19}, {EQ, MERGER, BNF19},
    {PLUS, MERGER, BNF19}, {MINUS, MERGER, BNF19}, {MULT, MOVE, I35},
    {DIV, MOVE, I36}
};   
static struct action_node status_I43[] =
{
    {KEY_THEN, MERGER, BNF23}, {KEY_ELSE, MERGER, BNF23}, {KEY_END, MERGER, BNF23},
    {KEY_UNTIL, MERGER, BNF23}, {SEMI, MERGER, BNF23}, {RPAREN, MERGER, BNF23},
    {END_FILE, MERGER, BNF23}, {LT, MERGER, BNF23}, {EQ, MERGER, BNF23},
    {PLUS, MERGER, BNF23}, {MINUS, MERGER, BNF23}, {MULT, MERGER, BNF23},
    {DIV, MERGER, BNF23}
};
static struct action_node status_I44[] =
{
    {KEY_THEN, MERGER, BNF27}, {KEY_ELSE, MERGER, BNF27}, {KEY_END, MERGER, BNF27},
    {KEY_UNTIL, MERGER, BNF27}, {SEMI, MERGER, BNF27}, {RPAREN, MERGER, BNF27},
    {END_FILE, MERGER, BNF27}, {LT, MERGER, BNF27}, {EQ, MERGER, BNF27},
    {PLUS, MERGER, BNF27}, {MINUS, MERGER, BNF27}, {MULT, MERGER, BNF27},
    {DIV, MERGER, BNF27}
};
static struct action_node status_I45[] =
{
    {KEY_ELSE, MERGER, BNF11}, {KEY_END, MERGER, BNF11}, {KEY_UNTIL, MERGER, BNF11},
    {SEMI, MERGER, BNF11}, {END_FILE, MERGER, BNF11}
};
static struct action_node status_I46[] =
{
    {KEY_ELSE, MERGER, BNF9}, {KEY_END, MERGER, BNF9}, {KEY_UNTIL, MERGER, BNF9},
    {SEMI, MERGER, BNF9}, {END_FILE, MERGER, BNF9}
};
static struct action_node status_I47[] =
{
    {KEY_IF, MOVE, I9}, {KEY_REPEAT, MOVE, I10}, {KEY_READ, MOVE, I12},
    {KEY_WRITE, MOVE, I13}, {ID, MOVE, I11}
};
static struct action_node status_I48[] =
{
    {KEY_END, MOVE, I49}, {SEMI, MOVE, I14}
};
static struct action_node status_I49[] =
{
    {KEY_ELSE, MERGER, BNF10}, {KEY_END, MERGER, BNF10}, {KEY_UNTIL, MERGER, BNF10},
    {SEMI, MERGER, BNF10}, {END_FILE, MERGER, BNF10}
};
 
/* goto table */
struct goto_node
{
    TokenType current_status;
    TokenType next_status;
};
static struct goto_node goto_program[] =
{
    {I0, I1}
};
static struct goto_node goto_stmt_sequence[] =
{
    {I0, I2}, {I10, I22}, {I27, I40}, {I47, I48}
};
static struct goto_node goto_statement[] =
{
    {I0, I3}, {I10, I3}, {I14, I26}, {I27, I3}, {I47, I3}
};
static struct goto_node goto_if_stmt[] =
{
    {I0, I4}, {I10, I4}, {I14, I4}, {I27, I4}, {I47, I4}
};
static struct goto_node goto_repeat_stmt[] =
{
    {I0, I5}, {I10, I5}, {I14, I5}, {I27, I5}, {I47, I5}
};
static struct goto_node goto_assign_stmt[] =
{
    {I0, I6}, {I10, I6}, {I14, I6}, {I27, I6}, {I47, I6}
};
static struct goto_node goto_read_stmt[] =
{
    {I0, I7}, {I10, I7}, {I14, I7}, {I27, I7}, {I47, I7}
};
static struct goto_node goto_write_stmt[] =
{
    {I0, I8}, {I10, I8}, {I14, I8}, {I27, I8}, {I47, I8}
};
static struct goto_node goto_exp[] =
{
    {I9, I15}, {I13, I25}, {I19, I37}, {I23, I39}, {I38, I45}
};
static struct goto_node goto_simple_exp[] =
{
    {I9, I16}, {I13, I16}, {I19, I16}, {I23, I16}, {I28, I41}, {I38, I16}
};
static struct goto_node goto_term[] =
{
    {I9, I17}, {I13, I17}, {I19, I17}, {I23, I17}, {I28, I17}, {I29, I42},
    {I38, I17}
};
static struct goto_node goto_comparison_op[] =
{
    {I16, I28}
};
static struct goto_node goto_factor[] =
{
    {I9, I18}, {I13, I18}, {I19, I18}, {I23, I18}, {I28, I18}, {I29, I18},
    {I34, I43}, {I38, I18}
};
static struct goto_node goto_addop[] =
{
    {I16, I29}, {I41, I29}
};
static struct goto_node goto_mulop[] =
{
    {I17, I34}, {I42, I34}
};
 
/* action, go_to and merger function */
static TokenType get_operation(const struct action_node* action_item, int count,
                              TokenType current_token, TokenType* status_bnf);
static TokenType get_next_status(const struct goto_node* goto_item, int count,
                                TokenType current_status);
 
TokenType action(TokenType current_status, TokenType current_token,
                TokenType* status_bnf)
{
    TokenType oper;
    switch(current_status)
    {
    case I0:
       oper = get_operation(status_I0, sizeof(status_I0)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_THEN || current_token == KEY_ELSE ||
              current_token == KEY_END)
           return E0001;
       else if(current_token == KEY_UNTIL)
           return E0002;
       else if(current_token == END_FILE)
           return E0004;
       else
           return E0003;
       break;
    case I1:
       oper = get_operation(status_I1, sizeof(status_I1)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else
           return E0003;
       break;
    case I2:
       oper = get_operation(status_I2, sizeof(status_I2)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I3:
       oper = get_operation(status_I3, sizeof(status_I3)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I4:
       oper = get_operation(status_I4, sizeof(status_I4)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I5:
       oper = get_operation(status_I5, sizeof(status_I5)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
          return E0201;
       else
           return E0003;
       break;
    case I6:
       oper = get_operation(status_I6, sizeof(status_I6)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I7:
       oper = get_operation(status_I7, sizeof(status_I7)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I8:
       oper = get_operation(status_I8, sizeof(status_I8)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I9:
       oper = get_operation(status_I9, sizeof(status_I9)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == LT || current_token == EQ ||
              current_token == PLUS || current_token == MINUS ||
              current_token == MULT || current_token == DIV ||
              current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I10:
       oper = get_operation(status_I10, sizeof(status_I10)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_THEN || current_token == KEY_ELSE ||
              current_token == KEY_END)
           return E0001;
       else if(current_token == KEY_UNTIL)
           return E0002;
       else if(current_token == END_FILE)
           return E1001;
       else
           return E0003;
       break;
    case I11:
       oper = get_operation(status_I11, sizeof(status_I11)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == ID || current_token == NUM ||
              current_token == LPAREN)
           return E1101;
       else if(current_token == END_FILE)
           return E1102;
       else
           return E0003;
       break;
    case I12:
       oper = get_operation(status_I12, sizeof(status_I12)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == SEMI || current_token == END_FILE)
           return E1201;
       else
           return E0003;
       break;
    case I13:
       oper = get_operation(status_I13, sizeof(status_I13)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == SEMI || current_token == LT ||
              current_token == EQ || current_token == PLUS ||
              current_token == MINUS || current_token == MULT ||
              current_token == DIV || current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I14:
       oper = get_operation(status_I14, sizeof(status_I14)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_THEN || current_token == KEY_ELSE ||
              current_token == KEY_END)
           return E0001;
       else if(current_token == KEY_UNTIL)
           return E0002;
       else if(current_token == END_FILE)
           return E1401;
       else
           return E0003;
       break;
    case I15:
       oper = get_operation(status_I15, sizeof(status_I15)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E1501;
       else if(current_token == END_FILE)
           return E1502;
       else
           return E0003;
       break;
    case I16:
       oper = get_operation(status_I16, sizeof(status_I16)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == ID || current_token == NUM ||
              current_token == LPAREN)
           return E1601;
       else
           return E0003;
       break;
    case I17:
       oper = get_operation(status_I17, sizeof(status_I17)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == ID || current_token == NUM ||
              current_token == LPAREN)
           return E1701;
       else
           return E0003;
       break;
    case I18:
       oper = get_operation(status_I18, sizeof(status_I18)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else
           return E0003;
       break;
    case I19:
       oper = get_operation(status_I19, sizeof(status_I19)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == RPAREN || current_token == LT ||
              current_token == EQ || current_token == PLUS ||
              current_token == MINUS || current_token == MULT ||
              current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I20:
       oper = get_operation(status_I20, sizeof(status_I20)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else
           return E0003;
       break;
    case I21:
       oper = get_operation(status_I21, sizeof(status_I21)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else
           return E0003;
       break;
    case I22:
       oper = get_operation(status_I22, sizeof(status_I22)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else if(current_token == NUM || current_token == LPAREN)
           return E2201;
       else if(current_token == END_FILE)
           return E1001;
       else
           return E0003;
       break;
    case I23:
       oper = get_operation(status_I23, sizeof(status_I23)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == SEMI || current_token == LT ||
              current_token == EQ || current_token == PLUS ||
              current_token == MINUS || current_token == MULT ||
              current_token == DIV || current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I24:
       oper = get_operation(status_I24, sizeof(status_I24)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I25:
       oper = get_operation(status_I25, sizeof(status_I25)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I26:
       oper = get_operation(status_I26, sizeof(status_I26)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I27:
       oper = get_operation(status_I27, sizeof(status_I27)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_THEN || current_token == KEY_ELSE ||
              current_token == KEY_END)
           return E0001;
       else if(current_token == KEY_UNTIL)
           return E0002;
       else if(current_token == END_FILE)
           return E2701;
       else
           return E0003;
       break;
    case I28:
       oper = get_operation(status_I28, sizeof(status_I28)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == PLUS || current_token == MINUS ||
              current_token == MULT || current_token == DIV ||
              current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I29:
       oper = get_operation(status_I29, sizeof(status_I29)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == MULT || current_token == DIV ||
              current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I30:
       oper = get_operation(status_I30, sizeof(status_I30)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I31:
       oper = get_operation(status_I31, sizeof(status_I31)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I32:
       oper = get_operation(status_I32, sizeof(status_I32)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I33:
       oper = get_operation(status_I33, sizeof(status_I33)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I34:
       oper = get_operation(status_I34, sizeof(status_I34)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I35:
       oper = get_operation(status_I35, sizeof(status_I35)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I36:
       oper = get_operation(status_I36, sizeof(status_I36)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I37:
       oper = get_operation(status_I37, sizeof(status_I37)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == END_FILE)
           return E3701;
       else
           return E0003;
       break;
    case I38:
       oper = get_operation(status_I38, sizeof(status_I38)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == SEMI || current_token == LT ||
              current_token == EQ || current_token == PLUS ||
              current_token == MINUS || current_token == MULT ||
              current_token == DIV || current_token == END_FILE)
           return E0901;
       else
           return E0003;
       break;
    case I39:
       oper = get_operation(status_I39, sizeof(status_I39)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I40:
       oper = get_operation(status_I40, sizeof(status_I40)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else if(current_token == END_FILE)
           return E4001;
       else
           return E0003;
       break;
    case I41:
       oper = get_operation(status_I41, sizeof(status_I41)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == ID || current_token == NUM ||
              current_token == LPAREN)
           return E4101;
       else
           return E0003;
       break;
    case I42:
       oper = get_operation(status_I42, sizeof(status_I42)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == ID || current_token == NUM ||
              current_token == LPAREN)
           return E1701;
       else
           return E0003;
       break;
    case I43:
       oper = get_operation(status_I43, sizeof(status_I43)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else
           return E0003;
       break;
    case I44:
       oper = get_operation(status_I44, sizeof(status_I44)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else
           return E0003;
       break;
    case I45:
       oper = get_operation(status_I45, sizeof(status_I45)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I46:
       oper = get_operation(status_I46, sizeof(status_I46)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    case I47:
       oper = get_operation(status_I47, sizeof(status_I47)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_THEN || current_token == KEY_ELSE ||
              current_token == KEY_END)
           return E0001;
       else if(current_token == KEY_UNTIL)
           return E0002;
       else if(current_token == END_FILE)
           return E1502;
       else
           return E0003;
       break;
    case I48:
       oper = get_operation(status_I48, sizeof(status_I48)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else if(current_token == END_FILE)
           return E4001;
       else
           return E0003;
       break;
    case I49:
       oper = get_operation(status_I49, sizeof(status_I49)/sizeof(struct action_node),
                           current_token, status_bnf);
       if(oper != ERROR)
           return oper;
       else if(current_token == KEY_IF || current_token == KEY_REPEAT ||
              current_token == KEY_READ || current_token == KEY_WRITE ||
              current_token == ID)
           return E0201;
       else
           return E0003;
       break;
    default:
       fprintf(stderr, "error status!/n");
       exit(-1);
       break;
    }
}
 
static TokenType get_operation(const struct action_node* action_item, int count,
                              TokenType current_token, TokenType* status_bnf)
{
    int i = 0;
    for(i = 0; i < count; i++)
    {
       if(action_item[i].token == current_token)
       {
          *status_bnf = action_item[i].next_status_bnf;
           return action_item[i].action;
       }
    }
 
    return ERROR;
}
 
TokenType go_to(TokenType prev_status, TokenType top_token)
{
    switch(top_token)
    {
    case NES_PROGRAM:
       return get_next_status(goto_program,
                             sizeof(goto_program)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_STMT_SEQUENCE:
       return get_next_status(goto_stmt_sequence,
                             sizeof(goto_stmt_sequence)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_STATEMENT:
       return get_next_status(goto_statement,
                             sizeof(goto_statement)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_IF_STMT:
       return get_next_status(goto_if_stmt,
                             sizeof(goto_if_stmt)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_REPEAT_STMT:
       return get_next_status(goto_repeat_stmt,
                             sizeof(goto_repeat_stmt)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_ASSIGN_STMT:
       return get_next_status(goto_assign_stmt,
                             sizeof(goto_assign_stmt)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_READ_STMT:
       return get_next_status(goto_read_stmt,
                             sizeof(goto_read_stmt)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_WRITE_STMT:
       return get_next_status(goto_write_stmt,
                             sizeof(goto_write_stmt)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_EXP:
       return get_next_status(goto_exp,
                             sizeof(goto_exp)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_SIMPLE_EXP:
       return get_next_status(goto_simple_exp,
                             sizeof(goto_simple_exp)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_TERM:
       return get_next_status(goto_term,
                             sizeof(goto_term)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_COMPARISON_OP:
       return get_next_status(goto_comparison_op,
                             sizeof(goto_comparison_op)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_FACTOR:
       return get_next_status(goto_factor,
                            sizeof(goto_factor)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_ADDOP:
       return get_next_status(goto_addop,
                             sizeof(goto_addop)/sizeof(struct goto_node),
                             prev_status);
       break;
    case NES_MULOP:
       return get_next_status(goto_mulop,
                             sizeof(goto_mulop)/sizeof(struct goto_node),
                             prev_status);
       break;
    default:
       fprintf(stderr, "error non end symbol!/n");
       exit(-1);
       break;
    }
}
 
static TokenType get_next_status(const struct goto_node* goto_item, int count,
                                TokenType current_status)
{
    int i = 0;
    for(i = 0; i < count; i++)
    {
       if(goto_item[i].current_status == current_status)
           return goto_item[i].next_status;
    }
 
    return ERROR;
}
 
TokenType merger(TokenType bnf_id, int* number)
{
    int i = 0;
    for(i = 0; i < sizeof(bnf_map)/sizeof(TokenType); i++)
    {
       if(bnf_map[i] == bnf_id)
           break;
    }
 
    if(i < sizeof(bnf_map)/sizeof(TokenType))
    {
       *number = TINY_BNF[i].count;
       return TINY_BNF[i].nes;
    }
    else
       return ERROR;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值