Где ошибка в коде синтаксического анализатора?
Есть некий учебный язык, лексический анализатор и синтаксический анализатор для этого языка. Сурс на языке подаётся на вход лексического, затем выходной с лексического подаётся на вход синтаксического. Дело в том, что синтаксический анализатор выдаёт ошибки с тем же кодом, когда у другого человека он проходит без ошибок. Пожалуйста помогите найти ошибки в коде
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
должно быть так
Но, у меня выдаёт ошибки
*я тут сделал, чтоб на вход программы не подавались файлы, а читались/записывались определённые, поэтому там нет 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: за что минусы то? Конкретно скажите, что не так в моём вопросе?

