在这个yacc解析器中,为什么在减少后不结束解析?


s       :type fname OPEN_P param CLOSE_P NEW_LINE OPEN_F NEW_LINE s CLOSE_F                     {check=1;}  
    |fname OPEN_P call CLOSE_P SEMI_COLON                   {if(npd != npc) printf("No of parameters don't matchn");}
    |type vars SEMI_COLON
    |VAR EQL NUM SEMI_COLON
    |RETURN VAR SEMI_COLON NEW_LINE

我得到如下解析输出文件

Terminals unused in grammar
KEY_WORD
OPEN_S
CLOSE_S
STAR

State 18 conflicts: 1 shift/reduce
State 19 conflicts: 1 shift/reduce

Grammar
0 $accept: s $end
1 s: type fname OPEN_P param CLOSE_P NEW_LINE OPEN_F NEW_LINE s CLOSE_F
2  | fname OPEN_P call CLOSE_P SEMI_COLON
3  | type vars SEMI_COLON
4  | VAR EQL NUM SEMI_COLON
5  | RETURN VAR SEMI_COLON NEW_LINE
6  | OPEN_F
7  | CLOSE_F
8 vars: VAR
9     | VAR COMMA vars
10 fname: VAR
11 type: VTYPE
12     | type pointer
13     | type ar
14 ar: '[' ']'
15   | ar '[' ']'
16 pointer: '*'
17        | pointer '*'
18 param: type VAR
19      | type VAR COMMA param
20 call: VAR
21     | VAR COMMA call

Terminals, with rules where they appear
$end (0) 0
'*' (42) 16 17
'[' (91) 14 15
']' (93) 14 15
error (256)
VAR (258) 4 5 8 9 10 18 19 20 21
VTYPE (259) 11
NUM (260) 4
RETURN (261) 5
KEY_WORD (262)
EQL (263) 4
SEMI_COLON (264) 2 3 4 5
OPEN_P (265) 1 2
CLOSE_P (266) 1 2
OPEN_F (267) 1 6
CLOSE_F (268) 1 7
OPEN_S (269)
CLOSE_S (270)
COMMA (271) 9 19 21
STAR (272)
NEW_LINE (273) 1 5

Nonterminals, with rules where they appear
$accept (22)
on left: 0
s (23)
on left: 1 2 3 4 5 6 7, on right: 0 1
vars (24)
on left: 8 9, on right: 3 9
fname (25)
on left: 10, on right: 1 2
type (26)
on left: 11 12 13, on right: 1 3 12 13 18 19
ar (27)
on left: 14 15, on right: 13 15
pointer (28)
on left: 16 17, on right: 12 17
param (29)
on left: 18 19, on right: 1 19
call (30)
on left: 20 21, on right: 2 21

State 0
0 $accept: . s $end
VAR      shift, and go to state 1
VTYPE    shift, and go to state 2
RETURN   shift, and go to state 3
OPEN_F   shift, and go to state 4
CLOSE_F  shift, and go to state 5
s      go to state 6
fname  go to state 7
type   go to state 8

State 1
4 s: VAR . EQL NUM SEMI_COLON
   10 fname: VAR .
EQL  shift, and go to state 9
$default  reduce using rule 10 (fname)

State 2
   11 type: VTYPE .
$default  reduce using rule 11 (type)

State 3
5 s: RETURN . VAR SEMI_COLON NEW_LINE
VAR  shift, and go to state 10

State 4
6 s: OPEN_F .
$default  reduce using rule 6 (s)

State 5
7 s: CLOSE_F .
$default  reduce using rule 7 (s)

State 6
0 $accept: s . $end
$end  shift, and go to state 11

State 7
2 s: fname . OPEN_P call CLOSE_P SEMI_COLON
OPEN_P  shift, and go to state 12

State 8
1 s: type . fname OPEN_P param CLOSE_P NEW_LINE OPEN_F NEW_LINE s CLOSE_F
3  | type . vars SEMI_COLON
   12 type: type . pointer
   13     | type . ar
VAR  shift, and go to state 13
'['  shift, and go to state 14
'*'  shift, and go to state 15
vars     go to state 16
fname    go to state 17
ar       go to state 18
pointer  go to state 19

State 9
4 s: VAR EQL . NUM SEMI_COLON
NUM  shift, and go to state 20

State 10
5 s: RETURN VAR . SEMI_COLON NEW_LINE
SEMI_COLON  shift, and go to state 21

State 11
0 $accept: s $end .
$default  accept

State 12
2 s: fname OPEN_P . call CLOSE_P SEMI_COLON
VAR  shift, and go to state 22
call  go to state 23

State 13
8 vars: VAR .
9     | VAR . COMMA vars
   10 fname: VAR .
COMMA  shift, and go to state 24
OPEN_P    reduce using rule 10 (fname)
$default  reduce using rule 8 (vars)

State 14
   14 ar: '[' . ']'
']'  shift, and go to state 25

State 15
   16 pointer: '*' .
$default  reduce using rule 16 (pointer)

State 16
3 s: type vars . SEMI_COLON
SEMI_COLON  shift, and go to state 26

State 17
1 s: type fname . OPEN_P param CLOSE_P NEW_LINE OPEN_F NEW_LINE s CLOSE_F
OPEN_P  shift, and go to state 27

State 18
   13 type: type ar .
   15 ar: ar . '[' ']'
'['  shift, and go to state 28
'['       [reduce using rule 13 (type)]
$default  reduce using rule 13 (type)

State 19
   12 type: type pointer .
   17 pointer: pointer . '*'
'*'  shift, and go to state 29
'*'       [reduce using rule 12 (type)]
$default  reduce using rule 12 (type)

State 20
4 s: VAR EQL NUM . SEMI_COLON
SEMI_COLON  shift, and go to state 30

State 21
5 s: RETURN VAR SEMI_COLON . NEW_LINE
NEW_LINE  shift, and go to state 31

State 22
   20 call: VAR .
   21     | VAR . COMMA call
COMMA  shift, and go to state 32
$default  reduce using rule 20 (call)

State 23
2 s: fname OPEN_P call . CLOSE_P SEMI_COLON
CLOSE_P  shift, and go to state 33

State 24
9 vars: VAR COMMA . vars
VAR  shift, and go to state 34
vars  go to state 35

State 25
   14 ar: '[' ']' .
$default  reduce using rule 14 (ar)

State 26
3 s: type vars SEMI_COLON .
$default  reduce using rule 3 (s)

State 27
1 s: type fname OPEN_P . param CLOSE_P NEW_LINE OPEN_F NEW_LINE s CLOSE_F
VTYPE  shift, and go to state 2
type   go to state 36
param  go to state 37

State 28
   15 ar: ar '[' . ']'
']'  shift, and go to state 38

State 29
   17 pointer: pointer '*' .
$default  reduce using rule 17 (pointer)

State 30
4 s: VAR EQL NUM SEMI_COLON .
$default  reduce using rule 4 (s)

State 31
5 s: RETURN VAR SEMI_COLON NEW_LINE .
$default  reduce using rule 5 (s)

State 32
   21 call: VAR COMMA . call
VAR  shift, and go to state 22
call  go to state 39

State 33
2 s: fname OPEN_P call CLOSE_P . SEMI_COLON
SEMI_COLON  shift, and go to state 40

State 34
8 vars: VAR .
9     | VAR . COMMA vars
COMMA  shift, and go to state 24
$default  reduce using rule 8 (vars)

State 35
9 vars: VAR COMMA vars .
$default  reduce using rule 9 (vars)

State 36
   12 type: type . pointer
   13     | type . ar
   18 param: type . VAR
   19      | type . VAR COMMA param
VAR  shift, and go to state 41
'['  shift, and go to state 14
'*'  shift, and go to state 15
ar       go to state 18
pointer  go to state 19

State 37
1 s: type fname OPEN_P param . CLOSE_P NEW_LINE OPEN_F NEW_LINE s CLOSE_F
CLOSE_P  shift, and go to state 42

State 38
   15 ar: ar '[' ']' .
$default  reduce using rule 15 (ar)

State 39
   21 call: VAR COMMA call .
$default  reduce using rule 21 (call)

State 40
2 s: fname OPEN_P call CLOSE_P SEMI_COLON .
$default  reduce using rule 2 (s)

State 41
   18 param: type VAR .
   19      | type VAR . COMMA param
COMMA  shift, and go to state 43
$default  reduce using rule 18 (param)

State 42
1 s: type fname OPEN_P param CLOSE_P . NEW_LINE OPEN_F NEW_LINE s CLOSE_F
NEW_LINE  shift, and go to state 44

State 43
   19 param: type VAR COMMA . param
VTYPE  shift, and go to state 2
type   go to state 36
param  go to state 45

State 44
1 s: type fname OPEN_P param CLOSE_P NEW_LINE . OPEN_F NEW_LINE s CLOSE_F
OPEN_F  shift, and go to state 46

State 45
   19 param: type VAR COMMA param .
$default  reduce using rule 19 (param)

State 46
1 s: type fname OPEN_P param CLOSE_P NEW_LINE OPEN_F . NEW_LINE s CLOSE_F
NEW_LINE  shift, and go to state 47

State 47
1 s: type fname OPEN_P param CLOSE_P NEW_LINE OPEN_F NEW_LINE . s CLOSE_F
VAR      shift, and go to state 1
VTYPE    shift, and go to state 2
RETURN   shift, and go to state 3
OPEN_F   shift, and go to state 4
CLOSE_F  shift, and go to state 5
s      go to state 48
fname  go to state 7
type   go to state 8

State 48
1 s: type fname OPEN_P param CLOSE_P NEW_LINE OPEN_F NEW_LINE s . CLOSE_F
CLOSE_F  shift, and go to state 49

State 49
1 s: type fname OPEN_P param CLOSE_P NEW_LINE OPEN_F NEW_LINE s CLOSE_F .
$default  reduce using rule 1 (s)

这是我给的输入文件

*int add(int a)
{
 return a;
}
c=10;
d=20;
add(10);*

我得到这样的输出

您的词法分析器/解析器接口存在一些潜在的问题,但是由于您没有显示词法分析器,因此很难判断。

  • 您有一个令牌STAR,但是您的语法使用'*',因此取决于您的词法分析器返回STAR还是'*',它可能无法工作。您需要一致地使用令牌名称或单字符令牌文字。一般来说,我认为最好总是使用单字符字面量,因为这样更清晰(所以使用'('而不是OPEN_P等)。

  • 您的语法在某些地方需要NEW_LINE标记,但是对于这种语言(带有显式的';'分隔符),您通常希望词法分析器忽略换行符。

您的语法被编写为只接受一个声明,但是您给了它多个声明。人们可能会期望这会导致解析器简单地以Syntax error退出,但可能是词法分析器的问题之一阻止了这种情况的发生。如果你想接受多个声明,你需要你的开始规则像input: /*empty*/ | input declaration ;

在语法中有两个shift/reduce冲突(状态18和19),这是由指针和数组的使用方式的模糊性引起的。简化一下,您有四个与指针相关的规则:

type : VTYPE | type pointer
pointer : '*' | pointer '*'

可以在typepointer上递归,所以当你有一个具有多个*的类型时,它可以以任何一种方式解析它们:

            type                         type
           /                           /    
       type      pointer            type      pointer
        /       /                 /             
     VTYPE    pointer   '*'     type   pointer    '*'
                 |               /        |
                '*'            VTYPE     '*'

你会想要去掉其中一个递归(最简单的是去掉pointerar)。然而,这仍然可能不是您想要的,因为通常(在类似C的语言中),指针和数组修饰符与声明符相关联,而不是类型(因此您可以拥有像int *a, *b;这样的输入)

相关内容

  • 没有找到相关文章

最新更新