Где ошибка в коде синтаксического анализатора?

Есть некий учебный язык, лексический анализатор и синтаксический анализатор для этого языка. Сурс на языке подаётся на вход лексического, затем выходной с лексического подаётся на вход синтаксического. Дело в том, что синтаксический анализатор выдаёт ошибки с тем же кодом, когда у другого человека он проходит без ошибок. Пожалуйста помогите найти ошибки в коде


  begin x, y int; // это сурс на учебном языке
  read x, y; //который не должен давать ошибок
  a2: 
  write x; 
  end

это выходной файл с лексического анализатора

[1, 0] lc: KWBEGIN lv: begin
[1, 3] lc: lexId lv: x
[1, 4] lc: lexComma lv: ,
[1, 6] lc: lexId lv: y
[1, 10] lc: KWINT lv: int
[2, 0] lc: lexSemicolon lv: ;
[2, 5] lc: KWREAD lv: read
[2, 7] lc: lexId lv: x
[2, 8] lc: lexComma lv: ,
[2, 10] lc: lexId lv: y
[3, 0] lc: lexSemicolon lv: ;
[3, 3] lc: lexMetka lv: a2
[4, 0] lc: lexColon lv: :
[4, 6] lc: KWWRITE lv: write
[4, 8] lc: lexId lv: x
[5, 0] lc: lexSemicolon lv: ;
[5, 4] lc: KWEND lv: end
[5, 4] lc: lexEof lv: -1

должно быть так

я не подаю на вход программы параметры, у меня он читает in.txt


Но, у меня выдаёт ошибки

Error! Pos=4 lc=KWINT, lv=int

*я тут сделал, чтоб на вход программы не подавались файлы, а читались/записывались определённые, поэтому там нет input.txt и output.txt


Вот сурсы синтаксического анализатора:


main.cpp


#include <iostream>
#include <string.h>
#include <stdio.h>
#include "type.h"
#include "analys.h"
#pragma warning(disable : 4996)

int main(/* argc, char* argv[]*/)
{
    /*if (argc != 3) {
        printf("\nIncorrect command format!\n");
        printf("\nYou must type: command sourced_file recived_file.\n");
        return 0;
    }
    if ((infil = fopen(argv[1], "r")) == 0) {
        printf("\nInput file is absent!\n"); return false;
    }

    outfil = fopen(argv[2], "w");*/
    setlocale(0,"");
    infil = fopen("in.txt", "r");
    outfil = fopen("out.txt", "w");
    lv = new char* [300];
    for (int i = 0; i < 300; i++)      lv[i] = new char[300];
    lc = new char* [300];
    for (int i = 0; i < 300; i++)      lc[i] = new char[300];
    ilex = new lc_type[300];

    Tr.lex = new lc_type[500];
    Tr.sym = new char* [500];
    for (int i = 0; i < 500; i++)      Tr.sym[i] = new char[500];

    Scanfile();
    Programma();
    fclose(infil);
    fclose(outfil);
    getchar();
    return 0;
}

analys.h


#ifndef ANALYS_H_INCLUDED
#define ANALYS_H_INCLUDED
#define DEBLOG(s) std::cerr << " DEBLOG " << __LINE__ << ": " << s << "\n"

#include "type.h"
#include <string>
#include <stdio.h>
using namespace std;
string code;
int pos;
string str;
void Programma();
bool isit(lc_type);
bool Opisanie();
bool Operator();
bool Operator1();
bool Nepomecheniy();
bool Sostavnoy();
bool Prisvaivaniya();
bool Peremennaya();
bool Index();
bool Perehoda();
bool Imya_metki();
bool Uslovniy();
bool Operacia();
bool Operand();
bool Cikla();
bool Vvoda();
bool Vivoda();
bool Specifikator();
bool Metka();
bool Imya_Metki();
bool Chislo();
bool Term();
bool Unarnoe();
bool Mnojitel();
bool Slagaemoe();
bool Virajenie();
bool Error();


bool isit(lc_type it) //Это та самая лексема?
{
    if (ilex[pos] != it) return false; //ошибка, это не то!  //25.04.20 UPD
    else
    {
        printf("\nRaspoznal %s \t\tpos=%d", lc[pos], pos);
        fprintf(outfil, "\nRaspoznal %s \t\tpos=%d", lc[pos], pos);
        str += lv[pos];
        str += " ";
        code = str;
        pos++;
        //if (ilex[pos] == lexEof) return false;
        return true;
    } //Ок, следующая лексема
}

//Готово
//$ описание = идентификатор{ "," идентификатор } ":"[vector "[" целое "]" of] тип.
bool Opisanie()
{
    fprintf(outfil, "\nOpisanie");
    if (isit(lexId)) {
        while (isit(lexComma)) {
            if (!isit(lexId)) {  // проверяем оператор присваивания, т.к. начало совпадает
                if (Chislo()) {  // если после запятой чило, то проверяем есть ли знак присваивания
                    if (isit(lexAssign)) if (isit(lexSemicolon) || isit(kwOr)) return true;
                }
                if (Virajenie()) if (isit(lexAssign)) { //если после запятой выражение также проверяем оператор присваивания
                    if (isit(lexSemicolon) || isit(kwOr)) return true;
                }
                else
                {
                    DEBLOG("//ошибка isit(lexAssign) == false");
                    return false;
                }
            } //ошибка описания нескольких переменных
        }
        if (!isit(lexColon)) {  // если не встретили знак : , проверяем оператор присваивания
            if (isit(lexAssign)) {
                if (isit(lexSemicolon) || isit(kwOr)) return true; // проверяем ; в конце либо ключевое слово Or, которое идет после
            }
        }
        if (isit(kwVector))
        {
            if (!isit(lexLftSqBr))
            {
                DEBLOG("//ошибка нехватает [");
                return false; //ошибка нехватает [
            }
            if (!isit(lexInt))
            {
                DEBLOG("//ошибка должно быть число после [");
                return false; //ошибка должно быть число после [
            }
            if (!isit(lexRghSqBr))
            {
                DEBLOG("//ошибка должно быть ] после числа");
                return false; //ошибка должно быть ] после числа
            }
            if (!isit(kwOf))
            {
                DEBLOG("//ошибка нехватает of");
                return false; //ошибка нехватает of
            }
            if (!(isit(kwInt) || isit(kwFloat)))
            {
                DEBLOG("//ошибка в типе");
                return false; //ошибка в типе
            }
            return true;
        }
        else
        {
            if (!(isit(kwInt) || isit(kwFloat)))
            {
                DEBLOG("//ошибка в типе");
                return false; //ошибка в типе
            }
            if (isit(lexSemicolon)) return true; //;
        }
        if (isit(kwInt) || isit(kwReal)) return true; // вот тут я сделал проверку, чтоб он при встрече kwint возвращал true, но почему-то он всё равно выбрасывает ошибку

    }
    else
    {
        DEBLOG("//ошибка isit(lexId) = false");
        return false;
    }
}
//$имя_метки = буква{буква|цифра}
bool Imya_metki()
{
    fprintf(outfil, "\nImya_metki");
    if (!isit(lexMetka)) return false;
    else return true;
}

//$ метка = имя_метки ":"
bool Metka()
{
    fprintf(outfil, "\nMetka");
    if (!Imya_metki()) return false;
    if (!isit(lexColon)) return false;
    return true;
}
bool Error() // обработка ошибок
{
    fprintf(outfil, "\nError");

    if (isit(lexError)) return true;
    return false;
}
//$ оператор = [метка] непомеченный.

bool Operator()
{
    fprintf(outfil, "\nOperator");//
    if (Nepomecheniy()) return true; // если нет метки, проверяем непомеченный
    if (Metka())
    {
        if (!Nepomecheniy()) return false;// если есть метка, проверяем идет ли за ней непомоченный
    }
    if (isit(lexSemicolon)) return true; // проверяем ; после оператора
    return false;

}
//$ составной = BST {/ оператор ";" /} EST.
bool Sostavnoy()
{
    fprintf(outfil, "\nSostavnoy");

    if (!isit(kwBegin)) return false;
    if (!Operator()) return false;
    if (!isit(lexSemicolon)) return false;
    while (Operator())
    {
        if (!isit(lexSemicolon)) return false;
    }
    if (!isit(kwEnd)) return false;
    return true;
}
//$ присваивание = переменная "," выражение ASS
bool Prisvaivaniya()// постфиксная форма записи для присваивания
{
    fprintf(outfil, "\n Prisvaivanie");//
    if (!Peremennaya()) return false;
    if (!isit(lexComma)) return false;
    if (!Virajenie()) return false;
    if (!isit(lexAssign)) return false;
    return true;
}
//$ переменная = идентификатор [ "[" индекс "]" ].
bool Peremennaya()
{
    fprintf(outfil, "\nPeremennaya");
    if (!isit(lexId)) return false;
    if (isit(lexLftSqBr))  // проверяем есть ли [
    {
        if (!Index()) return false;  // если внутри скобок нет индекса
        if (!isit(lexRghSqBr)) return false; // проверяем есть ли ]
        return true;
    }
    else return true;
}
//$ индекс = идентификатор | целое.
bool Index()
{
    fprintf(outfil, "\nIndex");
    if (isit(lexId)) return true;
    if (isit(lexInt)) return true;
    return false;
}

//$ перехода = goto имя_метки.
bool Perehoda()
{
    fprintf(outfil, "\nPerehod");
    if (!isit(kwGoto)) return false; // если нет перехода goto
    if (!Imya_metki()) return false; // если после goto нет метки
    return true;
}
//$ условный = if выражение then непомеченныйй [else непомеченный ]
bool Uslovniy()
{
    fprintf(outfil, "\nUslovniy");//
    if (!isit(kwIf)) return false;
    if (!Virajenie()) return false;
    if (!isit(kwThen)) return false;
    if (!Nepomecheniy()) return false;
    if (isit(kwElse))
    {
        if (!Nepomecheniy()) return false;
        return true;
    }
    return true;
}
//$ число = integer| real.
bool Chislo()
{
    fprintf(outfil, "\nChislo");
    if (isit(lexInt)) return true;
    if (isit(lexFloat)) return true;
    if (isit(lexBin)) return true; // проверяем также целые числа в других сс
    if (isit(lexOctal)) return true;
    if (isit(lexHex)) return true;
    return false;
}
//$ терм = переменная | число | "(" выражение")".
bool Term()
{
    fprintf(outfil, "\nTerm");
    if (Peremennaya()) return true;
    if (Chislo()) return true;
    if (isit(lexLftRndBr))
    {
        if (!Virajenie()) return false;
        if (!isit(lexRghRndBr)) return false;
        return true;
    }
    return false;
}
//$ унарное = [ MIN ] терм.
bool Unarnoe()
{
    fprintf(outfil, "\nUnarnoe");
    if (isit(lexMin))
    {
        if (!Term()) return false;
        return true;
    }
    if (Term()) return true;
    return false;
}
//$ множитель = унарное { (MUL | DIV | MOD) унарное }.
bool Mnojitel()
{
    fprintf(outfil, "\nMnojitel");
    if (Unarnoe())
    {
        while ((isit(lexStar) || isit(lexSlash) || isit(lexMod)))
        {
            if (!Unarnoe()) return false;
        }
        return true;
    }
    return false;
}
//$ слагаемое = множитель{ (ADD | MIN) множитель }.
bool Slagaemoe()
{
    fprintf(outfil, "\nSlagaemoe");
    if (Mnojitel())
    {
        while ((isit(lexPlus) || isit(lexMin)))
        {
            if (!Mnojitel()) return false;
        }
        return true;
    }
    return false;
}
//$ выражение = слагаемое{ (EQ | NE | LT | GT | LE | GE) слагаемое }.?????
bool Virajenie()
{
    fprintf(outfil, "\nVirajenie");
    if (Slagaemoe())
    {
        while ((isit(lexEQ) || isit(lexNE) || isit(lexLT) || isit(lexGT) || isit(lexLE) || isit(lexGE)))
        {
            if (!Slagaemoe()) return false;

        }
        return true;
    }
    return false;
}
//$ цикла = loop непомеченный.
bool Cikla()
{
    fprintf(outfil, "\nCikl");
    if (!isit(kwloop)) return false; // проверяем ключевое слово loop
    if (!Nepomecheniy()) return false; // проверяем есть ли после loop условие

    return true;
}
//$ непомеченный = составной | присваивания | перехода
// условный | цикла | пустой | ввода | вывода.
bool Nepomecheniy()
{
    fprintf(outfil, "\nNepomecheniy");
    if (Sostavnoy())  return true;
    if (Prisvaivaniya()) return true;
    if (Perehoda()) return true;
    if (Uslovniy()) return true;
    if (Cikla()) return true;
    if (Vvoda()) return true;
    if (Vivoda()) return true;

    return false;
}
//$ ввода = wtite ( выражение |спецификатор ) { "," ( выражение |спецификатор ) }.
bool Vvoda()
{
    fprintf(outfil, "\nVvod");
    if (!isit(kwRead)) return false;
    if (!Peremennaya()) return false;
    while (isit(lexComma))
    {
        if (!Peremennaya()) return false;
    }
    return true;
}
/*$ вывода = write(выражение | спецификатор) { "," (выражение | спецификатор) }.*/
bool Vivoda()
{
    fprintf(outfil, "\nVivod");
    if (!isit(kwWrite)) return false;
    if (!(Virajenie() || Specifikator())) return false;
    while (isit(lexComma))
    {
        if (!(Virajenie() || Specifikator())) return false;
    }
    return true;
}
//$ спецификатор = skip | space | tab.
bool Specifikator()
{
    fprintf(outfil, "\nSpecifikator");
    if (isit(kwSkip) || isit(kwSpace) || isit(kwTab)) return true;

    return false;
}


//$ программа = { / (описание | оператор) ";" / } конец_файла.
void Programma()
{
    //setlocale(LC_ALL, "Russian");

    fprintf(outfil, "\nProgramma");
    bool res;
    pos = 0;
    code = new char[200];

    str = "";
    res = Opisanie();
    if (res == false) res = Operator();
    if (res) {
        // printf("\n'%s'\n", code);
         //fprintf(outfil, "\n'%s'\n", code);
         //printf("pos=%d Vse Ok! next...\n", pos);
         //fprintf(outfil, "\npos=%d Vse Ok! next...\n", pos);
    }
    else {
        //printf("\n'%s'    Error!\n", code);
       // fprintf(outfil, "\n'%s'    Error!\n", code);
        printf("\nError! Pos=%d, lc=%s, lv=%s", pos, lc[pos], lv[pos]);
        fprintf(outfil, "\nError! Pos=%d, lc=%s, lv=%s", pos, lc[pos], lv[pos]);
    }
    if (isit(lexEof)) {
        //printf("\n'%s'\n", code);
        //fprintf(outfil, "\n'%s'\n", code);
        printf("\nEnd! No Error!");
        fprintf(outfil, "\nEnd! No Error!");
        return;
    }
    while (pos < maxi) {
        str = "";
        res = Opisanie();
        if (res == false)  res = Operator();
        if (isit(kwEnd)) res = true;

        if (isit(lexEof) || isit(kwEndProg)) {
            //printf("\n'%s'\n", code);
            //fprintf(outfil, "\n'%s'\n", code);
            printf("\nEnd! No Error!");
            fprintf(outfil, "\nEnd! No Error!");
            break;
        }

        if (res) {
            //printf("\n'%s'\n",code);
            //fprintf(outfil,"\n'%s'\n",code);
            //printf("pos=%d Vse Ok! next...\n", pos);
            //fprintf(outfil, "\npos=%d Vse Ok! next...\n", pos);
        }
        else {
            //printf("\n'%s'    Error!\n", code);
            //fprintf(outfil, "\n'%s'    Error!\n", code);
            printf("\nError! Pos=%d, lc=%s, lv=%s", pos, lc[pos], lv[pos]);
            fprintf(outfil, "\nError! Pos=%d, lc=%s, lv=%s", pos, lc[pos], lv[pos]);
            break;

        }
    }
}

#endif // ANALYS_H_INCLUDED
#pragma once

type.h


#ifndef TYPE_H_INCLUDED
#define TYPE_H_INCLUDED
#include <string.h>
#include <stdio.h>
#include <fstream>
#pragma warning(disable : 4996)
char** lc; // Типы лексем
char** lv; // Лексемы

FILE* infil,*outfil;

int maxi;
int line, column;

typedef enum {
    tltLetter, tltDigit, tltSkip
} sic_type;

typedef enum {
    lexArrow,
    lexAssign,
    lexColon,
    lexComma,
    lexComment,
    lexEQ,
    lexEof,
    lexError,
    lexFloat,
    lexGE,
    lexGT,
    lexId,
    lexIgnore,
    lexLE,
    lexLftRndBr,
    lexLftSqBr,
    lexLT,
    lexMin,
    lexNE,
    lexOctal,
    lexBin,
    lexHex,
    lexMod,
    lexPlus,
    lexSemicolon,
    lexSkip,
    lexSlash,
    lexStar,
    lexString,
    lexRghRndBr,
    lexRghSqBr,
    lexInt,
    lexReal,
    lexMetka,
    kwBegin,
    kwCase,
    kwEnd,
    kwEndProg,
    kwFloat,
    kwGoto,
    kwInt,
    kwReal,
    kwOr,
    kwRead,
    kwSkip,
    kwSpace,
    kwTab,
    kwWrite,
    kwWhile,
    kwDo,
    kwOf,
    kwIf,
    kwThen,
    kwElse,
    kwVector,
    kwloop,
    NONE
}lc_type;

lc_type* ilex; // Индексы лексем
typedef struct {
    lc_type* lex;
    char** sym;
    //char** lex;
    int pos;
} TR;

TR Tr;

void Scanfile()
{
    int i = 0;
    while (fscanf(infil, "[%d, %d] lc: %s\t\tlv: %s\n", &line, &column, lc[i], lv[i]) != EOF)
    {
        ilex[i] = NONE;

        if (strcmp(lc[i], "lexPlus") == 0)     ilex[i] = lexPlus;
        if (strcmp(lc[i], "lexAssign") == 0)      ilex[i] = lexAssign;
        if (strcmp(lc[i], "lexComma") == 0)    ilex[i] = lexComma;
        if (strcmp(lc[i], "lexComment") == 0)  ilex[i] = lexComment;
        if (strcmp(lc[i], "lexColon") == 0)    ilex[i] = lexColon;
        if (strcmp(lc[i], "lexEQ") == 0)       ilex[i] = lexEQ;
        if (strcmp(lc[i], "lexEof") == 0)      ilex[i] = lexEof;
        if (strcmp(lc[i], "lexError") == 0)    ilex[i] = lexError;
        if (strcmp(lc[i], "lexGE") == 0)       ilex[i] = lexGE;
        if (strcmp(lc[i], "lexGT") == 0)       ilex[i] = lexGT;
        if (strcmp(lc[i], "lexId") == 0)       ilex[i] = lexId;
        if (strcmp(lc[i], "lexIgnore") == 0)   ilex[i] = lexIgnore;
        if (strcmp(lc[i], "lexInt") == 0)  ilex[i] = lexInt;
        if (strcmp(lc[i], "lexReal") == 0)  ilex[i] = lexReal;
        if (strcmp(lc[i], "lexLE") == 0)       ilex[i] = lexLE;
        if (strcmp(lc[i], "lexLftRndBr") == 0) ilex[i] = lexLftRndBr;
        if (strcmp(lc[i], "lexLftSqBr") == 0)  ilex[i] = lexLftSqBr;
        if (strcmp(lc[i], "lexLT") == 0)       ilex[i] = lexLT;
        if (strcmp(lc[i], "lexPercent") == 0)  ilex[i] = lexMod;
        if (strcmp(lc[i], "lexStar") == 0)     ilex[i] = lexStar;
        if (strcmp(lc[i], "lexNE") == 0)       ilex[i] = lexNE;
        if (strcmp(lc[i], "lexRghRndBr") == 0) ilex[i] = lexRghRndBr;
        if (strcmp(lc[i], "lexRghSqBr") == 0)  ilex[i] = lexRghSqBr;
        if (strcmp(lc[i], "lexSkip") == 0)     ilex[i] = lexSkip;
        if (strcmp(lc[i], "lexMinus") == 0)    ilex[i] = lexMin;
        if (strcmp(lc[i], "lexString") == 0)      ilex[i] = lexString;
        if (strcmp(lc[i], "lexFloat") == 0)      ilex[i] = lexFloat;
        if (strcmp(lc[i], "lexArrow") == 0)      ilex[i] = lexArrow;
        if (strcmp(lc[i], "lexSemicolon") == 0)      ilex[i] = lexSemicolon;
        if (strcmp(lc[i], "lexSlash") == 0)      ilex[i] = lexSlash;
        if (strcmp(lc[i], "lexMetka") == 0)      ilex[i] = lexMetka;
        if (strcmp(lc[i], "lexOctal") == 0)      ilex[i] = lexOctal;
        if (strcmp(lc[i], "lexBin") == 0)      ilex[i] = lexBin;
        if (strcmp(lc[i], "lexHex") == 0)      ilex[i] = lexHex;

        if (strcmp(lc[i], "KWBEGIN") == 0)     ilex[i] = kwBegin;
        if (strcmp(lc[i], "KWEND") == 0)       ilex[i] = kwEnd;
        if (strcmp(lc[i], "KWENDPROG") == 0)       ilex[i] = kwEndProg;
        if (strcmp(lc[i], "KWGOTO") == 0)      ilex[i] = kwGoto;
        if (strcmp(lc[i], "KWINT") == 0)   ilex[i] = kwInt;
        if (strcmp(lc[i], "KWREAL") == 0)   ilex[i] = kwReal;
        if (strcmp(lc[i], "KWWHILE") == 0)      ilex[i] = kwWhile;
        if (strcmp(lc[i], "KWDO") == 0)        ilex[i] = kwDo;
        if (strcmp(lc[i], "KWREAD") == 0)      ilex[i] = kwRead;
        if (strcmp(lc[i], "KWSKIP") == 0)      ilex[i] = kwSkip;
        if (strcmp(lc[i], "KWSPACE") == 0)     ilex[i] = kwSpace;
        if (strcmp(lc[i], "KWTAB") == 0)       ilex[i] = kwTab;
        if (strcmp(lc[i], "KWWRITE") == 0)     ilex[i] = kwWrite;
        if (strcmp(lc[i], "KWOF") == 0)        ilex[i] = kwOf;
        if (strcmp(lc[i], "KWELSE") == 0)      ilex[i] = kwElse;
        if (strcmp(lc[i], "KWVECTOR") == 0)    ilex[i] = kwVector;
        if (strcmp(lc[i], "KWLOOP") == 0)    ilex[i] = kwloop;
        if (strcmp(lc[i], "KWDO") == 0)    ilex[i] = kwDo;
        if (strcmp(lc[i], "KWCASE") == 0)    ilex[i] = kwCase;
        if (strcmp(lc[i], "KWFLOAT") == 0)    ilex[i] = kwFloat;
        if (strcmp(lc[i], "KWOR") == 0)    ilex[i] = kwOr;

        printf("id%d %12.15s\t %8.10s  i=%d\n", ilex[i], lc[i], lv[i], i);
        fprintf(outfil, "id%d %12.15s\t %8.10s  i=%d\n", ilex[i], lc[i], lv[i], i);

        Tr.lex[i] = ilex[i];
        Tr.sym[i] = lv[i];
        i++;

    }
    maxi = i;
}

#endif // TYPE_H_INCLUDED
#pragma once

В analys.h добавил условие, чтобы он не ругался на kwint при встрече, а возвращал true, но почему-то не проходит. Причем, с kwreal такая же фигня. Вобщем, как исправить, чтобы не ругался на int, а распознавал его?

UPD: за что минусы то? Конкретно скажите, что не так в моём вопросе?


Ответы (0 шт):