嗨,我正在研究一个小野牛,以了解它是如何工作的.野牛应该解析一个句子.句子由表达式组成,表达式由单词组成.
以下是我的代码:
%{
#include <stdio.h>
#include <string.h>
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
}
%}
%token ASSIGN RANGE OR AND WHITESPACE QUOTE LPAREN RPAREN NOT GREATER LESS
%union
{
int number;
char *string;
}
%token <number> VALUE
%token <string> WORD
%type <string> term
%type <string> expression
%%
query: /* empty */
| query expression
{
printf("WOrd:%s",$2);
}
;
expression:
term
|expression term
|expression AND term
{
printf("AND");
}
;
term:
WORD
{
$$=$1;
}
;
Run Code Online (Sandbox Code Playgroud)
因此,当用户输入单词时,它应该打印出单词.用户应该能够输入:单词,单词,单词和单词
我不确定如何使用$$传递一个单词并将其从"查询表达式"规则中打印出来.我该怎么做呢?
这是我的flex:
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
%}
%%
[0-9]+ yylval.number=atoi(yytext);return VALUE;
[a-zA-Z][a-zA-Z]* yylval.string=strdup(yytext);return WORD;
":" return ASSIGN;
"and"|"&"|"&&" return AND;
".." return RANGE;
"-" return NOT;
"|" return OR;
"\"" return QUOTE;
">" return GREATER;
"<" return LESS;
\n /* ignore end of line */;
\t /* ignore end of line */;
%%
Run Code Online (Sandbox Code Playgroud)
提前谢绝了这么多.莎拉
通常,编写解析器的目的是让您最终得到一个表示输入的数据结构.然后以某种方式转换结构,或者,在您的情况下,只需将其打印出来.
在每个表达式生成中,您希望在该结构中构造一个节点,该节点表示到目前为止您已识别的内容.
我有点生疏,但它会是这样的:
query: /* empty */
| query expression { printNode($2); /* printf()s are in here */ }
;
expression: term { $$ = makeTermNode($1); }
| expression OR term { $$ = makeOrNode($1, $3); }
| expression AND term { $$ = makeAndNode($1, $3); }
;
Run Code Online (Sandbox Code Playgroud)
用于保存节点的数据结构:
struct Node {
int nodeType; /* WORD or operator token like AND, OR */
node* leftOperand;
node* rightOperand; /* will be null if the node is a term */
}
%union
{
int number;
char *string;
Node *node;
}
Run Code Online (Sandbox Code Playgroud)
更新:
我用C编码已经有一段时间了,所以我不得不求助于伪代码.这里没有代码可以在我们完成后回收内存.对任何其他错误道歉.
struct Node *makeTermNode(int word) {
Node *node = malloc(sizeof struct Node);
node->nodeType = word;
node->rightOperand = null;
node->leftOperand = null;
return node;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您的WORD令牌只表示扫描了一串某些字母; 字母的特定顺序被丢弃.(如果您想知道序列,请让词法分析器返回yytext的副本而不是WORD标记.)
struct Node *makeAndNode(struct Node* leftOperand, struct Node *rightOperand) {
Node *node = malloc(sizeof struct Node);
node->nodeType = AND;
node->leftOperand = leftOperand;
node->rightOperand = rightOperand;
return node;
}
Run Code Online (Sandbox Code Playgroud)
同样适用于makeOrNode().或者,您可以只编写makeNodeWithOperator(int运算符,struct Node*leftOperand,struct Node*rightOperand)来处理"和"和"或"情况.
我将printAllNodes()更改为printNode().它从我们构建的表达式树结构的根开始,首先递归访问每个子表达式的左侧,然后是右侧.它是这样的:
void printNode (struct Node* node) {
switch (node->nodeType) {
case WORD:
printf("%i", node->nodeType);
return;
case AND:
case OR:
printf("(");
printNode(node->leftOperand);
printf("%i", node->nodeType);
printfNode(node->rightOperand);
printf(")");
return;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7037 次 |
| 最近记录: |