Flex and Bison, ошибка Windows при использовании таблицы символов - PullRequest
0 голосов
/ 20 февраля 2019

Программа предназначена для хранения значений в таблице символов и последующей возможности их распечатки с указанием части речи.Далее нужно разобрать и указать больше в парсере, будь то предложение и т. Д.

Я создаю исполняемый файл с помощью

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

в cmd (WINDOWS)

Моя проблема возникает, когда я пытаюсь объявить какое-либо значение при запуске исполняемого файла, глагол run он выглядит следующим образом: BOLD IS INPUT

глагол run
run
run

синтаксическая ошибка
существительное cat
cat

синтаксическая ошибка
run
run

синтаксическая ошибка
cat run
синтаксическая ошибка

МОИ МЫСЛИ: я не уверен, почему я получаю эту ошибку обратно из кода Синтаксическая ошибка.Хотя после отладки и попытки распечатать, какое значение хранилось, я решил, что со связанным списком должна быть какая-то проблема.Как казалось, только одно значение сохранялось в связанном списке и вызывало какую-то ошибку.Поскольку я пытался распечатать сохраненное целочисленное значение word_type для run, он выводил бы правильное значение 259, но отказывался позволять мне определять любые другие слова в моей таблице символов.Я отменил изменения печатных операторов, и теперь это работает, как указано ранее.Я снова думаю, что есть проблема с методом addword, так как он не добавляется должным образом, поэтому метод поиска приводит к сбою программы.

Файл Lexer, этот пример взят из O'Reily 2nd edition на Lex AndYacc, пример 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

1 Ответ

0 голосов
/ 20 февраля 2019
  1. Если вы чувствуете, что есть проблема с реализацией вашего связанного списка, вам будет гораздо лучше протестировать и отладить его с помощью простой программы-драйвера, чем пытаться сделать это с помощью некоторых инструментов (гибкость и бизон), которую вы все еще изучаете.В целом, чем проще тест и чем меньше у него зависимостей, тем легче отследить проблемы.См. это полезное эссе Эрика Клипперта с некоторыми советами по отладке.

  2. Я не понимаю, почему вы почувствовали необходимость ввести "короткие версии" токенаидентификаторы.Пример кода в книге Левина нигде не использует эти символы.Вы не можете просто придумывать символы, и вам не нужны эти сокращения ни для чего.

    Комментарий о том, что вам "нужно было создать 2 версии [файла заголовка] для некоторых значений", но что "код имелСпорить с ними, и я не понимаю, почему "слишком неопределенным для ответа.Возможно, проблема заключалась в том, что вы думали, что можете использовать идентификаторы, которые нигде не определены, что, несомненно, приведет к ошибке компилятора.Но если есть какая-то другая проблема, вы можете задать вопрос с точным описанием проблемы (то есть, именно с какой проблемой вы столкнулись) и Минимальный, Полный и Проверяемый пример (как указано в справке StackOverflowстраниц).

    В любом случае, ручная установка значений идентификаторов токенов почти наверняка , что не позволяет вам распознать вводимые данные.Bison / yacc резервирует значения 256 и 257 для внутренних токенов, поэтому первый из них, который будет сгенерирован (и, следовательно, использован в синтаксическом анализаторе), имеет значение 258. Это означает, что значения токенов, которые вы возвращаете из лексического сканера, имеют другое значениевнутри бизонаИтог: Никогда установить значения токенов вручную.Если ваш заголовок генерируется неправильно, выясните, почему.

  3. Насколько я вижу, единственный допустимый ввод для вашей программы имеет форму:

    sentence: subject VERB object
    

    Поскольку ни один из ваших примеров ввода (например, "run") не имеет этой формы, синтаксическая ошибка не удивительна.Однако тот факт, что вы получили очень раннюю синтаксическую ошибку на входе "cat", наводит на мысль, что может быть проблема с поиском в таблице символов.(Это, вероятно, результат проблемы, отмеченной выше.)

...