Читайте также:
|
|
Цель работы.
Изучение основ построения лексического анализатора для заданного языка.
БНФ реализуемого языка
<Программа>::= <Объявление переменных> <Описание вычислений>
<Описание вычислений>::= <Список присваиваний>
<Объявление переменных>::= Var <Список переменных>;
<Список переменных>::= <Идент> | <Идент>, <Список переменных>
<Список присваиваний>::= <Присваивание> |
<Присваивание> <Список присваиваний>
<Присваивание>::= <Идент>:= <Выражение>;
<Выражение>::= <Ун.оп.><Подвыражение> | <Подвыражение>
<Подвыражение>:: = (<Выражение>) | <Операнд> |
< Подвыражение > <Бин.оп.> <Подвыражение>
<Ун.оп.>::= "-"
<Бин.оп.>::= "-" | "+" | "*" | "/"
<Операнд>::= <Идент> | <Const>
<Идент>::= <Буква> <Идент> | <Буква>
<Const>::= <Цифра> <Const> | <Цифра>
Список классов лексем реализуемого языка
1. Идентификатор
2. Ключевое слово «var»
3. Константа
4. Символ присваивания
5. Символ унарного минуса
6. Скобки.
7. Символы операций умножения и деления
8. Символы операций сложения и вычитания
9. Специальные символы «,» и «;»
Исходный код
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <string>
#include <set>
using namespace std;
/*обозначение классов лексем*/
const int ERROR = 0;// Недопустимый символ
const int IDENT = 1;//1. Идентификатор
const int VAR = 2;//2. Ключевое слово «var»
const int CONST = 3;//3. Константа
const int PRISV = 4;//4. Символ присваивания
const int UMIN = 5;//5. Символ унарного минуса
const int PAREN = 6;//6. Скобки.
const int MULT = 7;//7. Символы операций умножения и деления
const int SUMM = 8;//8. Символы операций сложения и вычитания
const int SEPAR = 9;//9. Специальные символы «,» и «;»
void main ()
{
FILE* prog = fopen("my_prog.txt","r");
if (prog == NULL){
printf("can`t open file to parse\n");
return;
}
FILE* lex = fopen("my_lex.txt","w");
if (lex ==NULL){
printf("can`t open file for output\n");
fclose(prog);
return;
} char * ch = (char*) malloc (sizeof(char));
char c = 'a';
/* prog - файл с транслируемой программой, lex - выходной файл лексем */
int string_number= 1;
/* признак унарного минуса*/
bool u_minus =true;
/*списки использованных идентификаторов и констант*/
set<string> Idents;
set<int> Nums;
//шапка таблицы
fprintf(lex,"Лексема\tКласс\tПредставление\t№строки\n");
while(!feof (prog))
{
fread(ch,1,1,prog);
c = *ch;
/* чтение очередного символа ch с пропуском пробелов */
if(isalpha(c)){
/* чтения идентификатора и вывода его в файл */
string ident;
while(isalpha(c) &&!feof(prog)){
ident += c;
fread(ch,1,1,prog);
c = *ch;
}
if (ident == "Var")
/*ключевое слово Var не является идентификатором*/
fprintf(lex,"Var\t%d\t-\t%d\n",VAR,string_number);
else
if (Idents.find(ident)==Idents.end()){
/*не выводим повторяющиеся идентификаторы*/
Idents.insert(ident);
fprintf(lex,"%s\t%d\t-\t%d\n",ident.c_str(),IDENT,string_number);
}
ungetc(c,prog);
}
else
if(isdigit(c)){
/* чтения числа и вывода его в файл */
string num;
while(isdigit(c) &&!feof(prog)){
num += c;
fread(ch,1,1,prog);
c = *ch;
}
int inum = atoi(num.c_str());
if (Nums.find(inum)==Nums.end()){
Nums.insert(inum);
/*не выводим повторяющиеся константы*/
fprintf(lex,"%s\t%d\t%x\t%d\n",num.c_str(),CONST,inum,string_number);
}
ungetc(c,prog);
u_minus = false;
}
else
if(c == ':')
{
/* чтения оператора присваивания и вывода его в файл */
fread(ch,1,1,prog);
if (*ch == '='){
fprintf(lex,":=\t%d\t-\t%d\n",PRISV,string_number);
u_minus= true;
}
else
{
fprintf(lex,":\t%d\t-\t%d\n",ERROR,string_number);
ungetc(*ch,prog);
}
}
else
if(c== '('){
fprintf(lex,"(\t%d\t-\t%d\n",PAREN,string_number);
u_minus=true;
}
else
if (c== ')'){
fprintf(lex,")\t%d\t-\t%d\n",PAREN,string_number);
u_minus = false;
}
else
if(c== '*' || c == '/')
fprintf(lex,"%c\t%d\t-\t%d\n",c,MULT,string_number);
else
if(c == ',' || c == ';')
fprintf(lex,"%c\t%d\t-\t%d\n",c,SEPAR,string_number);
else
if(c == '+')
fprintf(lex,"%c\t%d\t-\t%d\n",c,SUMM,string_number);
else
if (c == '-')
if (u_minus)
fprintf(lex,"-\t%d\t-\t%d\n",UMIN,string_number);
else
fprintf(lex,"-\t%d\t-\t%d\n",SUMM,string_number);
else
if (c=='\n'){
/*учет начала новой строки, увеличиваем счетчик строк*/
string_number+=1;
}else
if (! isspace(c))
/*игнорируя символы разделители (пробел, табуляция...)*/
/*все остальные символы ошибочны*/
fprintf(lex,"%c\t%d\t-\t%d\n",c,ERROR,string_number);
}
free(ch);
fclose(prog);
fclose(lex);
}
Контрольные примеры и результаты их выполнения.
Пример 1.
Var a;
a:= 4;
Результат работы:
Лексема | Класс | Представление | №строки |
Var | - | ||
a | - | ||
; | - | ||
:= | - | ||
; | - |
Пример 2.
Var a;
a == a;
Результат работы:
Лексема | Класс | Представление | №строки |
Var | - | ||
a | - | ||
; | - | ||
= | - | ||
= | - | ||
; | - |
Пример 3.
Var a,b,c;
a:= 2+23;
b:= -a;
c:= -(23-3)/4;
Результат:
Лексема | Класс | Представление | №строки |
Var | - | ||
a | - | ||
, | - | ||
b | - | ||
, | - | ||
c | - | ||
; | - | ||
:= | - | ||
+ | - | ||
; | - | ||
:= | - | ||
- | - | ||
; | - | ||
:= | - | ||
- | - | ||
( | - | ||
- | - | ||
) | - | ||
/ | - | ||
; | - | ||
; | - |
Пример 4.
Var Vars;
Результат:
Лексема | Класс | Представление | №строки |
Var | - | ||
Vars | - | ||
; | - |
Вывод.
Лексический анализатор – это очень хорошо. Он позволяет выявлять недопустимые символы, и разбивать исходный код на лексемы.
Дата добавления: 2015-11-30; просмотров: 34 | Нарушение авторских прав