Flex 和 Bison 不接受输入文件

问题描述 投票:0回答:1

我正在为一个班级编写一个 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 从文件中读取的问题。 有人可以帮我解决这个问题吗?

c parsing flexbox bison
1个回答
0
投票

至少出现这个错误:

目的地错误

// strcpy(varName, node->varName);
strcpy(node->varName, varName);

更好的代码会使用类似的大小限制

if (snprintf(node->varName, sizeof node->varName, "%s", varName) >= sizeof node->varName){
  Handle_Error();
}
© www.soinside.com 2019 - 2024. All rights reserved.