Использование BNF C для определения базового c языка для логик высказываний c (синтаксическая ошибка) - PullRequest
0 голосов
/ 11 апреля 2020

Я бы хотел разобрать предложения в логах высказываний c, используя BNF C. Я написал следующую грамматику 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 `|'

Что синтаксически неверно в предоставленной мной спецификации?

Edit 1

Хорошо, похоже, bnfc действительно не нравится идея использовать символ | для объединения. Как тогда назначить несколько продукций одному правилу, если не через объединение? Я не хочу определять Atom1. L ::= Ident ;, Atom2. L ::= N ; и т. Д., Но необходимо ли это, если я хочу, чтобы это работало?

Edit 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 на сгенерированном bnf c файле 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; должно позволить это пройти? Почему это не так?

1 Ответ

0 голосов
/ 11 апреля 2020

Оказывается, БНФ C немного придирчив, когда речь идет о порядке производства. Мне пришлось написать

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

в дополнение к избавлению от цифр на концах этикеток, чтобы это работало. Теперь я могу анализировать простые предложения в логике предикатов c:

$ echo "(a&(a<=>b))" | ./Testlogic 

Parse Succesful!

[Abstract Syntax]
(AtomC [(Conjuction (Atom ["a"]) (AtomE [(Equivalence (Atom ["a"]) (Atom ["b"]))]))])

[Linearized Tree]
(a  & (a <=> b))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...