我正在为一个班级编写一个 Flex & Bison 程序,我觉得我快完成了。 然而,当我尝试使用输入文件运行程序时,它只是拒绝读取它并让我输入行。
我有两个代码文件:tp2.l(对于 Flex)和 tp2.y(对于 Bison)。 他们的代码如下。
tp2.l(Flex 代码)
%option noyywrap
%{
//#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
#include "tp2.tab.h"
int yylex();
%}
%%
[0-9]+ { printf("%s, integer\n", yytext); yylval.numValue = atoi(yytext); return NUM; }
"+" { printf("%s, operator\n", yytext); return ADD; }
"-" { printf("%s, operator\n", yytext); return SUB; }
"*" { printf("%s, operator\n", yytext); return MUL; }
"/" { printf("%s, operator\n", yytext); return DIV; }
"^" { printf("%s, operator\n", yytext); return POW; }
"=" { printf("equal sign\n"); return EQUAL; }
[a-zA-Z][a-zA-Z0-9]* { strcpy(yylval.stringValue, yytext); printf("%s, variable\n", yytext); return VAR; }
[ \t] {}
"\n" { printf("Newline\n"); yylval.charValue = yytext[0]; return ENDL; }
. { printf("Unknown\n"); return ERR; }
%%
tp2.y(Bison 代码)
%{
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
const int ADDITION = 0;
const int SUBTRACTION = 1;
const int MULTIPLICATION = 2;
const int DIVISION = 3;
const int POWER = 4;
// Node types
const int INSTRUCTION = 0;
const int VALUE = 1;
const int VARIABLE = 2;
int yyerror(const char *s);
extern int yylex();
extern int yyparse();
extern FILE *yyin;
// A parse tree node. Has either a value, instruction, or variable name.
struct ParseNode {
int type;
int value; // Holds numerical value..
char varName[255]; // Holds variable name.
char symbol; // Mathematical symbol
// Branch nodes, can be NULL.
struct ParseNode* left;
struct ParseNode* right;
};
// Node creation functions.
// These create & return a node. If the ROOT is NULL, set the root to the node you created.
// Creates & returns an instruction node.
struct ParseNode *createInstructionNode(char op, struct ParseNode* left, struct ParseNode* right)
{
struct ParseNode* node = (struct ParseNode* )malloc(sizeof(struct ParseNode));
//struct ParseNode node;
node->type = INSTRUCTION;
node->symbol = op;
node->left = left;
node->right = right;
return node;
}
// Creates & returns a value node.
struct ParseNode *createValueNode(int value, struct ParseNode* left, struct ParseNode* right)
{
struct ParseNode* node = (struct ParseNode* )malloc(sizeof(struct ParseNode));
node->type = VALUE;
node->value = value;
node->left = left;
node->right = right;
return node;
}
// Creates & returns a variable node.
struct ParseNode *createVariableNode(char *varName, struct ParseNode* left, struct ParseNode* right)
{
struct ParseNode* node = (struct ParseNode* )malloc(sizeof(struct ParseNode));
node->type = VARIABLE;
node->left = left;
node->right = right;
strcpy(varName, node->varName);
return node;
}
// Calculate the depth of a tree node.
int treeDepth(struct ParseNode *root)
{
if(root == NULL)
{
return 0;
}
else
{
int left_depth = treeDepth(root->left);
int right_depth = treeDepth(root->right);
if(left_depth > right_depth)
return left_depth;
return right_depth;
}
}
// Print a NULL spot in the tree.
void printNull(int depth, int index)
{
if(depth > 0)
{
printNull(depth-1, (index*2));
printNull(depth-1, (index*2) + 1);
}
printf("%d %d \n", depth, index);
}
void printNode(struct ParseNode* root, int depth, int index)
{
// Recurse to lower nodes.
if(depth > 0)
{
if(root->left == NULL)
printNull(depth-1, (index*2));
else
printNode(root->left, depth-1, (index * 2));
if(root->right == NULL)
printNull(depth-1, (index*2) + 1);
else
printNode(root->right, depth-1, (index * 2) + 1);
}
// Print the contents of the node.
printf("%d %d ", depth, index);
if(root == NULL)
{
printf("_");
return;
}
switch(root->type)
{
case 0:
printf("%c", root->symbol);
break;
case 2:
printf("%d", root->value);
break;
default:
printf("%s", root->varName);
break;
}
printf("\n");
}
// Print a tree using postorder traversal.
void printTree(struct ParseNode* root)
{
int depth = treeDepth(root);
printNode(root, depth, 1);
}
void freeTree(struct ParseNode *node)
{
if(node->left != NULL)
freeTree(node->left);
if(node->right != NULL)
freeTree(node->right);
node = NULL;
}
%}
%union{
int numValue;
char stringValue[255];
char charValue;
struct ParseNode *node;
}
// I am sorry I was not able to finish this. I would like to come in for help.
%token <node> NUM VAR EQUAL ADD SUB MUL DIV POW ENDL ERR
%type <node> assign exp term factor
//%type <node> assign exp
//%type <node> input assign exp term factor
%%
input: /* nothing */
| input exp ENDL { printTree($2); freeTree($2); }
;
assign: VAR EQUAL exp { $$ = createInstructionNode('=', $1, $3); }
;
exp: term { $$ = $1; }
| exp ADD exp { $$ = createInstructionNode('+', $1, $3); }
| exp SUB exp { $$ = createInstructionNode('-', $1, $3); }
;
term: factor { $$ = $1; }
| term MUL term { $$ = createInstructionNode('*', $1, $3); }
| term DIV term { $$ = createInstructionNode('/', $1, $3); }
| term POW term { $$ = createInstructionNode('^', $1, $3); }
;
factor: exp { $$ = $1; }
| NUM { $$ = createValueNode($1->value, NULL, NULL); }
| VAR { $$ = createVariableNode($1->varName, NULL, NULL); }
;
%%
int yyerror(const char *s)
{
fprintf(stderr, "error: %s\n", s);
return 0;
}
int main(int argc, char *argv[])
{
yyin = fopen(argv[1], "r");
if(!yyin)
{
perror("File not found.");
return 1;
}
do {
yyparse();
} while( !feof(yyin) );
//yyparse();
fclose(yyin);
return 0;
}
这是我使用的 makefile:
tp2: tp2.l tp2.y
bison -d tp2.y
flex tp2.l
cc -o $@ tp2.tab.c lex.yy.c -lfl
当我使用 ./a.out input.txt 运行它时,它应该尝试逐行读取文件并打印解析树。 相反,它只是要求我在命令行上输入。
我认为这是尝试设置 yyin 从文件中读取的问题。 有人可以帮我解决这个问题吗?
至少出现这个错误:
目的地错误
// strcpy(varName, node->varName);
strcpy(node->varName, varName);
更好的代码会使用类似的大小限制
if (snprintf(node->varName, sizeof node->varName, "%s", varName) >= sizeof node->varName){
Handle_Error();
}