Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <ctype.h>
- #include <malloc.h>
- #include <string.h>
- #define KeySet unsigned long int
- #define SymType int
- #define E 1 << // napr. E VALUE => 1 equiv {VALUE}, lebo VALUE = 0
- // Typy symbolov a mnozin symbolov
- enum Symbols {
- BOOLCONST, LPAR, RPAR, ANDD, ORR, SEOF, SERROR, INTCONST
- };
- char* Keywords[2] = { "FALSE", "TRUE"};
- KeySet SymbolSet = 0;
- // Nastavenie SymbolSet na prazdnu mnozinu
- // Vstupne premenne
- char sourceString[100]; // - vstupny retazec
- char c;
- int ic; // vstupny znak a index do vstupneho retazca
- // Vystupny symbol lexikalnej analyzy, jeho kod a atribut
- SymType symbol;
- int attr;
- void getsymbol();
- char *errmsg[]={
- /* 0 */ "Ocakava sa &&",
- /* 1 */ "ocakava sa ||",
- /* 2 */ "ocakava sa (",
- /* 3 */ "ocakava sa ( alebo hodnota",
- /* 4 */ "ocakava sa && alebo podvyraz",
- /* 5 */ "ocakava sa || alebo podvyraz",
- /* 6 */ "ocakava sa )",
- };
- KeySet HTerm = (E BOOLCONST)|(E INTCONST) | (E LPAR);
- KeySet HSub = HTerm;
- KeySet HExpr = HExpr;
- int synerrs=0;
- void error(int n, KeySet keys) {
- printf("SYN_CHYBA: %s\n",errmsg[n]);
- synerrs++;
- while (!((E symbol) & keys)) getsymbol();
- }
- void check(int n, KeySet keys) {
- if (!((E symbol) & keys)) error(n,keys);
- }
- // Lexikalny analyzator
- void getsymbol() {
- char instring[30];
- int is; // pre retazec znakov a klúcové slovo
- c = sourceString[ic];
- ic = ic + 1;
- while (c == ' ') {
- c = sourceString[ic];
- ic = ic + 1;
- }
- switch (c) {
- case '&':
- c = sourceString[ic];
- ic = ic + 1;
- if (c == '&') {
- symbol = ANDD;
- }else {
- ic = ic-1;
- symbol = SERROR;
- }
- break;
- case '|':
- c = sourceString[ic];
- ic = ic + 1;
- if (c == '|') {
- symbol = ORR;
- }else {
- ic = ic-1;
- symbol = SERROR;
- }
- break;
- case '(':
- symbol = LPAR;
- break;
- case ')':
- symbol = RPAR;
- break;
- case '\0':
- symbol = SEOF;
- break;
- default:
- if (c >= '0' && c <= '9') { // celé císlo
- symbol = INTCONST;
- attr = 0;
- while (c >= '0' && c <= '9') {
- attr = attr * 10 + (int) c - (int) '0';
- c = sourceString[ic++];
- }
- ic--;
- } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { // klúcové slovo
- is = 0;
- instring[is++] = toupper(c);
- c = sourceString[ic++];
- while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
- instring[is++] = toupper(c);
- c = sourceString[ic++];
- }
- instring[is] = '\0';
- ic--;
- if (strcmp(instring, Keywords[0]) == 0) { // boolovská konštanta
- symbol = BOOLCONST;
- attr = 0;
- } else if (strcmp(instring, Keywords[1]) == 0) { // boolovská konštanta
- symbol = BOOLCONST;
- attr = 1;
- }else {
- symbol = SERROR;
- }
- } else {
- symbol = SERROR;
- }
- }
- }
- // Koniec lexikálnej analýzy ************************
- // **************************************************
- // Preklad do syntaktického stromu riadený syntaxou
- // **************************************************
- // Definícia syntaktického stromu výrazu
- // Znacky vrcholov stromu
- //Tu su zadefinovane vsetky typy Kostantant -> Int a Boolean ktore sa pouzivaju v programe
- //Dalej Operatory -> polymorfny je OR lebo mozme bud porovnavat int||int alebo vzhodnocovat logickz vyraz BoolConst||BoolConst
- // Operatory -> monomorfne te uz specifikuju ake presne typy sa budu vzhodnocovat , ak napr. prava a lava strana bola Int tak sa nastavy operator na OR_INT_OP
- enum NodeTags {
- // druhy konštánt
- BOOL_CONST,
- INT_CONST,
- // operátory polymorfných operácií
- OR_OP,
- AND_OP,
- // operátory monomorfných operácií
- OR_INT_OP,
- OR_BOOLEAN_OP,
- AND_BOOLEAN_OP,
- UNDEFINED_OP
- };
- // Typová definícia uzla stromu ExpTree
- typedef union ExpTreeNode {
- struct {
- int constTag; //znacka typu konstanty
- int constVal; //hodnota konstanty
- } operand; //operand resp. konstanta
- struct {
- int binOp; //identifikator operatora
- ExpTreeNode* leftTree; //lavy operand - podstrom
- ExpTreeNode* rightTree; //pravy operand - podstrom
- } binaryop; //binarna operacia
- } ExpTree;
- // Konštruktory uzlov stromu výrazu
- // Konštruktor konštanty (listu stromu)
- ExpTree* mkValNode(NodeTags constTag, int constVal) {
- //alokovanie pamate pre uzol stromu
- ExpTreeNode* node = (ExpTreeNode*) malloc(sizeof(ExpTreeNode));
- //priradenie hodnot konstantam uzla
- node->operand.constTag = constTag;
- node->operand.constVal = constVal;
- //vrati vytvoreny uzol
- return node;
- }
- // Konštruktor binárneho operátora
- ExpTree* mkBinNode(NodeTags binOp, ExpTree* leftTree, ExpTree* rightTree) {
- ExpTreeNode* node = (ExpTreeNode*) malloc(sizeof(ExpTreeNode));
- node->binaryop.binOp = binOp;
- node->binaryop.leftTree = leftTree;
- node->binaryop.rightTree = rightTree;
- return node;
- }
- ExpTree* term(KeySet keys);
- ExpTree* expr(KeySet keys);
- ExpTree* sub(KeySet keys);
- // Funkcie pre preklad výrazu do syntakcického stromu
- // (podla pravidiel gramatiky)
- // Vstup: symboly podávané procedúrou getsymbol()
- // Výstup: výraz v tvare syntaktického stromu
- // (konštanty v listoch, operátory v ostatných uzloch
- // Operátory môžu by monomorfné aj polymorfné
- // Ak sú polymorfné, sú nevykonatelné!
- // Interpretator vyrazov s gramatikou
- // Expr -> Sub [ <||> Expr ]
- // Sub -> Term { <&&> Term }
- // Term -> <BOOLVAL> | <INTVAL> | <(> Expr <)>
- // Pozn: Terminalne symboly su v zatvorkach < >
- // Expr -> Sub [ <||> Expr ]
- ExpTree* expr(KeySet keys) {
- SymType sy; // pre zapamätanie symbola na vstupe
- ExpTree* rightTree;
- ExpTree* leftTree; // konštruované (pod)stromy
- KeySet loopkeys, allkeys;
- loopkeys = (E ORR) | HExpr;
- allkeys = loopkeys | keys;
- leftTree = sub(allkeys);
- check(5,allkeys);
- if ((E symbol) & loopkeys) {
- if (symbol == ORR) {
- sy = symbol;
- getsymbol();
- } else {
- error(1, keys);
- }
- rightTree = expr(allkeys);
- if (sy == ORR) {
- leftTree = mkBinNode(OR_OP, leftTree, rightTree);
- }
- check(4,keys);
- }
- return leftTree;
- }
- // Sub -> Term { <&&> Term }
- ExpTree* sub(KeySet keys){
- SymType sy; // pre zapamätanie symbola na vstupe
- ExpTree* rightTree;
- ExpTree* leftTree; // konštruované (pod)stromy
- KeySet loopkeys, allkeys;
- loopkeys = (E ANDD) | HSub;
- allkeys = loopkeys | keys;
- leftTree = term(allkeys);
- check(4,allkeys);
- while ((E symbol) & loopkeys) {
- if (symbol == ANDD) {
- sy = symbol;
- getsymbol();
- } else {
- error(0, keys);
- }
- rightTree = term(allkeys);
- if (sy == ANDD) {
- leftTree = mkBinNode(AND_OP, leftTree, rightTree);
- }
- check(4,allkeys);
- }
- return leftTree;
- }
- // Term -> <BOOLVAL> | <INTVAL> | <(> Expr <)>
- ExpTree* term(KeySet keys){
- ExpTree* subtree; // konštruovaný (pod)strom
- check(3,HTerm | keys);
- switch (symbol) {
- case LPAR :
- if (symbol == LPAR) {
- getsymbol();
- }else {
- error(2, keys);
- }
- subtree = expr((E RPAR) | keys);
- if(symbol==RPAR) {
- getsymbol();
- }
- else {
- error(6,keys);
- }
- break;
- case BOOLCONST:
- subtree = mkValNode(BOOL_CONST, attr);
- getsymbol();
- break;
- case INTCONST:
- subtree = mkValNode(INT_CONST, attr);
- getsymbol();
- break;
- default:
- error(3,keys);
- subtree = mkValNode(UNDEFINED_OP, 0);
- }
- return subtree;
- }
- // **************************************************
- // TEST - Výpis syntaktického stromu
- // **************************************************
- // NETREBA VEDIET
- // Testovacia procedúra pre výpis syntaktického stromu v prefixnej forme
- // (navrhnutá všeobecne pre všetky operátory - monomorfné aj polymorfné)
- void ExpTreePrint(ExpTree* tree) {
- switch (tree->operand.constTag) {
- // Konštanty
- case BOOL_CONST:
- if (tree->operand.constVal == 0)
- printf("False ");
- else
- printf("True ");
- break;
- case INT_CONST:
- printf("%i ", tree->operand.constVal);
- break;
- // Polymorfné operácie
- case AND_OP:
- printf("&& ");
- ExpTreePrint(tree->binaryop.leftTree);
- ExpTreePrint(tree->binaryop.rightTree);
- break;
- case OR_OP:
- printf("|| ");
- ExpTreePrint(tree->binaryop.leftTree);
- ExpTreePrint(tree->binaryop.rightTree);
- break;
- // Monomorfné operácie
- case OR_INT_OP:
- printf("||_int ");
- ExpTreePrint(tree->binaryop.leftTree);
- ExpTreePrint(tree->binaryop.rightTree);
- break;
- case OR_BOOLEAN_OP:
- printf("||_boolean ");
- ExpTreePrint(tree->binaryop.leftTree);
- ExpTreePrint(tree->binaryop.rightTree);
- break;
- case AND_BOOLEAN_OP:
- printf("&&_boolean ");
- ExpTreePrint(tree->binaryop.leftTree);
- ExpTreePrint(tree->binaryop.rightTree);
- break;
- }
- }
- // Koniec testu *************************************
- // **************************************************
- // Sémantická analýza = kontrola typov [ + transformácia stromu]
- // **************************************************
- // [Transformácia stromu vedie k stromu s monomorfnými operátormi]
- // Množina typov
- enum Type {
- BoolType, IntType, AnyType
- };
- // Funkcia sémantického spracovania (typovej kontroly+transformácie)
- // Vstup: výraz (alebo podvýraz) (v našom prípade v tvare stromu)
- // Úcinok: zmena polymorfného operátora na monomorfný v závislosti
- // od typov argumentov operácie (reprezentovaných podstromami)
- // Výstup: monomorfný typ výrazu (podvýrazu)
- // Pozn:
- // 1. Konštanty sú monomorfné (a sú v listoch stromu)
- // 2. Zlyhanie je indikované všeobecným typom AnyType
- // 3. Lepšie je najprv realizovat a otestovat interpretátor
- //Tato funkcia meni polymorfného operátora na monomorfný v závislosti od toho vstupu
- //ak boli zadane spravne vstupy tak tak operacie nastavy na urcene monomorfne operatory inak
- //sa nastavy na neidentifikovatelny typ a tym padom typova kontrola pada a dalej uz sa nemoze vykonat ani vypocet
- Type TypeCheck(ExpTree* tree) {
- Type tyvalLeft;
- Type tyvalRight; // Typ laveho a praveho podvyrazu
- switch (tree->operand.constTag) {
- case BOOL_CONST:
- return BoolType;
- case INT_CONST:
- return IntType;
- case OR_OP:// ak bol nacitany operator OR tak
- tyvalLeft = TypeCheck(tree->binaryop.leftTree);// si zisti typ premmenej z laveho pod stromu
- tyvalRight = TypeCheck(tree->binaryop.rightTree);// si zisti typ premmenej s praveho pod stromu
- if (tyvalLeft == IntType && tyvalRight == IntType) {//a ak je lavy aj pravy Int tak
- tree->binaryop.binOp = OR_INT_OP; //nastavy operator na OR_INT_OP
- return BoolType;
- }else if (tyvalLeft == BoolType && tyvalRight == BoolType) { // alebo ak je lavz aj pravy typu boolean tak
- tree->binaryop.binOp = OR_BOOLEAN_OP;//nastavy operator na OR_BOOLEAN_OP
- return BoolType;
- }else
- return AnyType; // a ak ani jeden s tychto typov tak sa nastavy vysledok vyrazu na AnyType a to znamena ze sa neda vykonat dana operacia a typova kontrola zlyha
- break;
- case AND_OP: //Pri AND sa bud nastavy typ vysledku na boolean ak su obidva typy int inak sa nastavy na Anytype
- tyvalLeft = TypeCheck(tree->binaryop.leftTree);
- tyvalRight = TypeCheck(tree->binaryop.rightTree);
- if (tyvalLeft == BoolType && tyvalRight == BoolType) {
- tree->binaryop.binOp = AND_BOOLEAN_OP;
- return BoolType;
- }else
- return AnyType;
- break;
- default:
- return AnyType;
- }
- }
- // Koniec sémantickej analýzy ***********************
- // **************************************************
- // Interpretátor cielového výrazu v tvare stromu
- // s monomorfnými operáciami
- // **************************************************
- // Typová definícia návratovej hodnoty všetkých monomorfných typov
- //
- typedef union {
- int intval; //ciselna hodnota
- } MonoType;
- // Funkcia výpoctu výrazu - interpretácia cielového stromu
- MonoType* Evaluate(ExpTree* tree) {
- MonoType* cellLeft = (MonoType*) malloc(sizeof(MonoType));
- MonoType* cellRight = (MonoType*) malloc(sizeof(MonoType));
- switch (tree->operand.constTag) {// podla operatora vyberie vyraz ktory bude pocitat
- case BOOL_CONST:
- cellLeft->intval = tree->operand.constVal;
- return cellLeft;
- case INT_CONST:
- cellLeft->intval = tree->operand.constVal;
- return cellLeft;
- //podla typu operatora sa vykona dany case, bud spravy OR s cislami alebo s true a false alebo AND s hodnotami true a false
- case OR_INT_OP:
- cellLeft = Evaluate(tree->binaryop.leftTree); //nacita sa lava strana
- cellRight = Evaluate(tree->binaryop.rightTree); //nacita sa pravastrana
- if (cellLeft->intval == cellRight->intval) { // porovna sa a nastavy vysledok na 1 alebo 0
- cellLeft->intval = 1;
- } else {
- cellLeft->intval = 0;
- }
- return cellLeft;
- break;
- case OR_BOOLEAN_OP:
- cellLeft = Evaluate(tree->binaryop.leftTree);
- cellRight = Evaluate(tree->binaryop.rightTree);
- if (cellLeft->intval || cellRight->intval)
- cellLeft->intval = 1;
- else
- cellLeft->intval = 0;
- return cellLeft;
- break;
- case AND_BOOLEAN_OP:
- cellLeft = Evaluate(tree->binaryop.leftTree);
- cellRight = Evaluate(tree->binaryop.rightTree);
- if (cellLeft->intval && cellRight->intval)
- cellLeft->intval = 1;
- else
- cellLeft->intval = 0;
- return cellLeft;
- break;
- default:
- return cellLeft;
- }
- }
- int main() {
- char tc;
- int i;
- Type ty; // typ hodnoty výrazu - pomocná premenná
- printf("\nSeparatna lexikalna analyza a interpretator vyrazov\n");
- printf("\nKody symbolov: BOOLCONST=0, LPAR=1, RPAR=2, AND=3, OR=4, SEOF=5, SERROR=6, INTCONST=7");
- printf("\n-------------------------------------------------------------------------\n\n");
- printf("Vstupny vyraz (retazec znakov): ");
- // Citanie vstupneho retazca
- for (i = 0; (i < 100) &&
- ((c = getchar()) != '\n'); i++) {
- sourceString[i] = c;
- }
- // Ukoncenie retazca znakom `\0`
- sourceString[i] = '\0';
- //
- ic = 0; // nastavenie na 1. znak
- printf("\nTest lexikalnej analyzy ------------> \n");
- printf("\nVystup lexikalnej analyzy (retazec symbolov)\n\n");
- do {
- getsymbol();
- printf("[%d] ", symbol);
- if (symbol == BOOLCONST)
- printf("<%d> ", attr);
- // tc = getchar();
- printf("\n");
- } while (symbol != SEOF);
- printf("\n<------------Koniec testu lexikalnej analyzy a obnova vstupu\n"); tc=getchar();
- printf("\nZaciatok syntaxou riadenej interpretacie\n\n");
- ic=0; // opatovne nastavenie na 1. znak
- getsymbol();
- ExpTree* syntTree = expr(E SEOF);
- // Kontrolny vypis vyrazu vo forme polymorfneho stromu
- printf("\n----Vypis vo forme polymorfneho stromu: \n");
- ExpTreePrint(syntTree);
- // Semanticka analyza
- printf("\n----Typova kontrola: \n");
- ty = TypeCheck(syntTree);
- if (ty == AnyType) {
- printf("ERROR: Zlyhala typova kontrola\n");
- } else {
- printf("Typova kontrola OK.\n");
- }
- if(ty == BoolType) {
- if (Evaluate(syntTree)->intval == 0) {
- printf("False ");
- } else {
- printf("True ");
- }
- }else if (ty == IntType) {
- printf("%d", Evaluate(syntTree)->intval);
- }
- getchar();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment