野牛中NOT令牌的分配

Distribution of NOT token in bison

本文关键字:分配 令牌 NOT      更新时间:2023-10-16

给定一个用C++编写的if条件(只有条件部分)的输入,我想根据De Morgan定律分配"nots"。问题是,根据我的规则,递归不允许我在找到符号"!"时立即获得括号内的表达式,然后我可以分发。让我用一个例子来解释:

输入:(!(a&&(b&&!(c&&d))))

输出(在找到每个令牌的时间内):c AND d ) ( b AND NOT b ) ( a AND ) ( ) ( NOT

输出被递归无序了,但是在这种情况下,我该如何应用德摩根定律?,在这个输入的情况下,我想得到:

(!(a&&(b&&!(c&&d))))->(!a&&!(b&&!(c&&d)))->(!a&&b&&(c||d))

请注意,每次我找到一个!令牌时,都会立即在下一个括号中使用分布。如果我得到(!a&&b),我不必使用它,只有当我找到!(作为下一个符号时。

所以,问题是:我无法在下一组条件中分发!令牌,因为我正在无序地获得所有令牌。

这是可能的吗?,我如何定义我的规则来执行此操作?

主.cpp:

#include <iostream>
#include <string>
#include "lex.yy.c"
using namespace std;
typedef yy_buffer_state *YY_BUFFER_STATE;
extern int yyparse();
extern YY_BUFFER_STATE yy_scan_buffer(char *, size_t);
int main(int argc, char** argv) {
    char condition[] = "(!(a&&(b&&!(c&&d)))) ";
    yy_scan_buffer(condition, sizeof(condition));
    yyparse();
    return 0;
}

scanner.l:

%option noyywrap
%{
    #include <iostream>
    #include "parser.tab.c"
    using namespace std;
%}
%%
[a-zA-Z0-9<>=]+  {
    yylval = strdup(yytext);
    return SYMBOL;
}
"&&" {
    return AND;
}
"||" {
    return OR;
}
"!" {
    return NOT;
}
[ ] {
    return END;
}
"("     {
    return LEFT_PAR;
}
")"     {
    return RIGHT_PAR;
}
%%

野牛:

%{
    #include <iostream>
    #include <string>
    using namespace std;
    int yylex(void);
    void yyerror(char *);
    #define YYSTYPE string
%}
%token  LEFT_PAR
        RIGHT_PAR
        SYMBOL
        END
        NOT
%left
        AND
        OR
%start input
%%
input:
    |   input terms
;
terms:
        LEFT_PAR terms close_terms        {  
            cout << " ( ";
        }
    |   LEFT_PAR condition close_terms       {  
            cout << " ( ";
        }
    |   LEFT_PAR NOT condition close_terms   {
            cout << " ( NOT ";
        }
    |   LEFT_PAR NOT terms close_terms    {
            cout << " ( NOT ";
        }
;
close_terms:
    RIGHT_PAR { 
        cout << " ) ";
    }
;
binary_condition:
        terms AND terms   { 
            cout << " AND ";
        }
    |   SYMBOL AND terms    {
            cout << $1 << " AND ";
        }
    |   SYMBOL AND NOT terms {
            cout << $1 << " AND NOT " << $3;
        }
    |   terms AND SYMBOL    {
            cout << " AND " << $3;
        }
    |   SYMBOL AND SYMBOL     {
            cout << $1 << " AND " << $3;
        }
    |   SYMBOL AND NOT SYMBOL {
            cout << $1 << " AND NOT " << $4;
        }

    |   terms OR terms    { 
            cout << " OR ";
        }
    |   SYMBOL OR terms     {
            cout << $1 << " OR ";
        }
    |   SYMBOL OR NOT terms {
            cout << $1 << " OR NOT ";
        }
    |   terms OR SYMBOL     {
            cout << " OR " << $3;
        }
    |   SYMBOL OR SYMBOL      {
            cout << $1 << " OR " << $3;
        }
    |   SYMBOL OR NOT SYMBOL {
            cout << $1 << " OR NOT " << $4;
        }
;

condition:
        SYMBOL                         {
            cout << $1;
        }          
    |   binary_condition
    |   binary_condition AND condition  
    |   binary_condition OR condition
;
%%
void yyerror(char *s) {
}

谢谢!

通常最有意义的是,对于要解析的内容,使语法尽可能简单,然后将要进行的任何转换视为解析树上的转换,而不是尝试以某种方式更改语法。 在你的情况下,你有一个非常混乱的语法 - 你已经AND和右递归OR优先级相等(尽管%left声明没有效果,因为它没有冲突可以解决。

因此,您从表达式的简单语法开始:

%left '|'
%left '&'   /* & and | are left recursive, with & having higher precedence */
%%
input: /* empty */ | input expr 'n' ;
expr: SYMBOL | '(' expr ')' | '!' expr | expr '&' expr | expr '|' expr

然后,添加规则以生成表达式树数据结构并对其进行转换:

input: /* empty */ | input expr 'n' { PrintExpr(ConvertToNormalForm($2)); }
expr: SYMBOL { $$ = CreateSymbolNode($1); }
    | '(' expr ')' { $$ = $2; }
    | '!' expr { $$ = CreateUnaryNode('!', $2); }
    | expr '&' expr { $$ = CreateBinaryNode('&', $1, $3); }
    | expr '|' expr { $$ = CreateBinaryNode('|', $1, $3); }