Помощь - Поиск - Пользователи - Календарь
Полная версия: Синтаксический анализатор на С++
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Krjuger
Суть задания в том чтобы разработь класс для синтаксического анализатора арифметических выражений.

//---------------------------------------------------------------------------

#pragma hdrstop
#include <stdio.h>
#include <string.h>
//---------------------------------------------------------------------------

class Analiz
{
private:
int Stat;
int Vloj;
public:
char *Input;
char *Output;
Analiz();
int Error;
int Result(int err, char const *tmp = '\0');

};

int Analiz::Result(int err, char const *tmp)
{
char *temp;
switch (err)
{
case 0: temp = "Верно 0"; break;
case 1: temp = "Пропущен операнд 1"; break;
case 2: temp = "Неверно расставлены скобки 2"; break;
case 3: temp = "Неверный символ 3 ", strcat(temp, tmp);break;
case 4: temp = "Пропущен оператор 4 ";break;
case 5: temp = "Не заданы параметры функции 5";strcat(temp,tmp); break;
case 6: temp = "Неизвестная функция 6 ",strcat(temp,tmp);break;
case 7: temp = "Неверное имя 7 ", strcat(temp,tmp);break;
case 8: temp = "Неверная константа 8 ", strcat(temp, tmp);break;
}
Output = temp;
return Error = err;
}


Analiz::Analiz()
{
int i;
int j = 0;
Stat=1;
Error = 0;
const char number[] = " 0123456789";
const char liter[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char znak[] = " -*/+";
const char func[] = "cos sin tg ctg ln log sign exp";
char tmp[100];
// *tmp=NULL;
for (i = 0; Input[i] != '\0'; i++)
{
switch (Stat)
{
case 0: break;
case 1:

if (strchr(number, Input[i]) != 0)
{
Stat=4;
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
tmp[j++] = Input[i];
Stat=3;
break;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Result(1);
return;
}
else

if (strchr("(", Input[i]) != 0)
{
Vloj++;
break;
}
else

if (strchr(")", Input[i]) != 0)
{
Result(2);
return;
}
else

if (strchr(".", Input[i]) != 0)
{
Stat = 5;
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 2:

if (strchr(number, Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Stat = 1;
break;
}
else

if (strchr("(", Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(")", Input[i]) != 0)
{
Vloj--;
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(3);
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 3:

if (strchr(number, Input[i]) != 0)
{
tmp[j++] = Input[i];
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
tmp[j++] = Input[i];
break;
}
else

if (strchr(" ", Input[i]) != 0)
{
//tmp[j++]='\0';
if (strstr(func,tmp) != 0)
{
Stat = 6;
}
else
{
Stat = 2;
}
*tmp=NULL;
j=0;
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
tmp[j++]='\0';
if (strstr(func,tmp) != 0)
{
Result(5, tmp);
return;
}
else
{
Stat = 1;
*tmp=NULL;
j=0;
}
break;

}
else

if (strchr("(", Input[i]) != 0)
{
tmp[j++]='\0';
if (strstr(func,tmp) != 0)
{
Stat = 1;
*tmp=NULL;
j=0;
}
else
{
Result(6, tmp);
return;
}
Vloj++;
break;
}
else

if (strchr(")", Input[i]) != 0)
{
tmp[j++]='\0';
if (strstr(func,tmp) != 0)
{
Result(2);
return;
}
else
{
Stat = 2;
*tmp=NULL;
j=0;
Vloj--;
}
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(7, tmp);
return;
}
else
{
Result(3, &Input[i]);
return;
}

case 4:

if (strchr(number, Input[i]) != 0)
{
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(8, tmp);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
Stat=2;
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Stat = 1;
break;
}
else

if (strchr("(", Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(")", Input[i]) != 0)
{
Stat = 2;
Vloj--;
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(3);
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 6:

if (strchr(number, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr("(", Input[i]) != 0)
{
Stat = 1;
Vloj++;
break;
}
else

if (strchr("", Input[i]) != 0)
{
Result(2);
return;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(5);
break;
}
else
{
Result(3, &Input[i]);
return;
}
}
}
if (Input[i] == '\0')
{
switch(Stat){
case 1: Result(1); break;
case 2: Result(0); break;
case 3:
tmp[j++]='\0';

if (strstr(func,tmp) != 0)
{
Result(5, tmp);
}
else
Result(0);
break;
case 4: Result(0); break;
case 5: Result(0); break;
case 6: Result(5, tmp); break;
}
}
}

void main()//пример чисто символический,потмоу чт все равно проект не проходит даже сборку
{
Analiz m1;
m1.Input="x+1/2";
printf("/n %s /n",m1.Output);
}


В отладчике выдается 2 ошибки:
1.error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup MSVCRTD.lib
2.fatal error LNK1120: 1 unresolved externals

Что делать ума не приложу.
volvo
Цитата
Что делать ума не приложу.
Создать консольное приложение, а не Win32-проект. У тебя компилятор не может найти обязательную для Win-приложения функцию WinMain, ибо нет ее в твоем проекте.
Krjuger
Ну я создаю пустой win32 console application и там .срр файл,кстати использую MVS.А тогда какой консольное приложение мне необходимо создать?Мда создал пустой проект и нормально собралось(как то тупо получилось.
Krjuger
Я чуть изменил код,

//---------------------------------------------------------------------------

#pragma hdrstop
#include <stdio.h>
#include <string.h>
//---------------------------------------------------------------------------

class Analiz
{
private:
int Stat;
int Vloj;
public:
char *Input;
char *Output;
Analiz(char *input);
int Error;
int Result(int err, char const *tmp = '\0');

};

int Analiz::Result(int err, char const *tmp)
{
char *temp;
switch (err)
{
case 0: temp = "Верно 0"; break;
case 1: temp = "Пропущен операнд 1"; break;
case 2: temp = "Неверно расставлены скобки 2"; break;
case 3: temp = "Неверный символ 3 ", strcat(temp, tmp);break;
case 4: temp = "Пропущен оператор 4 ";break;
case 5: temp = "Не заданы параметры функции 5";strcat(temp,tmp); break;
case 6: temp = "Неизвестная функция 6 ",strcat(temp,tmp);break;
case 7: temp = "Неверное имя 7 ", strcat(temp,tmp);break;
case 8: temp = "Неверная константа 8 ", strcat(temp, tmp);break;
}
Output = temp;
return Error = err;
}


Analiz::Analiz(char *input)
{
int i;
int j = 0;
Stat=1;
Error = 0;
const char number[] = " 0123456789";
const char liter[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char znak[] = " -*/+";
const char func[] = "cos sin tg ctg ln log sign exp";
char tmp[100];
Input=input;
// *tmp=NULL;
for (i = 0; Input[i] != '\0'; i++)
{
switch (Stat)
{
case 0: break;
case 1:

if (strchr(number, Input[i]) != 0)
{
Stat=4;
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
tmp[j++] = Input[i];
Stat=3;
break;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Result(1);
return;
}
else

if (strchr("(", Input[i]) != 0)
{
Vloj++;
break;
}
else

if (strchr(")", Input[i]) != 0)
{
Result(2);
return;
}
else

if (strchr(".", Input[i]) != 0)
{
Stat = 5;
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 2:

if (strchr(number, Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Stat = 1;
break;
}
else

if (strchr("(", Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(")", Input[i]) != 0)
{
Vloj--;
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(3);
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 3:

if (strchr(number, Input[i]) != 0)
{
tmp[j++] = Input[i];
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
tmp[j++] = Input[i];
break;
}
else

if (strchr(" ", Input[i]) != 0)
{
//tmp[j++]='\0';
if (strstr(func,tmp) != 0)
{
Stat = 6;
}
else
{
Stat = 2;
}
*tmp=NULL;
j=0;
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
tmp[j++]='\0';
if (strstr(func,tmp) != 0) //вот здесь впесто того чтобы пропустить прога переходит к Result(5, tmp),хотя не должна этого делать.
{
Result(5, tmp);//
return;
}
else
{
Stat = 1;
*tmp=NULL;
j=0;
}
break;

}
else

if (strchr("(", Input[i]) != 0)
{
tmp[j++]='\0';
if (strstr(func,tmp) != 0)
{
Stat = 1;
*tmp=NULL;
j=0;
}
else
{
Result(6, tmp);
return;
}
Vloj++;
break;
}
else

if (strchr(")", Input[i]) != 0)
{
tmp[j++]='\0';
if (strstr(func,tmp) != 0)
{
Result(2);
return;
}
else
{
Stat = 2;
*tmp=NULL;
j=0;
Vloj--;
}
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(7, tmp);
return;
}
else
{
Result(3, &Input[i]);
return;
}

case 4:

if (strchr(number, Input[i]) != 0)
{
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(8, tmp);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
Stat=2;
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Stat = 1;
break;
}
else

if (strchr("(", Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(")", Input[i]) != 0)
{
Stat = 2;
Vloj--;
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(3);
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 6:

if (strchr(number, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr("(", Input[i]) != 0)
{
Stat = 1;
Vloj++;
break;
}
else

if (strchr("", Input[i]) != 0)
{
Result(2);
return;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(5);
break;
}
else
{
Result(3, &Input[i]);
return;
}
}
}
if (Input[i] == '\0')
{
switch(Stat)
{
case 1: Result(1); break;
case 2: Result(0); break;
case 3:
tmp[j++]='\0';

if (strstr(func,tmp) != 0)
{
Result(5, tmp);
}
else
Result(0);
break;
case 4: Result(0); break;
case 5: Result(0); break;
case 6: Result(5, tmp); break;
}
}
}

void main()
{
Analiz m1("x+1/2");
printf("/n %s /n",m1.Output);
}



При использовании данного примера проиходит ошибка,проблема в том что именованое пространство func как то неверно сравнивается с моим текущим значением tmp...
volvo
Цитата
//вот здесь впесто того чтобы пропустить прога переходит к Result(5, tmp),хотя не должна этого делать.
Здесь - не должна (у меня и не переходит, но я тестировал с GCC, Майкрософтовского компилятора не держу), чуть ниже - здесь:
case 6:
if (strchr(number, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else
if (strchr(liter, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else
if (strchr(" ", Input[i]) != 0)
{
break;
}
else
if (strchr(znak, Input[i]) != 0)
{
Result(5, tmp); // <--- Вот именно здесь...
return;
}
- уже должна. Может быть VC++ так оптимизирует? Кстати, я бы на твоем месте чуть-чуть переписал бы. Вот так, например:
	const char *func = "cos sin tg ctg ln log sign exp\0";
char tmp[100] = {0};
Krjuger
Не, у меня это происходит именно в третьем case ,а
Цитата
const char *func = "cos sin tg ctg ln log sign exp\0";
пишет невозможно конвертировать const char to const char *
Цитата
Может быть VC++ так оптимизирует?

у меня такое ощущение,что оно разбило эти функции на элементы и сверяет с каждый,в итоге я проверяю не с нужными мне функциями,а с множеством элементов,образованных этими функциями.
volvo
Цитата
пишет невозможно конвертировать const char to const char *
Они что там, в MS вообще с ума посходили? Теперь понятно, почему у них такие поделки. То, что Стандарт обязывает такую конструкцию работать - это им плевать, их компилятор, значит, не пропускает? В топку его...
Krjuger
Да я бы сам на другом написал бы,но препод принимать все равно на MVS будет,а лишние всплывающие косяки мне не нужны.Кстати strstr тоже отказывается потом работать.
Хах короче данная проблема выличилась,оказывается надо так:

const char *func = {"cos sin tg ctg ln log sign exp\0"};


Но сама проблема с 3 кейсом не пропала((((
Krjuger
Так проблема с 3 кейсом тоже отпала,но появилась новая....
если я делаю

case 5: temp = "Не заданы параметры функции 5";
strcat(temp, tmp);


но вылазит какая то дремучая ошибка доступа,если я поменяю temp tmp местами то все нормарьно работает,но будет не то что мне нужно если создам третью переменную char *temp2, и использую

case 5: temp = "Не заданы параметры функции 5";
strcat(temp2, tеmp);
strcat(temp2, tmp);


То мне пишет что temp2 используется без инициализации.
volvo
Стоп... А с чего ты решил, что
Цитата
if (strstr(func,tmp) != 0) //вот здесь впесто того чтобы пропустить прога переходит к Result(5, tmp),хотя не должна этого делать.
? В тот момент tmp = "x", так? Ну, а в строке: "cos sin tg ctg ln log sign exp" Все правильно... Я проверял только с первыми четырьмя функциями, добавил все - всё встало на свои места, там ДОЛЖЕН быть переход на Result(5, tmp).
Krjuger
Не ,его как раз быть не должно по задумке,потому что "х" не является функцией обьявленной в множестве функций,и должно обрабатываться как операнд.наверно мне надо как то по другому обьявить множестов функций,чтобы более чтрого проверялось наличие.
volvo
Цитата
Не ,его как раз быть не должно по задумке,потому что "х" не является функцией обьявленной в множестве функций
А ты это что, уже объяснил функции strstr? Ей по фигу, что в каком множестве содержится. Она ищет вхождения строк. Точка. Больше - ничего. А строка "x" в строке "cos sin tg ctg ln log sign exp" присутствует по-любому. Так что переход быть ДОЛЖЕН. Или переписывай strstr так, чтоб она знала, что есть твои "множества функций".

Добавлено через 1 мин.
Цитата
наверно мне надо как то по другому обьявить множестов функций,чтобы более чтрого проверялось наличие.
Наверное... Например, в строке, содержащей функции, первый и последний - пробелы. И сам tmp тоже обрамить пробелами с двух сторон. Тогда будет искаться точное соответствие.
Krjuger
С проверкой я разобрался теперь все нормально рабоатет,но вот проблема с выводом результата все еще остается.

Все,сделал,спасибо,осталось отловить различные случаи,потом скину конечный результат...
Krjuger
В общем помучавшись мальца я пришел к такому варианту:

//---------------------------------------------------------------------------

#pragma hdrstop
#include <stdio.h>
#include <string.h>
//---------------------------------------------------------------------------

class Analiz
{
private:
int Stat;
int Vloj;
public:
char *Input;
char *Output;
Analiz(char *input);
int Error;
int Result(int err, char *tmp = '\0');

};

int Analiz::Result(int err, char *tmp)
{
char temp[100];
switch (err)
{
case 0: strcpy(temp, "Верно 0"); break;
case 1: strcpy(temp, "Пропущен операнд 1"); break;
case 2: strcpy(temp, "Неверно расставлены скобки 2"); break;
case 3: strcpy(temp, "Неверный символ 3 ");
strcat(temp, tmp); break;
case 4: strcpy(temp ,"Пропущен оператор 4 ");
// strcat(temp, tmp);
break;
case 5: strcpy(temp, "Не заданы параметры функции 5 ");
strcat(temp, tmp);break;
case 6: strcpy(temp, "Неизвестная функция 6 ");
strcat(temp, tmp);break;
case 7: strcpy(temp, "Неверное имя 7 ");
strcat(temp, tmp);break;
case 8: strcpy(temp, "Неверная константа 8 ");
strcat(temp, tmp);break;
}
Output = temp;
return Error = err;
}


Analiz::Analiz(char *input)
{
int i;
int j = 0;
Stat=1;
Vloj=0;
Error = 0;
const char number[] = "0123456789";
const char liter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char znak[] = "-*/+";
const char *func[] = {" cos sin tg ctg ln log sign exp\0"};
char tmp[100]={0};
char tmp1[100]={0};
Input=input;
// *tmp=NULL;
for (i = 0; Input[i] != '\0'&&Error==0; i++)
{
switch (Stat)
{
case 0: break;
case 1:

if (strchr(number, Input[i]) != 0)
{
Stat=4;
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
tmp[j++] = Input[i];
Stat=3;
break;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Result(1);
return;
}
else

if (strchr("(", Input[i]) != 0)
{
Vloj++;
break;
}
else

if (strchr(")", Input[i]) != 0)
{
Result(2);
return;
}
else
{
Result(3, &Input[i]);
return;
}

case 2:

if (strchr(number, Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Stat = 1;
break;
}
else

if (strchr("(", Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(")", Input[i]) != 0)
{
Vloj--;
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(3);
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 3:

if (strchr(number, Input[i]) != 0)
{
tmp[j++] = Input[i];
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
tmp[j++] = Input[i];
break;
}
else

if (strchr(" ", Input[i]) != 0)
{
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
if (strstr(*func,tmp1) != 0)
{
Stat = 6;
}
else
{
Stat = 2;
}
*tmp=NULL;
j=0;
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
Result(5, tmp1);
return;
}
else
{
Stat = 1;
*tmp=NULL;
j=0;
}
break;

}
else

if (strchr("(", Input[i]) != 0)
{
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
Stat = 1;
*tmp=NULL;
j=0;
}
else
{
Result(6, tmp);
return;
}
Vloj++;
break;
}
else

if (strchr(")", Input[i]) != 0)
{
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
Result(2);
return;
}
else
{
Stat = 2;
*tmp=NULL;
j=0;
Vloj--;
}
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(7, tmp);
return;
}
else
{
Result(3, &Input[i]);
return;
}

case 4:

if (strchr(number, Input[i]) != 0)
{
break;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(8, tmp);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
Stat=2;
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Stat = 1;
break;
}
else

if (strchr("(", Input[i]) != 0)
{
Result(4);
return;
}
else

if (strchr(")", Input[i]) != 0)
{
Stat = 2;
Vloj--;
break;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(3,".");
break;
}
else
{
Result(3, &Input[i]);
return;
}

case 6:

if (strchr(number, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr(liter, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr(" ", Input[i]) != 0)
{
break;
}
else

if (strchr(znak, Input[i]) != 0)
{
Result(5, tmp);
return;
}
else

if (strchr("(", Input[i]) != 0)
{
Stat = 1;
Vloj++;
break;
}
else

if (strchr(")", Input[i]) != 0)
{
Result(2);
return;
}
else

if (strchr(".", Input[i]) != 0)
{
Result(5);
break;
}
else
{
Result(3, &Input[i]);
return;
}
}
}
if (Input[i] == '\0')
{
if (Vloj==0)
{
Result(0);
}
else
{
Result(2);
}
}
}

void main()
{ char *str;
char str1[100];
//scanf("%s",&str);
str=gets(str1);
printf("%s",str);
Analiz m1(str);
}


Если у кого то есть желание и возможность то потестируйте его на прочность и если возникнут неверные результаты просьба выложить их суда,чтобы я исправил.
cos sin tg ctg ln log sign exp- список допустымых функций.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.