Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing 如何创建应用De Morgan的语法';用yacc把s定理转化为一个表达式?_Parsing_Grammar_Yacc_Lex - Fatal编程技术网

Parsing 如何创建应用De Morgan的语法';用yacc把s定理转化为一个表达式?

Parsing 如何创建应用De Morgan的语法';用yacc把s定理转化为一个表达式?,parsing,grammar,yacc,lex,Parsing,Grammar,Yacc,Lex,我想使用yacc和lex应用于输入 输入可以是任何表达式,如a+b、!(A+B)等: 表达式a+b的结果应该是!A.∙!b 表情!(a+b)应导致a+b 我认为lex部分已经完成了,但是我对将法律应用到表达式所需的yacc语法有困难 我试图实现的是以下算法。将下列方程视为输入:y= a+b 应用德摩根定律后,它变成:!Y=!(A+B) 最后,展开括号应该会导致!Y=!A.∙!B 此处为lex代码: %{ #include <stdio.h> #include "y.tab.h"

我想使用yacc和lex应用于输入

输入可以是任何表达式,如a+b、!(A+B)等:

  • 表达式a+b的结果应该是!A.∙!b
  • 表情!(a+b)应导致a+b
我认为lex部分已经完成了,但是我对将法律应用到表达式所需的yacc语法有困难

我试图实现的是以下算法。将下列方程视为输入:y= a+b

应用德摩根定律后,它变成:!Y=!(A+B)

最后,展开括号应该会导致!Y=!A.∙!B

此处为lex代码:

%{
#include <stdio.h>
#include "y.tab.h"

extern int yylval;
int yywrap (void);
%}

%%
[a-zA-Z]+   {yylval = *yytext; return ALPHABET;}
"&&"        return AND;
"||"        return OR;
"="     return ('=');
[\t]        ;
\n      return 0;
.       return yytext[0];
"0exit"     return 0;
%%

int yywrap (void)
{
    return 1;
}
%{
#包括
#包括“y.tab.h”
外部国际组织;
int-yywrap(无效);
%}
%%
[a-zA-Z]+{yylval=*yytext;返回字母表;}
“&&”返回并返回;
“| |”返回或;
“=”返回(“=”);
[\t];
\n返回0;
.       返回文本[0];
“0退出”返回0;
%%
int-yywrap(无效)
{
返回1;
}
这是我的yacc代码:

%{
#include <stdio.h>

int yylex (void);
void yyerror (char *);
extern FILE* yyin;
%}

%token ALPHABET
%left '+''*'
%right '=' '!' NOT

%left AND OR
%start check

%%
check : expr  {printf("%s\n",$$);}
      ; 
expr : plus
     |plus '+' plus {$$ = $1 + $3;}
     ;
plus : times
     |times '*' times   {$$ = $1 * $3;}
     ;
times : and_op
      |and_op AND and_op{$$ = $1 && $3;}
      ;
and_op : or_op
       |or_op OR or_op  {$$ = $1 || $3;}
       ;
or_op : not_op
      |'!' not_op   {$$ = !$2;}
      ;
not_op : paren
       |'(' paren ')'   {$$ = $2;}
       ;
paren : 
      |ALPHABET     {$$ = $1;}
      ;

/*  
 E: E '+' E     {$$ = $1 + $3;}
  |E '*' E  {$$ = $1 * $3;}
  |E '=' E  {$$ = $1 = $3;}
  |E AND E  {$$ = ($1 && $3);}
  |E OR E   {$$ = ($1 || $3);}
  |'(' E ')'    {$$ = $2;}
  |'!' E %prec NOT {$$ = !$2;}
  |ALPHABET     {$$ = $1;}
  ;*/
%%

int main()
{
    char filename[30];
    char * line = NULL;
    size_t len = 0;
    printf("\nEnter filename\n");
    scanf("%s",filename);
    FILE *fp = fopen(filename, "r");
    if(fp == NULL)
    {
        fprintf(stderr,"Can't read file %s\n",filename);
        exit(EXIT_FAILURE);
    }
    yyin = fp;
//  while (getline(&line, &len, fp) != -1)
//  {
//      printf("%s",line);
//  }
//  printf("Enter the expression:\n");
    do
    {
        yyparse();
    }while(!feof(yyin)); 

    return 0;   
}
%{
#包括
int yylex(无效);
无效错误(字符*);
外部文件*yyin;
%}
%符号字母表
%左'+''*'
%对“=”不
%左或右
%开始检查
%%
检查:expr{printf(“%s\n”,$$);}
; 
expr:加上
|加上“+”加上{$$=$1+$3;}
;
加:次
|时间'*'时间{$$=$1*$3;}
;
泰晤士报:还有
|和_op和_op{$$=$1&&$3;}
;
和_op:或_op
|或_op或_op{$=$1 | |$3;}
;
或_op:不_op
|'!' 不是{$$=!$2;}
;
不,帕伦
|“('paren')”{$$=$2;}
;
帕伦:
|字母表{$$=$1;}
;
/*  
E:E'+'E{$$=$1+$3;}
|E'*'E{$$=$1*$3;}
|E'='E{$$=$1=$3;}
|E和E{$$=($1&&$3);}
|或{$$=($1 | |$3)}
|“('E')”{$$=$2;}
|'!' E%prec不是{$$=!$2;}
|字母表{$$=$1;}
;*/
%%
int main()
{
字符文件名[30];
char*line=NULL;
尺寸长度=0;
printf(“\n输入文件名\n”);
scanf(“%s”,文件名);
FILE*fp=fopen(文件名,“r”);
如果(fp==NULL)
{
fprintf(stderr,“无法读取文件%s\n”,文件名);
退出(退出失败);
}
yyin=fp;
//while(getline(&line,&len,fp)!=-1)
//  {
//printf(“%s”,第行);
//  }
//printf(“输入表达式:\n”);
做
{
yyparse();
}而(!feof(yyin));
返回0;
}

您正在尝试建立一个计算机代数系统

您的任务在概念上很简单:

  • 为“布尔”表达式的原子定义一个lexer
  • 根据词素定义命题逻辑的解析器
  • 构建存储表达式的树
  • 定义实现逻辑等价的过程(DeMorgan定理就是其中之一),通过匹配树结构,在树中找到可以应用逻辑等价的位置,然后相应地修改树
  • 运行这些过程以实现所需的逻辑重写
  • 把最后的答案预先打印出来
  • 但是概念上的简单并不一定意味着容易做到,并且把它做好

    (f) lex和yacc旨在帮助您以相对简单的方式完成步骤1-3;他们的文档包含了一个很好的指南。 他们根本不会帮助完成第4-6步,而这正是真正的工作发生的地方。(你的语法对于这一部分来说似乎是一个很好的开始)

    (您可以在没有flex和yacc的情况下执行1-3)

    第4步可能会很混乱,因为您必须决定要使用哪些逻辑定理,然后为每个定理编写一个过程来进行树匹配和树粉碎,以获得所需的结果。你能做到;它只是一段程序代码,在树上来回走动,比较节点类型和与子节点的关系以进行匹配,然后取消节点链接、删除节点、创建节点并重新链接以实现树修改。这只是一堆代码

    代数重写的一个小把戏现在要咬你了:(布尔)代数有结合算子和交换算子。这意味着一些代数规则将应用于树中任意相距较远的部分。考虑这个规则:

        a*(b + !a) =>  a*(b)
    
    当被解析的实际术语看起来像:

        q*(a + b + c + ... !q ... + z)
    
    查看树的“简单”过程代码现在必须在子树上任意向下走,以找到规则可以应用的位置。突然之间,编码匹配逻辑就不那么容易了,树粉碎也不能实现这种效果

    如果我们忽略关联和交换问题,对于复杂的匹配和修改,代码可能会有点笨拙,难以阅读;一旦你做到了,这将是显而易见的。如果你只想做一次或多次的分解,你可以通过编码相对容易地完成。如果你想实现大量的布尔代数规则来简化,这将是一件痛苦的事情。理想情况下,您希望使用与布尔逻辑相同的表示法来表示逻辑规则,以便它们易于表示,但现在您需要能够读取和解释逻辑规则的东西。这是一段复杂的代码,但如果操作正确,您可以编写如下逻辑规则:

     rule deMorgan_for_or(t1:boolexp, t2:boolexp):boolexp->boolexp
       " ! (\t1 + \t2) " ->   " !\t1 * !\t2 ";
    
    一个相关的问题(步骤5)是,您希望在哪里应用逻辑规则?仅仅因为你可以在一个非常大的逻辑术语中在15个地方应用德摩根定律,并不意味着你一定要这么做。所以在某些地方,你需要有一个控制机制来决定你的许多规则中的哪一条应该适用,以及它们应该适用于哪里。这让你进入元编程,一个全新的话题

    如果你的规则是“单调的”,也就是说,它们实际上只能应用一次,你只需在任何地方运行它们,并得到一个终止计算,如果单调的答案是你想要的。如果您有相反的规则(例如!(x+y)=>!x*!y和!a*!b=>!(a+b)),那么您的规则可能会永远重复运行