/* Syntax analyser * by Marek Zelem */ #include #include #include #include "language.h" static int patri_term(tab_t * tab, sym_t term) { int i; if ( /* term==END && */ tab->terminal[0] == END) return 1; for (i = 0; i < 16 && tab->terminal[i] != END; i++) { if (tab->terminal[i] == term) return 1; if (term == END && tab->terminal[i] == TEND) return 1; } return 0; } static tab_t *najdi_tab(tab_t * tab, sym_t stav, sym_t term) { while (tab->stav != END) { if (tab->stav == stav && patri_term(tab, term)) return tab; tab++; } return NULL; } #define RESIZE_STACK \ if( (stack=realloc(stack,sizeof(sym_t)*stacksize))==NULL )\ return(E|0x0fff) static sym_t get_want(sym_t * stack, int stacklen) { while (stacklen >= 0) { if ((stack[stacklen] & TYP) == T) return stack[stacklen]; if ((stack[stacklen] & TYP) != O) return END; stacklen--; } return END; } sym_t sa_automat(tab_t * tab, sym_t start, sym_t(*lex) (lex_t *, long, sym_t), void (*out) (lex_t *, sym_t), long d) { lex_t l; int i; tab_t *t; sym_t *stack, want; int stacklen, stacksize; stack = NULL; stacklen = 0; stacksize = 100; RESIZE_STACK; stack[stacklen++] = start; lex(&l, d, END); if ((l.sym & TYP) == E) { free(stack); return l.sym; } while (stacklen > 0) { while ((t = najdi_tab(tab, stack[stacklen - 1], l.sym)) == NULL) { lang_error("Unexpected %s", lex2str(&l)); //printf("\nError: Here can't be %s (line %d column %d)\n",lex2str(&l), //lex_line,lex_char); if (l.sym != END) lex(&l, d, END); else { free(stack); return E | 0; } } stacklen--; i = 0; while (t->stack[i] != END) i++; i--; while (i >= 0) { stack[stacklen++] = t->stack[i--]; if (stacklen >= stacksize) { stacksize += 100; RESIZE_STACK; } } while (stacklen > 0 && ((stack[stacklen - 1] & TYP) == T || (stack[stacklen - 1] & TYP) == O) ) { if ((stack[stacklen - 1] & TYP) == T) { if (l.sym != stack[stacklen - 1]) { lex_t pl; pl.sym = stack[stacklen - 1]; pl.num = 0; lang_error("Missing %s", lex2str(&pl)); //printf("\nError: expected symbol %s ",lex2str(&pl) ); //printf("and come %s on line %d column %d\n",lex2str(&l),lex_line,lex_char); // free(stack); // return(E|1); } else { if (l.sym != END) { want = get_want(stack, stacklen - 2); lex(&l, d, want); } if ((l.sym & TYP) == E) { free(stack); lang_error("Lexical %d", l.sym & ~TYP); return l.sym; } } } if ((stack[stacklen - 1] & TYP) == O) { out(&l, stack[stacklen - 1]); } stacklen--; } } free(stack); return T; }