Смекни!
smekni.com

Интерпретатор 2 (стр. 2 из 2)

#include "global.h"

struct entry keywords[]=

{

"if",IF,0,

"else",ELSE,0,

"while",WHILE,0,

"input",INPUT,0,

"print",PRINT,0,

"printn",PRINTN,0,

0,0,0,

};

void init(void)/* Загрузкаключевыхсловвтаблицусимволов */

{

struct entry *i;

for(i=keywords;i->token;i++)

insert(i->lexptr,i->token);

}


lexer.c

#include "global.h"

int CmpNextSym(int,int,int);

char lexbuf[BSIZE];

int lineno = 1;

double tokenval = NONE;

int lexan(void) /* Лексическийанализатор */

{

int t;

while (1)

{

t = fgetc(Open);// Считать в t символ из ранее открытого файла

if (t == ' ' || t == '\t'); /* Отбрасываем разделители-пробелы */

else if (t == '\n')// Если символ перевода строки, то

lineno++;// Увеличить счетчик линий

else if (isdigit(t)) /* t - цифра */

{

ungetc(t, Open);// Вернуть t во входной поток

fscanf(Open,"%lf",&tokenval);// Занести занчение числа (1 или > символов) в tokenval

return NUM;// Вернуть идентификатор числа

}

else if (isalpha(t)) /* t - буква */

{

int p, b = 0;

while (isalnum(t)) /* Пока t - букваилицифра */

{

lexbuf[b++] = t;// Добавить в буффер t

t=fgetc(Open);// Считать очередной символ

if (b >= BSIZE)// если превышен рзмер буффера

error("compiler error");// Вызов процедуры выхода с сообщением об ошибке

}

lexbuf[b] = EOS;// Добавить в буффер признак завершения последовательности символов (слова)

if (t != EOF)// Если t - не признак конца файла, то

ungetc(t, Open);// Вернуть t

p = lookup(lexbuf);// p = положение считанного слова в таблце символов

if (p == 0)// Если слово встретилось впервые

p = insert(lexbuf, ID);// Добавить в таблицу символов новую переменную

tokenval = p;

return symtable[p].token;// Вернуть соответствующий считанному слову идентификатор

}

else if (t == EOF) return DONE;// Если в t признак завершения файла - вернуть идентификатор конца программы

else switch(t)// Иначе, если t один из символов:

{

case '>':

return CmpNextSym('=',JG,JGE);// Если за t следует =, то вернуть инедтификатор условия JGE (больше-равно), иначе - JG (больше)

case '<':

return CmpNextSym('=',JL,JLE);// Меньше-равно, или меньше

case '!':

return CmpNextSym('=',JNE,'!');// Не равно, или символ !

case '=':

return CmpNextSym('=',JE,'=');// Равно (условие) или символ =

case ':':

return CmpNextSym('=',EQUAL,':');// Прсвоитьилисимвол :

case '{':

return BEGIN;// Вернутьидентификатор BEGIN

case '}':

return END;// Вернутьидентификатор END

default:// Если что-либо другое, то

tokenval=NONE;

return t;// Вернуть t

}

}

}

int CmpNextSym(int ch,int good,int bad)

{

int nc=fgetc(Open);// считать следующий символ

if(nc==ch) return good;//если следующий символ = ch - вернуть good

ungetc(nc,Open);//иначе, возврат символа во входной поток

return bad;// вернуть bad

}


parser.c

#include "global.h"

int FillCode(void);

int FC(void);

int expr(void);

int term(void);

int factor(void);

int IdIn(void);

void LabelPush(int);

int LabelPop(void);

int match(int);

int lookahead;//текущий сканируемый входной токен

int LabelStack[100],LabelCnt=0;

double tv;

int parse(void)/* Разбор и трансляция списка выражений */

{

lookahead=lexan();// Чтение слова

while(lookahead!=DONE)// До тех пор, пока не будет получен идентификатор завершения программы

{

FillCode();// Заполнение таблицы кодов

}

return 0;// Возврат

}

int FillCode()

{

int t;

FC();// Обработкаслова

while(1)// Бесконечно повторять

{

switch(lookahead)

{

case ';'://Если текущее слово - символ ";", то

match(';');// Перейти к следующему слову

insertcode(0,";",0);// Добавить в таблицу клдлв ";"

FC();// Обработка слова

break;

default:

return;

}

}

}

int FC(void)

{

while(1)

{

switch(lookahead)

{

case ID:

match(ID);

tv=tokenval;

match(EQUAL);

expr();// Обработкавыражения

insertcode(EQUAL,symtable[tv].lexptr,0);// Добавить в таблицу кодов присваивание переменной

break;

case PRINTN:

match(PRINTN);

expr();// Обработка выражения

insertcode(PRINTN,"printn",0);// Добавить строчку в таблицу кодов

while(1)

{

switch(lookahead)

{

case ',':// Обработкааргументов, введенных через запятую

match(',');

expr();

insertcode(PRINTN,"printn",0);

break;

default:

return;

}

}

case INPUT:

match(INPUT);

IdIn();// Добваить в таблицу кодов строчку получения заначения переменной

break;

case PRINT:

match(PRINT);

expr();

insertcode(PRINT,"print",0);

while(1)

{

switch(lookahead)

{

case ',':

match(',');

expr();

insertcode(PRINT,"print",0);

break;

default:

return;

}

}

case BEGIN:

match(BEGIN);

FillCode();// Вызов процедуры обработки слов (вначале проверится слово, затем ";")

match(END);

break;

case IF:

match(IF);

match('(');

expr();

insertcode(THEN,"then",0);

LabelPush(lastcode);// Добавитьметку

match(')');

FC();

codetable[LabelPop()].value=lastcode+1;// Изменить занчение в строке метки, для указания на нужную строчку

insertcode(GOTO,"else",0);

LabelPush(lastcode);// Добавитьметку

match(ELSE);

FC();

codetable[LabelPop()].value=lastcode;// Изменить занчение в строке метки, для указания на нужную строчку

break;

case WHILE:

insertcode(WHILE,"while",0);

LabelPush(lastcode);

match(WHILE);

match('(');

expr();

match(')');

insertcode(DO,"do",0);

LabelPush(lastcode);

FC();

codetable[LabelPop()].value=lastcode+1;

insertcode(GOTO,"goto",LabelPop());

break;

default:

return;

}

}

}

int expr(void)

{

term();// Ввызов вспомогательной процедуры разбора

while(1)

{

switch(lookahead)// Обработка операций + - и логических уловий

{

case '+':

match(lookahead);// Перейти к следующему слову

term();

insertcode('+',"+",0);

break;

case '-':

match(lookahead);

term();

insertcode('-',"-",0);

break;

case JNE:

match(lookahead);

term();

insertcode(JE,"!=",0);

break;

case JE:

match(lookahead);

term();

insertcode(JNE,"==",0);

break;

case JL:

match(lookahead);

term();

insertcode(JL,"<",0);

break;

case JLE:

match(lookahead);

term();

insertcode(JLE,"<=",0);

break;

case JG:

match(lookahead);

term();

insertcode(JG,">",0);

break;

case JGE:

match(lookahead);

term();

insertcode(JGE,">=",0);

break;

default:

return;

}

}

}

int term()

{

factor();// Ввызов вспомогательной процедуры разбора

while(1)

{

switch(lookahead)// Обработка матемтических операций типа *, /

{

case '*':

match(lookahead);

factor();

insertcode('*',"*",0);

break;

case '/':

match(lookahead);

factor();

insertcode('/',"/",0);

break;

default:

return;

}

}

}

int factor(void)

{

switch(lookahead)

{

case NUM:

insertcode(NUM,"num",tokenval);

match(NUM);

break;

case ID:

insertcode(ID,symtable[tokenval].lexptr,0);

match(ID);

break;

case '(':

match('(');

expr();

match(')');

break;

default:

error("syntax error");

}

return 0;

}

int IdIn()

{

insertcode(INPUT,symtable[tokenval].lexptr,0);

match(ID);

while(1)

{

switch(lookahead)

{

case ',':

match(',');

insertcode(INPUT,symtable[tokenval].lexptr,0);

match(ID);

break;

default:

return;

}

}

}

void LabelPush(int n)// Добавить метку в стек

{

LabelStack[LabelCnt++]=n;

}

int LabelPop(void)// Извлечь метку из стека

{

LabelCnt--;

return LabelStack[LabelCnt];

}

int match(int t)//процедура переходит к следующему входному токену, если ее аргумент t совпадает со сканируемым символом.

{

if(lookahead==t)// Если t совпадает со сканируемым словом, то

lookahead=lexan();// Считать следующее слово

else error("syntax error");// Иначе - вывод ошибки, выход

return 0;

}


symbol.c

#include "global.h"

#defineSTRMAX 1000 /* Размер массива лексем */

#define SYMMAX 1000 /* Размер таблицы символов */

#define CODEMAX 1000/* Размер таблицы кодов */

char lexemes[STRMAX];

int lastchar = -1; /* Последняя использованная позиция в lexemes */

struct entry symtable[SYMMAX];

int lastentry = 0; // Последняя использованная позиция в таблице символов

char lexgen[STRMAX];

int lastlexgen = -1;

struct code codetable[CODEMAX];

int lastcode = 0; /* Последняяиспользованнаяпозициявтаблицекодов */

int lookup(char s[]) /* Возвращает положение в таблице символов для s */

{

int i;

for(i = lastentry; i > 0; i--)

if (strcmp(symtable[i].lexptr, s) == 0)

return i;

return 0;

}

int insert(char s[], int tok) /* Добавитьстрочкувтаблицусимволов */

{

int len;

len = strlen(s); /* strlen вычисляетдлинустроки */

if (lastentry + 1 >= SYMMAX)

error("symbol table full");

if (lastchar + len + 1 >= STRMAX)

error("lexemes array full");

lastentry++;

symtable[lastentry].token = tok;

symtable[lastentry].lexptr = &lexemes[lastchar + 1];

lastchar += len + 1;

strcpy(symtable[lastentry].lexptr, s);

return lastentry;

}

int insertcode(int tok,char s[],double value){ //Добавлениевтаблицукодов

int len;

len=strlen(s);

if(lastcode+1>=CODEMAX)

error("code table full");

if(lastlexgen+len+1>=STRMAX)

error("lexemes array full");

lastcode++;

codetable[lastcode].value = value;

codetable[lastcode].token = tok;

codetable[lastcode].lexptr = &lexgen[lastlexgen+1];

lastlexgen+=len +1;

strcpy(codetable[lastcode].lexptr,s);

return lastcode;

}

int get_codetable()// Вывеститаблицукодов

{

int i;

for(i=1;i<=lastcode;i++)

printf("%d %d %s %g&bsol;n",i,codetable[i].token,codetable[i].lexptr,codetable[i].value);

return 0;

}

int get_symtable()// Вывеститаблицусимволов

{

int i;

for(i=1;i<=lastentry;i++)

printf("%d %d %s %g&bsol;n",i,symtable[i].token,symtable[i].lexptr,symtable[i].value);

return 0;

}


emitter.c

#include "global.h"

double stack[1000];

int j=0;

int a;

double pop(void);

void push(double n);

double x,y,z;

int emit(void) //Выполнениепрограммы

{

int i=0;

while(i<lastcode)// Выполнять, пока не достигнут конец таблицы кодов

{

switch(codetable[i].token)// Выполнить действие, в соответствии с прочитанным словом из таблицы кодов

{

case NUM:

push(codetable[i].value);

break;

case ID:

push(symtable[lookup(codetable[i].lexptr)].value);

break;

case '+':

y=pop();

z=pop();

push(z+y);

break;

case '-':

y=pop();

z=pop();

push(z-y);

break;

case '*':

y=pop();

z=pop();

push(z*y);

break;

case '/':

y=pop();

z=pop();

push(z/y);

break;

case EQUAL:

symtable[lookup(codetable[i].lexptr)].value=pop();

break;

case JE:

y=pop();

z=pop();

push(y==z);

break;

case JNE:

y=pop();

z=pop();

push(y!=z);

break;

case JL:

y=pop();

z=pop();

push(y<z);

break;

case JLE:

y=pop();

z=pop();

push(y<=z);

break;

case JG:

y=pop();

z=pop();

push(y>z);

break;

case JGE:

y=pop();

z=pop();

push(y>=z);

break;

case DO:

if(pop()==1)i=codetable[i].value;// Если условие выполнено - перейти в соответствующую строку

break;

case GOTO:

i=codetable[i].value;

break;

case THEN:

if(pop()==1)i=codetable[i].value;

break;

case PRINT:

printf("%g &bsol;n",pop());

break;

case PRINTN:

a = pop();

printf("%d &bsol;n",a);

break;

case INPUT:

scanf("%lf,",&symtable[lookup(codetable[i].lexptr)].value);

break;

}

i++;

}

return 0;

}

void push(double n)//Положитьвстек

{

stack[j++]=n;

}

double pop()//Извлечьизстека

{

j--;

return stack[j];

}


errors.c

#include"global.h"

int error(char *s)

{

printf("%s in line %d&bsol;n",s,lineno); // вывод сообщения об ошибке в конкретной строке

getch();

exit(1); // выход

return 0;

}


Список использованной литературы

1. А. Ахо, Р. Сети, Д. Ульман Компиляторы: принципы, технологии и инструменты.: Пер. с англ. — М.: Издательский дом "Вильяме", 2003. — 768 с.

2. Липпман C++ для начинающих. – 1194 с.

3. Флоренсов А.Н. Операционные системы: Учеб. пос. - Омск: Издательство ОмГТУ, 2005. – 160 с.