Egzamin+22.06.2007

Z góry dzięki za komentarze.
code format="pascal" var Leksem lek; function Leksem A{ lek:=dajZnak; switch(lek){ case ">": if (P) return "=>"; else return "err"; case "=": if (P) return "=="; else return "err"; default: if (P) return "="; else return "err"; } } function Leksem B{ lek:=dajZnak; switch(lek){ case ">": if (P) return "=>"; else return "err"; case "=": begin lek:=dajZnak; if lek==">" { if (P) return "=="; else return "err";} else return "err"; end; default: return "err"; } } function bool P{ lek:=dajZnak; switch(lek){ case " ": return true; case endln: return true; case "(": begin lek:=dajZnak; if lek=="*" return D; else return false; end; default: return false; } } function bool D{ lek:=dajZnak; switch(lek){ case "=": return D; case "<": return D; case ">": return D; case " ": return D; case ")": return D; case "(": return D; case "*": return G; case endln : return D; case eof: return false; default: return false; } } function bool G{ lek:=dajZnak; switch(lek){ case "=": return D; case "<": return D; case ">": return D; case " ": return D; case "(": return D; case "*": return G; case endln : return D; case ")": return true; case eof: return false; default: return false; } } function Leksem dajLeksem{ lek:=dajZnak; switch(lek){ case "=": return A; case "<": return B; case " " : return dajLeksem; case endln : return dajLeksem; case "(" : begin lek:=dajZnak; if (lek=="*" ) if D return dajLeksem; else return "err"; else return "err"; end; default: return "err"; } } code

eof powduje zawsze blad (*LALA*) tez da blad, wewnatrz komentarza moze byc cokolwiek.

 case ">": return B; //miałeś na myśli "<" ?

niedokonca lapie, jak masz stringa "(=====*) ==" to zwrocisz "= =".

wtf. wiki mi sie wtrynia, nawias otwierajacy, klika razy rowna sie, gwiadka, nawias zamkukajacy, rowna sie x2

I skoro chcialas(es) komentarze :) - wg. mnie latwiej czyta sie i bardziej przypomina zwykly automat sposob pisania kodu jaki jest w drugim egzaminie, trudniej tez zrobic blad.

Nie potrafie zrozumieć porzedniego rozwiązania ;P to jest moje: code format="c" char nextChar = getch;

char getNextChar { char tmp = nextChar; nextChar = getch; return tmp; }

string nextLexem { switch (getNextChar) { case '=': if (nextChar == '>') getNextChar; return "=>"; else if (nextChar == '=') getNextChar; return "=="; else return "="; case '<': if (nextChar == '>') getNextChar; return "<>"; else if (getNextChar == '=' && getNextChar == '>') return "<=>"; else return "err"; case ' ': case '\n': return nextLexem; case '(':       if (getNextChar == '*')            char ch;            repeat {                ch = getNextChar;            }            until ((ch == '*' && nextChar == ')') || ch == EOF); if (ch == EOF) return "err"; else return nextLexem; else return "err"; default: return "err"; } } code

...

STAN 0 : Start-> *E# E-> *E + E E-> *E(E) E->*(E) E-> *n

w stanie 0 po wczytaniu "E" przechodzi do stanu 1 w stanie 0 po wczytaniu "(" przechodzi do stanu 2 w stanie 0 po wczytaniu "n" przechodzi do stanu 3

STAN 1 Start-> E*# E-> E* + E E-> E*(E)

w stanie 1 po wczytaniu "#" przechodzi do stanu 4 w stanie 1 po wczytaniu "+" przechodzi do stanu 5 w stanie 1 po wczytaniu "(" przechodzi do stanu 6

STAN 2 E->(*E) E-> *E + E E-> *E(E) E->*(E) E-> *n

w stanie 2 po wczytaniu "E" przechodzi do stanu 7 w stanie 2 po wczytaniu "(" przechodzi do stanu 2 (czyli zostaje w stanie 2) w stanie 2 po wczytaniu "n" przechodzi do stanu 3

STAN 3 E-> n* redukcja (E->n)

STAN 4 Start-> E#*

STAN 5 E-> E + *E E-> *E + E E-> *E(E) E->*(E) E-> *n

w stanie 5 po wczytaniu "E" przechodzi do stanu 8 w stanie 5 po wczytaniu "(" przechodzi do stanu 2 w stanie 5 po wczytaniu "n" przechodzi do stanu 3

STAN 6 E-> E(*E) E-> *E + E E-> *E(E) E->*(E) E-> *n

w stanie 6 po wczytaniu "E" przechodzi do stanu 9 w stanie 6 po wczytaniu "(" przechodzi do stanu 2 w stanie 6 po wczytaniu "n" przechodzi do stanu 3

STAN 7 E->(E*) E-> E* + E E-> E*(E)

w stanie 7 po wczytaniu ")" przechodzi do stanu 10 w stanie 7 po wczytaniu "+" przechodzi do stanu 5 w stanie 7 po wczytaniu "(" przechodzi do stanu 6

STAN 8 E-> E + E* E-> E* + E E-> E*(E) KONFLIKT: shift-redukcja!!! "podejrzenie" kolejnego znaku nic nie da, bo nie jednoznaczna: E->E+E ->(E+E)+E==E+(E+E)=> nie LR(1)?

konfliktu nie bedzie, bo w LR(1) 5 stan to E->E+*E, $ E->*E+E, ( n czyli po wczytaniu E na postawie nastepnego tokenu decydujemy sie. Reszta gramatyki chyba nie ma juz zadnych problemow.

hmm, nie jedenak bedzie, bo jak wczytamy E takie, ze nie jest $ po nim, to wpadamy w stan E->E+*E, ( n E->*E+E, ( n

hmm. dobra w sumie to nie jestem pewien jak to sie powinno zapisywac. w E -> E+*E, $ E -> *E+E po wczytaniu E mozna wiedziec co zrobic, shift czy redukcja, ale nie wiem jak to zapisac.

Moim zdaniem w LR(1) pojawi się stan typu: E -> E + E*,+ E -> E * + E, # i tu dla plusa jest konflikt - czyli nie jest LR(1) Zresztą, komentarz Zarody: "od razu widać, że gramatyka jest niejednoznaczna, np. n + n + n ma dwa różne wyprowadzenia, więc nie jest LR(1)"

w stanie 8 po wczytaniu "+" przechodzi do stanu 5 w stanie 8 po wczytaniu "(" przechodzi do stanu 6

STAN 9 E-> E(E*) E-> E* + E E-> E*(E)

w stanie 9 po wczytaniu ")" przechodzi do stanu 11 w stanie 9 po wczytaniu "+" przechodzi do stanu 5 w stanie 9 po wczytaniu "(" przechodzi do stanu 6

STAN 10 E->(E)* redukcja (E->(E))

STAN 11 E-> E(E)* redukcja (E-> E(E))

...

code format="c" // Typ E to E.typ, informacje o wymiarze macierzy: E.mac.x i E.mac.y // mac(x, y) to 'konstruktor' typu, ERROR - blad...

E -> E1 * E2 { if (E1.typ == real) { E.typ = E2.typ; } else if (E2.typ == real) { E.typ = E1.typ; } else if (E1.mac.y == E2.mac.x) { E.typ = mac(E1.mac.x, E2.mac.y); } else ERROR; }

// Poprawilem, rzeczywiscie cos mi sie pomieszalo z mnozeniem, dzieki!

code



A) 1)w produkcji wyrazenie->id(wyrazenie) id musi oznaczac f-cje. 2)w produkcji wyrazenie->id id musi oznaczac zmienna 3)w produkcji def-f-cji pierwsze wyrazenie musi byc identyfikatorem zmiennej  4)jedna z funkcji musi miec identyfikator "main" 5)nazwy funkcji musza byc unikalne 6)zmienne musza byc zadeklarowane przed uzyciem (w wyrazeniu z let lub jako argument funkcji) //to jest implikowane przez 1 i 2.

B) addVariable(id) -> dodaje zmienna o nazwie id addFunction(id) -> dodaje funkcje o nazwie id newScope -> powoduje utworzenie nowego bloku nazw (to co w C powoduje {}) popScope -> zdejmuje ostatnio zadeklarowany scope isFunction(id) -> sprawdza czy id jest zadeklarowane, i jezeli tak to czy jako f-cja isVariable(id) -> to samo dla zmiennej C) wyrazenie ::= wyrazenie1 op wyrazenie2 { sprawdz(wyrazenie1); sprawdz(wyrazenie2); } wyrazenie ::= id {if !isVariable(id) { report_error; }} wyrazenie ::= stala calkowita {} wyrazenie ::= id(wyrazenie) {sprawdz(wyrazenie); if(!isFunction(id)) { report_error; }} wyrazenie ::= lef id1 = wyrazenie1 in wyrazenie2 { sprawdz(wyrazenie1); newScope; addVariable(id); sprawdz(wyrazenie2); popScope;}

Wg tego rozwiazania niepoprawny jest program: f (x) = x g(x) = let h = f in h (x) Pytanie czy zmienna lokalna moze byc funkcja (nie wiem z czego mialoby wynikac ze nie). Podobnie skad zalozenie, ze argumentem funkcji nie moze byc funkcja?

Zalozenie wyniklo z tego, ze let pozwala przypisac wartosc, co raczej impliuje np. liczbe niz funkcje, ktora jako taka wartoscia nie musi byc. Oczywiscie f-cja moglaby byc argumentem f-cji, ale skoro nie mozna miec let'owych zmiennych jako f-cje to zalozylem, ze argumenty tez.



Tablica symboli jest jak wyzej, tylko mamy dodatkowa informacje o id, tj. wiemy, pod ktorym numerem w locals ona jest. (czyli w addVariable bierze jeszcze dodatkowy argument, glebokosc zmiennej). Ta informacje uzyskujemy przez getVariableDepth. Dodatkowo na gramatyce umiemy odpalic maxLetInDepth, co zwraca nam maksimum po zagniezdzeniu let'ow.

definicja-f-cji ::= id(wyrazenie1) = wyrazenie2 { int depth = maxLetInDepth; printf("START %s LOCALS %i\n", id, depth); addVariable(wyrazenie1, 0); currentDepth = 1; wygeneruj(wyrazenie2); printf("RETURN\n"); } wyrazenie ::= wyrazenie1 'op' wyrazenie2 { wygeneruj(wyrazenie1); wygeneruj(wyrazenie2); printf("%c ", op); } wyrazenie ::= id { printf("LOAD %i ", getVariableDepth(id)); } wyrazenie ::= stala { printf("CONST %i ", stala); } wyrazenie ::= id(wyrazenie) { wygeneruj(wyrazenie); printf("CALL %s ", id); } wyrazenie ::= let id = wyrazenie1 in wyrazenie2 { wygeneruj(wyrazenie1); printf("STORE %i ", currentDepth); addVariable(id, currentDepth); currentDepth++; newScope; wygeneruj(wyrazenie2); popScope; currentDepth--; }