1 / 157

# Перемноження матриць - PowerPoint PPT Presentation

Перемноження матриць. #include "stdafx.h" using namespace System; using namespace System::IO; int main(array<System::String ^> ^args) { String^s; int n,m; Console::WriteLine("Enter n="); s=Console::ReadLine(); n=Convert::ToInt32(s); Console::WriteLine("Enter m=");

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about ' Перемноження матриць' - francis-floyd

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

#include "stdafx.h"

using namespace System;

using namespace System::IO;

int main(array<System::String ^> ^args)

{

String^s;

int n,m;

Console::WriteLine("Enter n=");

n=Convert::ToInt32(s);

Console::WriteLine("Enter m=");

m=Convert::ToInt32(s);

array<double,2>^y=gcnew array<double,2>(m,n);

array<double,2>^c=gcnew array<double,2>(n,n);

for(int i=0;i<n;i++)

for(int j=0;j<m;j++)

{

x[i,j]=Convert::ToDouble(s);

Console::WriteLine("x={0}",x[i,j]);

}

for(int i=0;i<m;i++)

for(int j=0;j<n;j++)

{

y[i,j]=Convert::ToDouble(s);

Console::WriteLine("y={0}",y[i,j]);

}

StreamWriter^sw=gcnew StreamWriter("D:\\AVRPROG\\VISUAL\\TestFile21.txt");

sw->AutoFlush::set(true);

for(int i=0;i<n;i++)

for(int j=0;j<n;j++)

{

c[i,j]=0;

for(int k=0;k<m;k++)

c[i,j]+=x[i,k]*y[k,j];

Console::WriteLine("c={0}",c[i,j]);

if(j%n==0)

sw->Write("\n");

sw->Write(" c[{0},{1}]={2} ",i,j,c[i,j]);

}

Console::WriteLine(L"Finish");

return 0;

}

• 1

• 2,5

• 3

• 4

• 5

• 6,7

• 8

• 10

• 20

• 30

• 40

• 50

• 60

• 70

• 80

### Елементи компіляції

Аналіз формальних мов

Відомості про регулярні вирази та граматики

• Алфавіт – конечна множина I елементів, які наз. СИМВОЛАМИ.

• Ланцюжок (слово)- конечна послідовність символів із алфавіту I.

• Мова в алфавіті I – довільна множина ланцюжків (слів).

Дії над ланцюжками та граматики

xn- ланцюжокxповторюється n раз.

xR - ланцюжок xпишеться в зворотномунапрямку.

XY – за ланцюжком X розміщується Y.

X* - ланцюжок xповторюється в циклі НУЛЬ і більше раз.

X+- ланцюжок xповторюється в циклі ОДИН і більше раз.

| X | та граматики - довжина ланцюжка.

{ } або έабоe– пустий ланцюжок.

[X] необов’язковий ланцюжок.

Регулярні вирази і граматика та граматики

• Нехай три символи { , * | }не входять до заданого алфавіту символів I.

Ланцюжок із об’єднанняI U { , * | } наз. регулярним виразом.

Граматика G=( T, N, P, S)

T, N - алфавіти термінальних і нетермінальних символів.

P та граматики - множина правил для отримання нетермінальних символів через термінальні та інші нетермінальні символи.

S - стартовий або головний нетермінальний символ.

intx, y, z;

DVARB - >intl iden ( ‘ , ’ iden) * ’;’

PROG->(DVARB | DCONST| DFUNC) *eof

G=(T, N, P, S) та граматики

T={x, y, w, z}

N={ S, A, B }

P={A->AB, A ->x, A ->y, B->w, B->z}

L(G)={xw, yw, xz, yz}

Розширені граматики та граматики

A i - > r i, де A iналежать до N

r i – регулярні вирази із T U N.

A1 – головний.

S - >AB

A - >x|y

B - > w|z

T = { та граматикивино, пиво, каша, борщ, м’ясо, чай, кофе}

N = {ОБІД, АЛКОГОЛЬ, ЇЖА, ПИТНЕ}

ОБІД - > АЛКОГОЛЬ* ЇЖА ПИТНЕ

АЛКОГОЛЬ - >вино| пиво

ЇЖА- >борщ м’ясо| каша

ПИТНЕ - >чай |кофе

Задачі аналізу та граматики

Дано слово і граматика. Перевірити, що слово належить до мови, яка описана цією граматикою. Приклад:

Дано слово [ [ x ] ]

G=(T,N,P,S

T={ [ , ], x, +} N={A,B}

P={A->x, A->[B], B->A, B->B+A}

LA(1) – аналіз. Стратегії зверху – вниз і знизу – вверх.

A ═> [B] ═> [A] ═> [[B]] ═> [[A]] ═> [[x]]

Синтаксичні діаграми та граматики

Орієнтований граф з двома вершинами: вхідною і вихідною.

ά та граматики1|ά2|ά3|

ά та граматики1 ά2 ά3

ά та граматики*

• 1) Не повинно бути непомічених дуг.

• 2) При розгалуженні дуги повинні починатися не з однакових термінальних символів.

• Проходженню дуги, поміченої термінальним символом, відповідає розпізнавання цього символу у вхідному ланцюжку і зсув на наступний символ, якщо розпізнавання відбулося. Інакше – повідомлення про помилку.

• Проходженню дуги, поміченої нетермінальним символом, наприклад А, відповідає виклик відповідної функції розпізнавання ланцюжків, які виводяться з нього. Перед викликом цієї функції потрібно, щоб був прочитаний ПЕРШИЙ ТЕРМІНАЛЬНИЙ символ X, який виводять із А.

• Функція успішно аналізує ланцюжок W, якщо у відповідності до синтаксичної діаграми відбувається попадання із вхідної вершини у вихідну при прочитанні символу за символом усього ланцюжка.

Введення в компіляцію нетермінальним символом, наприклад А, відповідає

• Транслятор – програма, яка перекладаєпрограму із вхідної мови (алгоритмічної) на еквівалентну їй об’єктну програму.

• Якщо вхідна мова високого рівня, а вихідною є машинна мова або асемблер, то такий транслятор наз. компілятором.

• Інтерпретатор– різновидність транслятора, який перекладає на мову простих проміжних команд і виконує її.

• Препроцесор перекладає із однієї мови високого рівня на іншу. Застосовується як частина компілятора.

Структура компілятора нетермінальним символом, наприклад А, відповідає

• ЛА нетермінальним символом, наприклад А, відповідає – лексичний аналізатор. Об’єднує символи в лексеми:

• Ключові і службові слова;

• Ідентифікатори;

• Знаки операцій;

• Знаки пунктуації;

• Числа;

• Признак кінця файлу.

• СА нетермінальним символом, наприклад А, відповідає – синтаксичний аналізатор. Будує із лексем синтаксичні структури, які можуть бути складовими інших структур (константи, змінні, вирази, функції і т. п.).

• ГПК – генерація проміжного коду.

• ОК – оптимізація коду.

• ГК – генерація коду.

Мова нетермінальним символом, наприклад А, відповідає SPL

Символи:

1) Букви: A ÷ Z, a ÷ z

2) 0 ÷ 9

3) + - * / % ( ) , ; = \n \t

Ідентифікатор – букви або букви і цифри, але першою повинна бути буква. До 40 символів.

\n , \t та пропуски не можна вживати в ідентифікаторах.

Константи – тільки цілічисла.

• Змінні нетермінальним символом, наприклад А, відповідає тільки цілого типу: глобальні і локальні.

Службові слова:begin, end, read, print, return, if, then,do, while, int, const – 11 слів.

Функції:

Ім’я (формальні параметри)

begin

локальні змінні і константи

Оператори

end

• Описання констант: нетермінальним символом, наприклад А, відповідає

• const a=12, b=4, d=- 5, s=0;

• Описання змінних:

• int x, y, z, teta ;

• Оператори закінчуються крапкою з комою. Перед end крапку з комою не ставити.

• Одна із функцій повинна бути main()

• Дані в функцію передаються лише по значенню.

• Результат повертається або через return або через глобальні змінні.

• Допускаються рекурсії.

Конструкция нетермінальним символом, наприклад А, відповідає if

ifвиразthenпослідовністьоператорів

end;

оператор_1;

Якщо результат обчислення виразу більше нуля, то виконується послідовність операторів за ключовим словомthen, якщо менше або дорівнює нулю ( ≤ ), то ця послідовність пропускається, і відбувається перехід до наступного за if оператора...

Конструкция нетермінальним символом, наприклад А, відповідає while

whileвиразdoпослідовність_операторів

end;

опер1;

...

Якщо результат обчислення виразу більше нуля, то виконується послідовність операторів за ключовим словом do,після чого знову обчислюється вираз. Якщо результат менше або дорівнює нулю ( ≤ ), то ця послідовність пропускається, і відбувається вихід із циклу.

Функція нетермінальним символом, наприклад А, відповідає ab b≥0

Програма лексичного аналізу нетермінальним символом, наприклад А, відповідає

Прочитати текст програми на SPL, розпізнати лексеми і занести ідентифікатори в таблицю ідентифікаторівchar TNM[400];

Ідентифікатори та їхні адреси занести в файл.

• В програмі кожній лексемі відповідає ціле число. Для символів це код із таблиці ASCII. Для ключових слів цілі числа задаються за допомогою перераховуваних констант( enum).

• enum {BEGINL=257, ENDL, READL, PRITL, RETRL, IFL, THENL, WHILEL, DOL, CONSTL, INTL, IDEN, NUMB};

• Признак кінця файлу в stdio.h

• #define EOF -1

Програма лексичного аналізу відповідає

#include<stdio.h>

#include<stdlib.h>

#include<ctype.h>

#include<conio.h>

#include<alloc.h>

#include<string.h>

/*Кодилексем ключових слів мови SPL*/

enum { BEGINL=257, ENDL, IFL, THENL,

PRITL, INTL, CONSTL, IDEN, NUMB };

int nst=0 відповідає ; //номер рядка в тексті на SPL

int lex;// лексема (ціле число)

int lval; //значення лексеми (для констант це число, а для ідентифікаторів – їхніадреси в таблиціchar TNM[400])

char nch='\n'; // символ, який читається із тексту програми на SPL

FILE*PF,*padres;//файл із текстом програми на SPL і файл для результатів

void get(void);

void number(void);

void word(void);

void main( int ac,char*av[ ] ) відповідає

{

clrscr( );

if(!ac)

{

puts(“Немає файлу із програмою");

exit(1);

}

PF=fopen(av[1],"r");

if(!PF)

puts("Файл не відкривається");

else

get( );// Виклик функції для отримання лексеми

}

void get() відповідає

{

while(nch!=EOF)

{

while(isspace(nch))

{

if( nch= = '\n‘ )

nst++;

nch = getc(PF);

}

If ( isdigit ( nch ) ) відповідає

number( );

else

if( isalpha ( nch ) )

word();

else

if(nch= ='(‘ || nch= =')‘ || nch= =',‘ || nch= = ';‘ ||nch== ‘='

||nch= ='+‘ ||nch= ='-‘ ||nch= ='*‘ || nch=='/‘ || nch= =‘%‘)

{

lex=nch;

nch=getc(PF);

}

}

if(nch= =EOF)

lex=EOF;

else

puts("Hедопустимийсимвол");

return;

}

void number() відповідає

{

for( lval=0; isdigit( nch ); nch= getc(PF))

lval=lval*10+nch - '0';

lex= NUMB;

return;

}

void word( ) відповідає

{

int cdl [ ]={BEGINL,ENDL,IFL,THENL,WHILEL,DOL,

char*serv [ ]={"begin", "end", "if", "then“, "while",

“do", "return", “read", "print", "int", "const“ };

int i;

char tx[40];

char*p;

for(p=tx; isdigit(nch) || isalpha(nch); nch=getc(PF))

*( p++ ) = nch;

*p='\0';

for( i=0; i<11; i++) відповідає

if( strcmp ( tx, serv [ i ] ) == 0)

{

lex=cdl [ i ];

return;

}

lex=IDEN;

lval= (int) add ( tx );

printf("Адреса для %s =%p\n",tx,lval);

return;

}

char TNM[400]; відповідає //таблиця ідентифікаторів char*ptn=TNM; //покажчик на перший вільний елемент в таблиці TNM[400 ]

//*******************************************

{

char*p;

for(p=TNM;p<ptn;p+=strlen(p)+1)

if(strcmp(p,nm)==0)

return p;

if((ptn+=strlen(nm)+1)>TNM+400)

{

puts("Переповнення таблиці ідентифікаторів");

exit( 1 );

}

return ( strcpy ( p, nm ) );

}

Повний синтаксис мови відповідає SPL

• Алфавіт термінальних символів – лексеми.

• Нетермінальні символи:

• PROG, DFUNC, DCONST, DVARB, CONS, PARAM, BODY, STML, STAT, EXPR, TERM, FACT, FCTL.

Регулярні вирази відповідає

PROG - >(DCONST |DVARB| DFUNC )*  eof

DCONST -> constl  CONS (‘,’ CONS) *  ‘;’

CONS - >iden ‘=’ [‘+’ | ’-’] numb

DVARB -> intl  iden (‘,’ iden)* ’;’

DFUNC -> iden  PARAM  BODY

PARAM -> ’(‘  [ iden (‘,’ iden)* ]  ‘)’

BODY->beginl (DVARB| DCONST)* STML endl

STML - > STAT (‘;’ STAT)*

STAT відповідає - >iden ‘=’ EXPR |

pritl EXPR |

retrl EXPR |

ifl EXPR thenl STML endl |whilel EXPR dol STML endl

//*************************************************

EXPR- >[‘+’ | ‘-’] TERM ((‘+’ | ‘-’) TERM)*

TERM відповідає - > FACT((‘*’|’/’|’%’) FACT)*

FACT- > ’(’ EXPR ‘)’ | numb | iden [‘(’ [FCTL] ’)’]

FCTL - > EXPR (‘,’EXPR)*

Синтаксичні діаграми і функції відповідає

розпізнавання ланцюжків для

нетермінальнихсимволів

void exam (int lx) відповідає

{

if (lex!=lx)

{

printf (“Не співпадають лексеми

lex=%i та lx=%i в nst=%i \n”, lex, lx, nst );

exit (1);

}

get ( );

return;

}

Замість відповідає while (nch!=EOF)

{ …

} в програмі тільки лексичного аналізу

Тепер треба запрограмувати

if (nch = = EOF)

{

lex = EOF;

return;

}

Нетермінальний символ  відповідає PROG

PROG - > (DCONST  |DVARB |  DFUNC )*  eof

void prog( ) відповідає

{

while (lex!=EOF)

{

switch (lex)

{

case IDEN: dfunc( ); break;

case INTL: dvarb( ); break;

case CONSTL: dconst( ); break;

default:

printf(“Помилка в nst=%i лексема lex=%i \n”, nst, lex);

}

}

return;

}

void dconst відповідає ( )

{

// Немає “свіжої” лексеми

// потрібно викликати get( );

do

{

get( );

cons( );

} while (lex = = ‘,’);

exam (‘;’);

return;

}

CONS відповідає - >iden ‘=’ [‘+’ | ’-’] numb

//“ відповідає Свіжа” лексема є

void cons( )

{

exam (IDEN);

exam (‘=’);

if (lex = = ‘+’ || lex = = ‘-‘)

get( );

exam (NUMB);

return;

}

Треба спочатку прочитати лексему

void dvarb( )

{

do

{

get( );

exam(IDEN);

} while(lex = = ‘,’);

exam(‘;’);

return;

}

Треба спочатку прочитати лексему

void dfunc( )

{

get( );

param( );

body( );

return;

}

PARAM - >  лексему’(‘ [ iden (‘,’ iden)* ]  ‘)’

void param лексему( )

{

exam (‘(‘);

if (lex ! = ’)’ )

{

exam (IDEN);

while (lex = = ’,’)

{

get( );

exam (IDEN);

}

}

exam (‘)’);

return;

}

BODY- лексему>beginl (DVARB | DCONST)* STML endl

void body( ) лексему

{

exam (BEGINL);

while(lex = = INTL || lex = = CONSTL)

if (lex = = INTL) dvarb( );

else

dconst( );

stml( );

exam(ENDL);

return;

}

STML лексему - >STAT(‘;’STAT)*

void stml( ) лексему

{

stat( );

while (lex = = ‘;’)

{

get( );

stat( );

}

return;

}

STAT лексему -> iden ‘=’EXPR |

pritl EXPR |

retrl EXPR |

iflEXPR thenl STML endl |

whilel EXPR dol STML endl

void stat( ) лексему

{

switch (lex)

{

case IDEN: get( ); exam (‘=’); expr( ); break;

case READL: get( ); exam (IDEN); break;

case PRITL: get( ); expr( ); break;

case RETRL: get( ); expr( ); break;

case IFL: get( ); expr( ); exam(THENL); stml( ); exam(ENDL); break;

case WHILEL: get( ); expr( ); exam(DOL); stml( ); exam(ENDL); break;

default:

printf(“Синтакс. помилка в stat в nst=%i \n”, nst);

}

return;

}

EXPR лексему - > [‘+’ | ‘-’]TERM ((‘+’ | ‘-’) TERM)*

void expr( ) лексему

{

if (lex = = ‘+’ || lex = = ‘-‘)

get( );

term( );

while (lex = = ‘+’ || lex = = ‘-‘)

{

get( );

term( );

}

return;

}

TERM лексему - > FACT((‘*’|’/’|’%’) FACT)*

void term() лексему

{

fact();

while(lex=='*'|| lex == '/'||lex=='%')

{

get();

fact();

}

return;

}

FACT лексему - >(’EXPR ‘)’ | numb | iden [‘(’ [FCTL] ’)’]

void fact( ) лексему

{

switch(lex)

{

case '(': get(); expr(); exam(')'); break;

case IDEN: get(); if ( lex=='(‘ )

{

get();

if ( lex != ')‘ ) fctl( );

exam ( ')‘ );

}

break;

case NUMB: get ( ); break;

default: puts(“Помилка в FACT");

}

return; }

FCTL лексему - > EXPR (‘,’EXPR)*

void fctl() лексему

{

expr();

while(lex==',')

{

get();

expr();

}

return;

}

Інтерпретація лексему

SPL – програма це послідовність проміжних команд, які послідовно заносяться в таблицю команд.

typedef struct

{

int cod; // кодкоманди ( що робити)

int opd; //операнд ( із чим щось робити )

} cmd;

cmd TCD[300]; // таблиця команд

int tc=0; // лічильник команд

Стекова пам лексему’ятьint st [ 500 ]

1) st[0], st[1],…..st[n] – глобальні змінні. Їхня кількість автоматично заноситься в глобальну змінну

int cgv = 0;

2)Далі - фактичні параметри ф-ції main().

3) Кількість фактичних параметрів

ф-ції main().

4)Адреса повернення (АПОВ) (для main() це число -2 )

5) лексемуАдреса активації (ААК)

( для main() це число -1 )

6) Локальні змінні для main().

1)Далі - фактичні параметри ф-ції, наприклад, p0().

2) Кількість фактичних параметрів

ф-ції p0().

3)Адреса повернення для p0().

4) Адреса активації (ААК) дляp0().

ААК лексемув програмі має ідентифікаторsp.

5) Вище від sp розміщуються локальні змінні для p0().

Вершина стеку має ідентифікаторt

Зсув в стеку для глобальних змінних

k= 0,1,2,…cgv.Адреса st[k].

Адреси в стеку для фактичних і локальних параметрів st[sp+k].

Для локальних k=1,2,3,…clv.

Для глобальних k=- ( n+2 ),….-3

n – кількість фактичних параметрів.

f ( x , y , z ) лексему

begin

int a,b;

.……….

………..

end

st[sp-5] – дляx

st[sp-4] – дляy

st[sp-3] – дляz

st[sp+1] – дляa

st[sp+2] – дляb

Робота із таблицями лексему

1) char TNM [ 400] - табл. ідентифікаторів

2) cmd TCD [300] - табл. команд.

3) typedef struct

{

char * name;//ім’я об’єкта

int what;//1- const, 2- глоб. 3- локал.

int val; //знач. для const або зміщенняk

} odc;

odc TOB[100]; // таблиця об’єктів

odc*pto =TOB; odc*ptol=TOB;//покажчики на перший вільний елемент в таблиці для глоб. i локальних змінних

int out=1; // out =1 – глоб. out=0 – локальна.

4) лексемуtypedef struct

{

char* name;//ім’я функції

int isd;// описана (1) чи ні (0)

int cpt;//кількість параметрів

int start;//точка входу в табл. команд

}fnd;

fnd TFN[30];//таблиця функцій

fnd* ptf =TFN;// покажчик на перший вільний елемент в TFN[ ].

Команди лексемуSPL

• enum { OPR, LIT, LDE, LDI, STE, STI, CAL, INI, JMP, JMC };

• OPR 1 – число із stdinзаноситься в вершину стека;

• OPR 2 – число із вершини стека - в stdoutдля виведення на екран;

OPR 3,4,5,6,7 – операції +, -, *, /, %

Перший операнд в t-1, а другий в t . Результат - в t .

• OPR 8 лексему – зміна знака у числа в вершині стеку;

• OPR 9 – повернення результату , який знаходиться в вершині стеку, в викликаючу функцію( return);

• OPR 10 – зупинка програми.

• LIT a – занесення const aв вершину стека t (load into t);

• LDE a – занесення в tглобальної змінної із зміщенням a в стеку(load exetrnal to st[a]) ;

• LDI a лексему - занесення в tлокальної змінної із зміщенням a в стеку(load internal to st [sp + a]) ;

• STE a – число із вершини стеку присвоюється глобальній змінній, розміщеній в стеку із зміщенням a (set external to st [a]);

• STI a – число із вершини стеку присвоюється локальній змінній, розміщеній в стеку із зміщенням a (set internal to st [sp + a] );

CAL a лексему – виклик функції із точкою входу aв таблиці команд cmdTCD[300];

INI a – виділення пам’яті (збільшення адреси вершини стека на а елементів);

JMP a – безумовна передача управління на команду номер а в таблиці команд;

JMC a – умовна передача управлінняна команду номер а в таблиці команд, якщо число в вершині стеку

t≤ 0. Число в tзникає!

Створення лексемуSPL- програми

• Вирази переводяться в зворотній польський вид, коли a+bвиглядає як

• <a><b>+

• Для занесення в стек використана функція void push(int a)

• Для занесення команди в таблицю команд використана функція

• int gen(int co,int op)

Функція занесення в стек лексему

void push(int a)

{

If ( t >= 499 )

{

puts("Переповнення стеку st");

exit(0);

}

st[+ + t ] = a;

return;

}

Функція занесення команд в таблицю команд cmd TCD[300]

int gen(int co,int op)

{

if( tc >= 300)

{

puts("Переповнення TCD");

exit(1);

}

TCD[tc].cod=co;

TCD[tc].opd=op;

return tc++;//звернути увагу на ++

}

1) Занесення константи таблицю команд val:

{ LIT val } – команда SPL;

gen(LIT, val); - функція занесення цієї команди в таблицю командTCD[300];

push ( val ); - функція в програмі інтерпретатора, яка виконує цю команду.

2) { LDE a }

gen ( LDE a );

push ( st [ a ] ); – глобальна змінна по адресі st [a] заноситься в вершину стека.

• 3) таблицю команд { LDI a }

gen ( LDI,a );

push ( st [ sp+a] ); – локальна змінна по адресі st [ sp+a]заноситься в вершину стека t.

4) read e; - оператор мовою SPL

{ OPR 1} { STE a} –прочитана глобальна змінна;

{ OPR 1} { STI a} – прочитана локальна змінна.

5) таблицю команд print e;оператор мовою SPL

<e> { OPR 2} виведення на екран

6) return e;

<e> { OPR 9}

7) e = - e;

<e> { OPR 8}

8) e1 op e2

<e1 ><e2> { OPRop}, де op= 3, 4, 5, 6, 7

відповідно для + - * / %.

9) таблицю команд Виклик функціїf (e1 , e2 , ….. en ) , ізточкою входу а в таблиці команд TCD

<e1><e2>….<en> { LIT n } { CAL a}

10) Описання функції з точкою входу а

F ( p1, p2 , ….. pm )

begin

Локальні змінні і константи

Оператори S

end

a : { INI m} < S > { OPR 10}

• if таблицю команд e then s end

< e > { JMC k } <s> k , де k - перша команда після послідовності операторів s.

12) таблицю команд while e do s end

lb : <e> { JMC k} <s> {JMP lb} k

main ( x, y ) таблицю команд

begin

int c;

c = x – y / c ;

if c then return c

end

Заповнення таблиці команд таблицю команд

• Заповнення відбувається розширеними функціями:

body(); stat(); expr(); term(); fact();

• Використовуються глобальні змінні:

int cgv=0;//кількість глобальних змін.

int clv=0;//кількість локальних змінних

int tc=0;//лічильник занесених команд в таблицю команд.

int out=1;//признак глобальна (1) чи локальна (0) змінна

Функція занесення команд в таблицюкоманд cmd TCD[300]

int gen ( int co,int op)

{

if( tc >= 300)

{

puts("Переповнення TCD");

exit(1);

}

TCD[tc].cod=co;

TCD[tc].opd=op;

return tc++;

}

int body() таблицю

{

int st;//адреса точки входу в TCD[]

exam(BEGINL); clv=0;

while(lex==CONSTL || lex==INTL)

if( lex==CONSTL) dconst();

else dvarb(); // тут можезмінитисяclv

st=gen(INI,clv);

stml();

exam(ENDL);

gen(OPR,10);

return st;//повертає адресу точки входу

}

Пошук елемента даних таблицюnm в таблиці об’єктів TOB[ ]

odc*findob(char*nm)

{

odc*p;

for(p=pto-1;p>=TOB; p--)

if(strcmp(nm,p->name)==0)

return p;

printf("Не описано %s \n“, nm );

return p;

}

void stat () таблицю

{

odc*p;

int t1, t2;

switch(lex)

{

case IFL: get(); expr(); exam(THENL); t1=gen(JMC,0);

stml(); exam(ENDL); TCD[t1].opd=tc; break;

case WHILEL: get(); t1=tc; expr( ); exam (DOL); t2=gen(JMC,0);stml();gen(JMP,t1);TCD[t2].opd=tc;exam(ENDL);break;

case RETRL:get();expr();gen(OPR,9);break; case PRITL:get();expr();gen(OPR,2);break;

if(p->what==1) puts("lval незмінна");

gen(p->what==2?STE:STI,p->val);

exam(IDEN);break;

case IDEN:p=findob((char*)lval);get();exam('=');expr();

if(p->what==1) puts("p->name незмінна");

gen(p->what==2?STE:STI,p->val);

break;

default:

printf(«Помилкав stat()nst=%i lex=%i \n“, nst, lex);

}

return;}

void expr() таблицю

{

int neg=( lex== '-‘ );

If ( lex=='+‘ || lex=='-‘ ) get();

term();

If ( neg ) gen(OPR,8);

while(lex=='+‘ || lex=='-')

{

neg = lex == '-‘ ? 4 : 3;

get();

term(); gen(OPR,neg);

}

return;

}

void term() таблицю

{

int op;

fact();

while( lex== '*‘ || lex == '/‘ || lex == '%‘ )

{

op= lex=='*'? 5: lex== '/’ ? 6: 7;

get();

fact();

gen(OPR,op);

}

return;

}

void fact() таблицю

{

char*nm; int cp; odc*p; fnd*pl;

switch(lex)

{

case IDEN: nm= (char*) lval; get();

if ( lex=='(‘ )

{

get(); cp= ( lex==')‘ ? 0: fctl ( ) ); exam( ')‘ );

pl=eval (nm, cp); gen (LIT, cp);

cp= gen (CAL, pl->start);

if( !pl-> isd ) pl->start=cp;

}

else таблицю

{

p= findob (nm);

gen (p->what==1?LIT: (p->what==2?LDE:LDI),

p->val);

}

break;

case '(': get (); expr (); exam ( ')‘ ); break;

case NUMB: gen( LIT, lval ); get (); break;

default:

printf(“ Errorinfact. nst=%i lex=%i\n“,nst,lex);

}

return;

}

int fctl() таблицю

{

int cf =1; // 1-й вираз

expr();

while(lex==',')

{

get();

expr();

cf++;

}

return cf; //повернення кількості виразів

}

Заповнення таблиці об таблицю’єктів

void newob (char*name, int wt, int vl );

name – ім’я об’єкта;

wt – признак: 1- const, 2- глоб. 3- локал.

vl - знач. для const або зміщення k для змінної.

Виклик із:cons(); dvarb(); param();

Викликається післяget() перед

exam(IDEN); exam(NUMB);

{

odc* pe, *p;

pe = out ? TOB: ptol;

for ( p = pto-1; p> =pe; p-- )

{

if(strcmp (nm, p->name )==0 )

{

puts("Описанадвічі"); exit(0);

}

}

if(pto>=TOB+100){puts("Переповнення TOB");exit(0);}

pto->name=nm;pto->what=wt;pto->val=vl;pto++; // Звернути увагу на ++

return;}

void cons() таблицю

{

char*nm= (char*)lval; int s;

exam(IDEN);

exam('=');

s=( lex=='-') ? -1 : 1;

if( lex=='+‘ || lex== '-‘ )

get();

newob(nm,1,s*lval);puts("Занесенооб’єкт");

exam(NUMB);

return;

}

void dvarb() таблицю

{

do

{

get();

newob((char*)lval,(out?2:3), (out ? cgv++ : ++clv));

exam(IDEN);

}while(lex==',');

exam(';');

return;

}

void dfunc() таблицю

{

int cp,st;char*nm=(char*)lval;

get();

out=0;

cp=param ();

st=body();

out=1;

pto=ptol;

defin (nm, cp, st);

return;

}

int param( таблицю){

odc*p;int cp=0;

exam( '(‘ );

if(lex!=‘)‘)

{

newob((char*)lval,3,++cp);

exam(IDEN);

while(lex==',‘)

{

get();

newob((char*)lval,3,++cp);

exam(IDEN);

}}

exam(‘)‘);

for(p=ptol;p<pto;p++)

p->val- =cp+3;

return cp;

}

Від таблицюptol, (відкіля почали заноситися фактичні параметри), до pto відбувається зсув зміщень на (cp+3) із врахуванням специфіки їхнього розміщення в стеку:

- (n+2) , …. -3, -2 , -1 , 0

st[ sp -2 ] - кількість параметрів;

st[ sp -1 ] - адреса повернення;

st[ sp] - ААК - адреса активації.

n таблицюewfn()-занесення в TFN элемента

fnd*newfn(char*nm,int df,int cp,int ps)

{

if(ptf>=TFN+30)

{

puts("Переповнення TFN");

exit(0);

}

ptf->name=nm;ptf->start=ps;

ptf->isd=df;ptf->cpt=cp;

return ptf++;

}

/*findfn- таблицюпошукфункціїnmвтаблиці TFN*/

fnd*findfn(char*nm)

{

fnd*p;

for(p=ptf-1;p>=TFN;p--)

If(strcmp(p->name,nm)==0)

return p;

return NULL;

}

/*eval()- таблицювикликфункціїnmізcpаргументами*/

fnd*eval ( char*nm, int cp)

{

fnd*p;

if( !(p=findfn (nm))) return newfn(nm,0,cp,-1);

if(p->cpt==cp) return p;

printf("Кількість параметрів для %s не співпадає“, nm);exit(1);

return NULL;

}

/*defin таблицю()-описання функції nm; cp-параметри,

{

fnd*p;

int c1,c2;

p=findfn(nm);

if(p)

{

if(p->isd)

{

printf(”%s oписанадвічі\n”, nm);

exit(1);

}

if(p->cpt!=cp) таблицю

{

printf(« Не сходиться кількість парам. для %s \n“, nm);

exit(1);

}

p->isd=1;

for(c1=p->start; c1!=-1; c1=c2 )

{

с2=TCD[c1].opd;

}

} //відповідна для if (p)

return;

}

/*fmain таблицю()-пошук main и неописаних функцій*/

fnd*fmain()

{

static char nm[]="main“;

fnd*pm=NULL;

fnd*p;

for(p=ptf–1;p>=TFN;p--)

{

if( !p - > isd )

{

puts("Функція не описана p->name");

exit(0);

}

if(strcmp(nm,p->name)==0)pm=p;

}

if(pm) return pm;

puts("Немає main");

return}

void prog() таблицю

{

fnd*p;

while(lex!=EOF)

{

switch(lex)

{

case CONSTL:dconst();break;

case INTL:dvarb();break;

case IDEN:dfunc();break;

default:puts("Ошибкасинтаксиса");

}

}

p=fmain();

return;

}

red()

{

int v,c;

do

{

puts("Введітьчисло");

fflush(stdin);

c=getchar();

}while(isspace(c));

if(!Isdigit(c))

puts(«Помилка при введенні");

for(v=0;isdigit(c);c=getchar())

v=v*10+c-'0';

ungetc(c,stdin);

return v;

}

void interp() stdin*/

{

int i;

t=-1;

printf("SPL:інтерпретація");

for(i=0;i<cgv;i++)

push(0);

if(cpnm)

{

printf("%d>",cpnm);

fflush(stdin);

for(i=0;i<cpnm;i++)

push(red( ));

}

push(cpnm); stdin*/

push(-2);

push(-1);

sp=t;

do

{

comman();

p++;

} while (p>=0);

if( p== -1)

printf ("st [%d] = %d \n ", t, st[ t ] );

}

/* stdin*/Виконання команди*/

comman()

{

int a=TCD[p].opd;

switch(TCD[p].cod)

{

case OPR:operat(a);break;

case LIT:push(a);break;

case LDE:push(st[a]);break;

case LDI:push(st[sp+a]);break;

case STE:st[a]=st[t--];break;

case STI:st[sp+a]=st[t--];break;

case CAL:push(p);push(sp);sp=t;p=a-1;break;

case INI: stdin*/

{

int i;

for(i=0;i<a;i++)

push(0);

}

break;

case JMP:p=a-1;break;

case JMC:if(st[t--]<=0)p=a-1;

}

return;

}

/*operat-виконання операції stdin*/a над вершиною стеку*/

void operat(int a)

{

int j=t-1;

switch(a)

{

case 1:printf("1>“);

fflush(stdout);

push(red( ) );break;

case 2: printf (“ %d \n ", st[ t - - ]); break;

case 3: st [ j ] + = st [ t - - ]; break;

case 4: st [ j ] - = st [ t - - ]; break;

case 5: st [ j ] * = st [ t - - ]; break;

case 6: if (st [t]==0) stdin*/

puts(“ /: ділитель = 0“ );

st [ j ] / = st [ t - - ]; break;

case 7: if (st [ t ] <=0 )

puts("%%:ділитель =0");

st [ j ] % = st [ t - - ]; break;

case 8: st [ t ] = - st [ t ]; break;

case 9: j = st [sp-2]; st [sp- j - 2]= st[t];

t = sp- j- 2; p=st [sp - 1]; sp= st [ sp ]; break;

case 10:p=-3;

}

return;

}

Постановка задачі stdin*/

Створити програму - інтерпретатор для модифікованої мови SPL, в якій добавлена операція піднесення в другу степінь

e stdin*/xp(a,b)

begin int z;

z=1;

while b do

if b%2 then z=z*a end;

a=a*a;b=b/2

end;

return z

end

main()

begin int x,y,z;

print exp(x,y);

z=x ^;

print z;

end

void get() stdin*/

{

if(nch==EOF)

{

lex=EOF;

return;

}

while(isspace(nch))

{

if(nch=='\n')

nst++;

nch=getc(PF);

}

if(isdigit(nch))

number();

else

if(isalpha(nch)) stdin*/

word();

else

if(nch=='('||nch==')'||nch==','||nch==';'||nch=='='

||nch=='+'||nch=='-'||nch=='*'||nch=='/'||nch=='%'||nch=='^')

{

lex=nch;

nch=getc(PF);

}

else

if(nch==EOF)

lex=EOF;

else

puts("Hедопустимый символ");

return;

}

void term() stdin*/

{

int op;

fact();

while(lex=='*'||lex=='/'||lex=='%'||lex=='^')

{

op=lex=='*'?5:lex=='/'?6:lex=='%'?7:11;

get();

if(op!=11)

fact();

gen(OPR,op);

}

return;

}

void operat(int a) stdin*/

{

int j=t-1,kk;

switch(a)

{

case 1:printf("1>");

fflush(stdout);push(red());break;

case 2:printf("%d\n",st[t--]);break;

case 3:st[j]+=st[t--];break;

case 4:st[j]-=st[t--];break;

case 5:st[j]*=st[t--];break;

case 6:if(st[t]==0) puts("/: stdin*/делитель =0");

st[j]/=st[t--];break;

case 7:if(st[t]<=0) puts("%%:делитель =0");

st[j]%=st[t--];break;

case 8:st[t]=-st[t];break;

case 9:for(kk=0;kk<25;kk++)

fprintf(ptc,"tc[%i]=%d \n",kk,st[kk]);

j=st[sp-2];st[sp-j-2]=st[t];

t=sp-j-2;p=st[sp-1];sp=st[sp];break;

case 10:p=-3;

case 11:st[t]*=st[t];

}

return;

}

Постановка задачі stdin*/

Створити програму - інтерпретатор для модифікованої мови SPL, в якійусі ключові слова на російській мові.

Крім того, добавлені дві операції: піднесення у квадрат і збільшення числа (increment) на два.

exp(a ,b) stdin*/

начало

целый z;

z=1;

пока b делать

если b%2 тогда z=z*a конец;

а=a*a; b=b/2

конец

main()

начало

целый x,y;

читать stdin*/x;

читать y;

печать exp(x,y);

печать x^;

печать x@;

конец

/* stdin*/Кодылексемязыка SPL*/

NUMB,IDEN};

int isalpharus(char c);

int isspace1(char c);

int isdigit1(char c);

void get() stdin*/

{

while(lex!=EOF)

{

while(isspace1(nch))

{

if(nch=='\n')

nst++;

nch=getc(PF);

}

if(isdigit1(nch))

number();

if(isalpharus(nch)) stdin*/

word();

else

if(nch=='('||nch==')'||nch==','||nch==';'||nch=='='

||nch=='+'||nch=='-'||nch=='*'||nch=='/'||nch=='%'|| nch=='^'|| nch=='@')

{

lex=nch;

nch=getc(PF);

}

else

if(nch==EOF)

lex=EOF;

else

printf("Hедопустимыйсимвол nch=%c nst=%i\n",nch,nst);

return;

}

void word() stdin*/

{

static char*serv[]={"если","пока","возврат","печать",

"читать","начало","конец","целый","константа",

"тогда","делать"};

ENDL,INTL, CONSTL,THENL,DOL};

int i;

char tx[40];

char*p;

for(p=tx;isdigit1(nch)||isalpharus(nch);nch=getc(PF))

*(p++)=nch;

*p='\0';

int isalpharus(char c) stdin*/

{

int v;

if(isalpha(c)||c=='а'||c=='б'||c=='в'||c=='г'||c=='д'||c=='е'||c=='ж'||c=='з'||c=='д'||c=='е'||c=='ж'||c=='з'||c=='и'||c=='й'||c=='к'||c=='л'

||c=='м'||c=='н'||c=='о'||c=='п'||c=='р'||c=='с'||c=='т'||c=='у'

||c=='ф'||c=='х'||c=='ц'||c=='ч'||c=='ш'||c=='щ'

||c=='ы'||c=='э'||c=='ю'||c=='я'||c=='ь')

v=8;

else

v=0;

return v;

}

int isspace1(char c) stdin*/

{

int v;

if(c==‘ \ ‘ ||c==‘ \n ‘ ||c=='\ t‘ ||c==‘ \f ')

v=1;

else

v=0;

return v;

}

int isdigit1(char c) stdin*/

{

int v;

if(c=='0'||c=='1'||c=='2'||c=='3'||c=='4'||c=='5'||c=='6'||c=='7'||c=='8'||c=='9')

v=2;

else

v=0;

return v;

}

void term() stdin*/

{

int op;

fact();

while(lex=='*'||lex=='/'||lex=='%'||lex=='^'||lex=='@')

{

op=lex=='*'?5:lex=='/'?6:lex=='%'?7:lex=='^'?11:12;

get();

if(op!=11 && op!=12)

{

fact();

}

gen(OPR,op);

}

return;

}

void operat(int a) stdin*/

{

int j=t-1;

switch(a)

{

case 1:printf("1>");

fflush(stdout);push(red());break;

case 2:printf("%d\n",st[t--]);break;

case 3:st[j]+=st[t--];break;

case 4:st[j]-=st[t--];break;

case 5:st[j]*=st[t--];break;

case 6:if(st[t]==0) puts("/:делитель =0");

st[j]/=st[t--];break;

case 7:if(st[t]<=0) puts("%%:делитель =0");

st[j]%=st[t--];break;

case 8:st[t]=-st[t];break; stdin*/

case 9:j=st[sp-2];st[sp-j-2]=st[t];

t=sp-j-2;p=st[sp-1];sp=st[sp];break;

case 10:p=-3;

case 11: st[t] *= st[t]; break;

case 12: st[t] += 2; break;

}

return;

}