首页 > 解决方案 > 使用 BNFC 确定命题逻辑的基本语言(语法错误)

问题描述

我想使用 BNFC 解析命题逻辑中的句子。我编写了以下 BNF 语法来促进这一点:

Negation.     N ::= "(" "-" L")";
Conjuction.   C ::= "(" L "&" L ")";
Disjuction.   D ::= "(" L "|" L ")";
Implication.  I ::= "(" L "=>" L ")";
Equivalence.  E ::= "(" L "<=>" L ")";
Atom.         L ::= Ident | N | C | D | I | E ;

但是,通过这种结构,我得到以下错误:

syntax error at line 6, column 27 before `|'

我提供的规范在语法上是不正确的?

编辑 1

好的,所以看起来bnfc真的不喜欢使用|联合符号的想法。如果不通过联合,我如何将多个产品分配给单个规则?我不想定义Atom1. L ::= Ident ;Atom2. L ::= N ;等等,但是如果我想让它起作用,这是否必要?

编辑 2

好的,所以给每个产品不同的标签L,如

Negation.     N ::= "(" "-" L")";
Conjuction.   C ::= "(" L "&" L ")";
Disjuction.   D ::= "(" L "|" L ")";
Implication.  I ::= "(" L "=>" L ")";
Equivalence.  E ::= "(" L "<=>" L ")";
Atom1.        L ::= Ident ;
Atom2.        L ::= N ;
Atom3.        L ::= C ;
Atom4.        L ::= D ;
Atom5.        L ::= I ;
Atom6.        L ::= E ;

允许文件logic.cf通过bnfc而没有任何错误。但是,当使用命令编译文件时

bnfc -m -c file.cf

然后我尝试运行make,当 Make 尝试gcc在 bnfc 生成的文件上运行时出现以下错误Printer.c

gcc -g -W -Wall -c Absyn.c
flex -Plogic -oLexer.c logic.l
gcc -g -W -Wall -c Lexer.c 
Lexer.c:1477:16: warning: ‘input’ defined but not used [-Wunused-function]
     static int input  (void)
                ^~~~~
Lexer.c:1434:17: warning: ‘yyunput’ defined but not used [-Wunused-function]
     static void yyunput (int c, char * yy_bp )
                 ^~~~~~~
bison -t -plogic logic.y -o Parser.c
gcc -g -W -Wall -c Parser.c
gcc -g -W -Wall -c Printer.c
Printer.c: In function ‘ppL’:
Printer.c:289:20: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     ppIdent(_p_->u.atom_.ident_, 0);
                    ^~~~~
                    atom1_
Printer.c:296:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     ppN(_p_->u.atom_.n_, 0);
                ^~~~~
                atom1_
Printer.c:303:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     ppC(_p_->u.atom_.c_, 0);
                ^~~~~
                atom1_
Printer.c:310:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     ppD(_p_->u.atom_.d_, 0);
                ^~~~~
                atom1_
Printer.c:317:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     ppI(_p_->u.atom_.i_, 0);
                ^~~~~
                atom1_
Printer.c:324:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     ppE(_p_->u.atom_.e_, 0);
                ^~~~~
                atom1_
Printer.c: In function ‘ppInteger’:
Printer.c:336:31: warning: unused parameter ‘i’ [-Wunused-parameter]
 void ppInteger(Integer n, int i)
                               ^
Printer.c: In function ‘ppDouble’:
Printer.c:342:29: warning: unused parameter ‘i’ [-Wunused-parameter]
 void ppDouble(Double d, int i)
                             ^
Printer.c: In function ‘ppChar’:
Printer.c:348:25: warning: unused parameter ‘i’ [-Wunused-parameter]
 void ppChar(Char c, int i)
                         ^
Printer.c: In function ‘ppString’:
Printer.c:354:29: warning: unused parameter ‘i’ [-Wunused-parameter]
 void ppString(String s, int i)
                             ^
Printer.c: In function ‘ppIdent’:
Printer.c:360:28: warning: unused parameter ‘i’ [-Wunused-parameter]
 void ppIdent(String s, int i)
                            ^
Printer.c: In function ‘shL’:
Printer.c:507:20: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     shIdent(_p_->u.atom_.ident_);
                    ^~~~~
                    atom1_
Printer.c:522:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     shN(_p_->u.atom_.n_);
                ^~~~~
                atom1_
Printer.c:537:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     shC(_p_->u.atom_.c_);
                ^~~~~
                atom1_
Printer.c:552:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     shD(_p_->u.atom_.d_);
                ^~~~~
                atom1_
Printer.c:567:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     shI(_p_->u.atom_.i_);
                ^~~~~
                atom1_
Printer.c:582:16: error: ‘union <anonymous>’ has no member named ‘atom_’; did you mean ‘atom1_’?
     shE(_p_->u.atom_.e_);
                ^~~~~
                atom1_
Makefile:42: recipe for target 'Printer.o' failed
make: *** [Printer.o] Error 1

我不知道这是什么意思。为什么要查找atom_,当我没有在 中指定这样的事情时,logic.cf如果有任何人对 的内部有更丰富的经验bnfc,我不介意收到你的来信。

编辑 3

好的,所以将标签写为

Negation.     N ::= "(" "-" L ")";
Conjuction.   C ::= "(" L "&" L ")";
Disjuction.   D ::= "(" L "|" L ")";
Implication.  I ::= "(" L "=>" L ")";
Equivalence.  E ::= "(" L "<=>" L ")";
Atom.         L ::= Ident;
AtomN.        L ::= N ;
AtomC.        L ::= C ;
AtomD.        L ::= D ;
AtomI.        L ::= I ;
AtomE.        L ::= E ;

莫名其妙地被允许make通过。但是,我的解析器并不能完全正常工作,就像这样简单

echo "p" | ./Testlogic

返回

error: line 1: syntax error at p

不是p一个有效的标识符,所以生产Atom. L ::= Ident;应该允许它通过?为什么不是这样?

标签: syntaxsyntax-errorbnfc

解决方案


第一个非终结符被认为是解析器的入口点,除非您使用entrypoint指令声明入口点。这就解释了为什么Edit 3还没有工作。


推荐阅读