Flex和Bison,使用符号表的Windows错误

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

程序旨在将值存储在符号表中,然后将它们打印出来,说明词性。进一步在解析器中进行解析和说明,无论是句子还是更多。

我通过创建可执行文件

flex try1.l
bison -dy try1.y
gcc lex.yy.c y.tab.c -o try1.exe

在cmd(WINDOWS)

当我在运行可执行文件时尝试声明任何值时出现我的问题,动词运行就像这样BOLD IS INPUT

动词运行 跑 跑 语法错误 名词猫 猫 语法错误 跑 跑 语法错误 猫跑 语法错误

我的想法:我不确定为什么我从代码语法错误中得到这个错误。虽然经过调试并试图打印出存储的值,但我认为链表必须存在某种问题。因为似乎只有一个值存储在链表中并导致排序错误。当我试图打印出存储的word_type整数值时,它会打印出正确的值259,但是会拒绝让我为符号表定义任何其他单词。我推翻了打印语句的更改,现在它的工作方式如前所述。我想再次使用addword方法存在一个问题,因为它没有正确添加,因此查找方法会导致程序崩溃。

Lexer文件,这个例子来自O'Reily第二版Lex And Yacc,例1-5-1-6。我试图自己学习Lex和Yacc并重现这个例子。

%{
/*
* We now build a lexical analyzer to be used by a higher-level parser.
*/
#include <stdlib.h>
#include <string.h>
#include "ytab.h" /* token codes from the parser */
#define LOOKUP 0 /* default - not a defined word type. */
int state;
%}
/* 
*  Example from page 9 Word recognizer with a symbol table. PART 2 of Lexer
*/
%%
\n { state = LOOKUP; } /* end of line, return to default state */
    \.\n { state = LOOKUP;
    return 0; /* end of sentence */
    }
        /* whenever a line starts with a reserved part of speech name */
        /* start defining words of that type */
        ^verb { state = VERB; }
        ^adj { state = ADJ; }
        ^adv { state = ADV; }
        ^noun { state = NOUN; }
        ^prep { state = PREP; }
        ^pron { state = PRON; }
        ^conj { state = CONJ; }
        [a-zA-Z]+ {
            if(state != LOOKUP) {
            add_word(state, yytext);
            } else {
                switch(lookup_word(yytext)) {
                case VERB:
                return(VERB);
                case ADJECTIVE:
                return(ADJECTIVE);
                case ADVERB:
                return(ADVERB);
                case NOUN:
                return(NOUN);
                case PREPOSITION:
                return(PREPOSITION);
                case PRONOUN:
                return(PRONOUN);
                case CONJUNCTION:
                return(CONJUNCTION);
                default:
                printf("%s: don't recognize\n", yytext);
                /* don't return, just ignore it */
                    }
                    }
               }
        . ;
%%
int yywrap()
{
return 1;
}
/* define a linked list of words and types */
struct word {
        char *word_name;
        int word_type;
        struct word *next;
};
struct word *word_list; /* first element in word list */
extern void *malloc() ;
int
add_word(int type, char *word)
    {
    struct word *wp;
        if(lookup_word(word) != LOOKUP) {
        printf("!!! warning: word %s already defined \n", word);
        return 0;
        }
    /* word not there, allocate a new entry and link it on the list */
    wp = (struct word *) malloc(sizeof(struct word));
    wp->next = word_list;
    /* have to copy the word itself as well */
    wp->word_name = (char *) malloc(strlen(word)+1);
    strcpy(wp->word_name, word);
    wp->word_type = type;
    word_list = wp;
    return 1; /* it worked */
    }
    int
    lookup_word(char *word)
    {
    struct word *wp = word_list;
    /* search down the list looking for the word */
    for(; wp; wp = wp->next) {
        if(strcmp(wp->word_name, word) == 0)
        return wp->word_type;
    }
return LOOKUP; /* not found */
}

Yacc文件,

%{
/*
* A lexer for the basic grammar to use for recognizing English sentences.
*/
#include <stdio.h>
%}
%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION CONJUNCTION
%%
sentence: subject VERB object{ printf("Sentence is valid.\n"); }
;
subject: NOUN
| PRONOUN
;
object: NOUN
;
%%
extern FILE *yyin;
main()
{
do
{
yyparse();
}
while (!feof(yyin));
}
yyerror(s)
char *s;
{
fprintf(stderr, "%s\n", s);
}

头文件,必须为某些值创建2个版本,不知道为什么但是代码与它们有问题,我不明白为什么所以我只是创建了一个带有全名的令牌而缩短了因为这本书只有一个每。

# define NOUN 257
# define PRON 258
# define VERB 259
# define ADVERB 260
# define ADJECTIVE 261
# define PREPOSITION 262
# define CONJUNCTION 263
# define ADV 260
# define ADJ 261
# define PREP 262
# define CONJ 263
# define PRONOUN 258
c windows debugging bison flex-lexer
1个回答
1
投票
  1. 如果您觉得链接列表实现存在问题,那么使用简单的驱动程序测试和调试它会好得多,而不是尝试使用一些您仍在学习的工具(flex和bison) 。总的来说,测试越简单,它所依赖的依赖性越少,就越容易追踪问题。有关调试的一些建议,请参阅this useful essay by Eric Clippert
  2. 我不明白为什么你觉得需要引入令牌ID的“短版本”。 Levine的书中的示例代码并没有使用这些符号。你不能只是发明符号,你不需要这些缩写。 您必须为某些值创建[头文件]的2个版本的评论“但是”代码与它们有问题,我不明白为什么“对于答案来说太过不明确了。也许问题是您认为可以使用未在任何地方定义的标识符,这肯定会导致编译器错误。但是如果还有其他问题,你可以问一个问题,准确的问题描述(也就是你遇到的问题)和Minimal, Complete, and Verifiable example(如StackOverflow帮助页面所示)。 在任何情况下,手动设置令牌ID的值几乎肯定会阻止您识别输入。 Bison / yacc为内部令牌保留值256和257,因此将生成的第一个(因此在解析器中使用)值为258.这意味着您从词法扫描器返回的令牌值具有不同的含义在野牛里面。底线:永远不要手动设置标记值。如果未正确生成标题,请找出原因。
  3. 据我所知,您的程序的唯一合法输入具有以下形式: sentence: subject VERB object 由于没有任何样本输入(例如“run”)具有此形式,因此语法错误并不令人惊讶。但是,您在输入“cat”上收到非常早期的语法错误这一事实确实表明您的符号表查找可能存在问题。 (这可能是上述问题的结果。)
© www.soinside.com 2019 - 2024. All rights reserved.