Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- quick.c
- #include "quick.h"
- void runFile(const char *fileName){
- char *inbuf=loadFile(fileName);
- puts(inbuf);
- getAtoms(inbuf);
- showAtoms();
- parse();
- }
- int main(int argc,char *argv[]){
- int iArg;
- if(argc==1)err("nu exista fisiere de intrare");
- for(iArg=1;iArg<argc;++iArg){
- runFile(argv[iArg]);
- }
- return 0;
- }
- parser.c
- #include "quick.h"
- Atom *crtAtom;
- Atom *consumed;
- void tkerr(const char *fmt,...){
- va_list va;
- va_start(va,fmt);
- fprintf(stderr,"eroare linia %d: ",crtAtom->line);
- vfprintf(stderr,fmt,va);
- fputc('\n',stderr);
- va_end(va);
- exit(EXIT_FAILURE);
- }
- bool consume(int code){
- if(crtAtom->code==code){
- consumed=crtAtom;
- crtAtom=crtAtom->next;
- return true;
- }
- return false;
- }
- bool block();
- bool expr();
- //factor ::= INT
- // | REAL
- // | STR
- // | LPAR expr RPAR
- // | ID ( LPAR ( expr ( COMMA expr )* )? RPAR )?
- bool factor(){
- if(consume(INT)){
- return true;
- }
- if(consume(REAL)){
- return true;
- }
- if(consume(STR)){
- return true;
- }
- if(consume(LPAR)){
- if(expr()){
- if(consume(RPAR)){
- return true;
- }else tkerr("expresie invalida dupa ( sau lipseste )");
- }else tkerr("expresie invalida dupa (");
- }
- if(consume(ID)){
- if(consume(LPAR)){
- if(expr()){
- while(consume(COMMA)){
- if(expr()){
- }else tkerr("expresie invalida dupa ,");
- }
- }
- if(consume(RPAR)){
- }else tkerr("expresie invalida pentru apel de functie sau lipseste )");
- }
- return true;
- }
- return false;
- }
- //exprPrefix ::= ( SUB | NOT )? factor
- bool exprPrefix(){
- if(consume(SUB)){
- if(factor()){
- return true;
- }else tkerr("expresie invalida dupa -");
- }
- if(consume(NOT)){
- if(factor()){
- return true;
- }else tkerr("expresie invalida dupa !");
- }
- return factor();
- }
- //exprMul ::= exprPrefix ( ( MUL | DIV ) exprPrefix )*
- bool exprMul(){
- if(exprPrefix()){
- for(;;){
- int op;
- if(consume(MUL)){
- op=MUL;
- }
- else if(consume(DIV)){
- op=DIV;
- }
- else break;
- if(exprPrefix()){
- }else tkerr("expresie invalida dupa %s",op==MUL?"*":"/");
- }
- return true;
- }
- return false;
- }
- //exprAdd ::= exprMul ( ( ADD | SUB ) exprMul )*
- bool exprAdd(){
- if(exprMul()){
- for(;;){
- int op;
- if(consume(ADD)){
- op=ADD;
- }
- else if(consume(SUB)){
- op=SUB;
- }
- else break;
- if(exprMul()){
- }else tkerr("expresie invalida dupa %s",op==ADD?"+":"-");
- }
- return true;
- }
- return false;
- }
- //exprComp ::= exprAdd ( ( LESS | EQUAL ) exprAdd )?
- bool exprComp(){
- if(exprAdd()){
- int op;
- if(consume(LESS)){
- op=LESS;
- }
- else if(consume(EQUAL)){
- op=EQUAL;
- }
- else return true;
- if(exprAdd()){
- }else tkerr("expresie invalida dupa %s",op==LESS?"<":"==");
- return true;
- }
- return false;
- }
- //exprAssign ::= ( ID ASSIGN )? exprComp
- bool exprAssign(){
- Atom *start=crtAtom;
- if(consume(ID)){
- if(consume(ASSIGN)){
- if(exprComp()){
- return true;
- }else tkerr("expresie invalida dupa =");
- }
- crtAtom=start;
- }
- return exprComp();
- }
- //exprLogic ::= exprAssign ( ( AND | OR ) exprAssign )*
- bool exprLogic(){
- if(exprAssign()){
- for(;;){
- int op;
- if(consume(AND)){
- op=AND;
- }
- else if(consume(OR)){
- op=OR;
- }
- else break;
- if(exprAssign()){
- }else tkerr("expresie invalida dupa %s",op==AND?"&&":"||");
- }
- return true;
- }
- return false;
- }
- //expr ::= exprLogic
- bool expr(){
- return exprLogic();
- }
- //instr ::= expr? SEMICOLON
- // | IF LPAR expr RPAR block ( ELSE block )? END
- // | RETURN expr SEMICOLON
- // | WHILE LPAR expr RPAR block END
- bool instr(){
- if(expr()){
- if(consume(SEMICOLON)){
- return true;
- }else tkerr("expresie invalida sau lipseste ;");
- return true;
- }
- if(consume(SEMICOLON)){
- return true;
- }
- if(consume(IF)){
- if(consume(LPAR)){
- if(expr()){
- if(consume(RPAR)){
- if(block()){
- }else tkerr("bloc invalid pentru if");
- if(consume(ELSE)){
- if(block()){
- }else tkerr("bloc invalid pentru else");
- }
- if(consume(END)){
- }else tkerr("bloc invalid sau lipseste END dupa if");
- }else tkerr("expresie if invalida sau lipseste )");
- }else tkerr("expresie if invalida");
- }else tkerr("lipseste ( dupa if");
- return true;
- }
- if(consume(RETURN)){
- if(expr()){
- if(consume(SEMICOLON)){
- }else tkerr("expresie invalida pentru return sau lipseste ;");
- }else tkerr("expresie invalida pentru return");
- return true;
- }
- if(consume(WHILE)){
- if(consume(LPAR)){
- if(expr()){
- if(consume(RPAR)){
- if(block()){
- if(consume(END)){
- }else tkerr("bloc invalid pentru while sau lipseste end");
- }else tkerr("bloc invalid pentru while");
- }else tkerr("expresie while invalida sau lipseste )");
- }else tkerr("expresie while invalida");
- }else tkerr("lipseste ( dupa while");
- return true;
- }
- return false;
- }
- //block ::= instr+
- bool block(){
- if(instr()){
- while(instr()){
- }
- return true;
- }
- return false;
- }
- //baseType ::= TYPE_INT | TYPE_REAL | TYPE_STR
- bool baseType(){
- if(consume(TYPE_INT)){
- return true;
- }
- if(consume(TYPE_REAL)){
- return true;
- }
- if(consume(TYPE_STR)){
- return true;
- }
- return false;
- }
- //defVar ::= VAR ID COLON baseType SEMICOLON
- bool defVar(){
- if(consume(VAR)){
- if(consume(ID)){
- if(consume(COLON)){
- if(baseType()){
- if(consume(SEMICOLON)){
- return true;
- }else tkerr("lipseste ; dupa definitia de variabila");
- }else tkerr("lipseste tipul variabilei");
- }else tkerr("lipseste : dupa numele variabilei");
- }else tkerr("lipseste numele variabilei");
- }
- return false;
- }
- //funcParam ::= ID COLON baseType
- bool funcParam(){
- if(consume(ID)){
- if(consume(COLON)){
- if(baseType()){
- return true;
- }else tkerr("lipseste tipul parametrului");
- }else tkerr("lipseste : dupa numele parametrului");
- }
- return false;
- }
- //funcParams ::= ( funcParam ( COMMA funcParam )* )?
- bool funcParams(){
- if(funcParam()){
- while(consume(COMMA)){
- if(funcParam()){
- }else tkerr("parametru invalid dupa ,");
- }
- }
- return true;
- }
- //defFunc ::= FUNCTION ID LPAR funcParams RPAR COLON baseType defVar* block END
- bool defFunc(){
- if(consume(FUNCTION)){
- if(consume(ID)){
- if(consume(LPAR)){
- if(funcParams()){
- if(consume(RPAR)){
- if(consume(COLON)){
- if(baseType()){
- while(defVar()){}
- if(block()){
- if(consume(END)){
- return true;
- }else tkerr("instructiune invalida sau lipseste end dupa functie");
- }else tkerr("bloc invalid pentru functie");
- }else tkerr("tip invalid pentru functie");
- }else tkerr("lipseste : dupa parametrii functiei");
- }else tkerr("parametru invalid sau lipseste ) dupa parametrii functiei");
- }else tkerr("parametri invalizi in definitia functiei");
- }else tkerr("lipseste ( dupa numele functiei");
- }else tkerr("lipseste numele functiei");
- }
- return false;
- }
- //program ::= ( defVar | defFunc | block )* FINISH
- bool program(){
- for(;;){
- if(defVar()){}
- else if(defFunc()){}
- else if(block()){}
- else break;
- }
- if(consume(FINISH))return true;
- tkerr("eroare de sintaxa");
- return false;
- }
- void parse(){
- crtAtom=atoms;
- program();
- }
- lexer.c
- #include "quick.h"
- Atom *atoms, *lastAtom;
- int line=1;
- Atom *addAtom(int code){
- Atom *a=safeAlloc(sizeof(Atom));
- a->code=code;
- a->line=line;
- a->next=NULL;
- if(lastAtom){
- lastAtom->next=a;
- }
- else{
- atoms=a;
- }
- lastAtom=a;
- return a;
- }
- void getAtoms(const char *pch){ //se extrag atomii
- const char *start;
- Atom *a;
- char *aux;
- for(;;){
- char ch=*pch;
- switch(ch){
- case '\0':addAtom(FINISH);return;
- case ' ':case '\t':++pch;break;
- case '\r':
- if(pch[1]=='\n')++pch;
- case '\n':
- ++line;
- ++pch;
- break;
- case ':':addAtom(COLON);++pch;break;
- case ';':addAtom(SEMICOLON);++pch;break;
- case '(':addAtom(LPAR);++pch;break;
- case ')':addAtom(RPAR);++pch;break;
- case ',':addAtom(COMMA);++pch;break;
- case '<':addAtom(LESS);++pch;break;
- case '+':addAtom(ADD);++pch;break;
- case '-':addAtom(SUB);++pch;break;
- case '*':addAtom(MUL);++pch;break;
- case '/':addAtom(DIV);++pch;break;
- case '=':
- switch(pch[1]){
- case '=':addAtom(EQUAL);pch+=2;break;
- default:addAtom(ASSIGN);++pch;
- }
- break;
- case '!':
- switch(pch[1]){
- case '=':addAtom(NOTEQUAL);pch+=2;break;
- default:addAtom(NOT);++pch;
- }
- break;
- case '&':
- if(pch[1]!='&')err("caracter invalid dupa &");
- addAtom(AND);
- pch+=2;
- break;
- case '|':
- if(pch[1]!='|')err("caracter invalid dupa |");
- addAtom(OR);
- pch+=2;
- break;
- case '#':
- for(++pch;(ch=*pch)!='\n'&&ch!='\0';++pch){}
- break;
- case '"':
- for(start=++pch;*pch!='"';++pch){
- if(*pch=='\0')err("lipseste sfarsitul de sir");
- }
- a=addAtom(STR);
- a->text=extract(start,pch);
- ++pch;
- break;
- default:
- if(isalpha(ch)||ch=='_'){
- for(start=pch++;isalnum(ch=*pch)||ch=='_';++pch){}
- int n=pch-start;
- if(n==3&&!memcmp(start,"var",n))addAtom(VAR);
- else if(n==8&&!memcmp(start,"function",n))addAtom(FUNCTION);
- else if(n==2&&!memcmp(start,"if",n))addAtom(IF);
- else if(n==4&&!memcmp(start,"else",n))addAtom(ELSE);
- else if(n==5&&!memcmp(start,"while",n))addAtom(WHILE);
- else if(n==3&&!memcmp(start,"end",n))addAtom(END);
- else if(n==6&&!memcmp(start,"return",n))addAtom(RETURN);
- else if(n==3&&!memcmp(start,"int",n))addAtom(TYPE_INT);
- else if(n==4&&!memcmp(start,"real",n))addAtom(TYPE_REAL);
- else if(n==3&&!memcmp(start,"str",n))addAtom(TYPE_STR);
- else{
- a=addAtom(ID);
- a->text=extract(start,pch);
- }
- }
- else if(isdigit(ch)){
- for(start=pch++;isdigit(*pch);++pch){}
- if(*pch=='.'){
- for(++pch;isdigit(*pch);++pch){}
- a=addAtom(REAL);
- aux=extract(start,pch);
- a->r=atof(aux);
- }else{
- a=addAtom(INT);
- aux=extract(start,pch);
- a->i=atoi(aux);
- }
- free(aux);
- }
- else err("caracter invalid: %c (%d)",ch,ch);
- }
- }
- }
- void showAtom(Atom *a){
- static const char *names[]={"ID","INT","REAL","STR","FINISH",
- // cuvinte cheie
- "VAR","FUNCTION","IF","ELSE","WHILE","END","RETURN","TYPE_INT","TYPE_REAL","TYPE_STR",
- // separatori si operatori
- "COLON","SEMICOLON","LPAR","RPAR","COMMA","OR","AND","NOT",
- "EQUAL","NOTEQUAL","LESS","ASSIGN","ADD","SUB","MUL","DIV"};
- printf("%d %s",a->line,names[a->code]);
- switch(a->code){
- case ID:
- case STR:
- printf(":%s",a->text);
- break;
- case INT:printf(":%d",a->i);break;
- case REAL:printf(":%g",a->r);break;
- }
- }
- void showAtoms(){
- Atom *a;
- for(a=atoms;a;a=a->next){
- showAtom(a);
- putchar('\n');
- }
- }
- utils.c
- #include "quick.h"
- void err(const char *fmt,...){
- va_list va;
- va_start(va,fmt);
- vfprintf(stderr,fmt,va);
- fputc('\n',stderr);
- va_end(va);
- exit(EXIT_FAILURE);
- }
- void *safeAlloc(size_t nBytes){
- void *p=malloc(nBytes);
- if(!p)err("memorie insuficienta");
- return p;
- }
- char *loadFile(const char *fileName){
- FILE *fis=fopen(fileName,"rb");
- if(fis){
- fseek(fis,0,SEEK_END);
- long n=ftell(fis);
- fseek(fis,0,SEEK_SET);
- char *inbuf=(char*)safeAlloc(n+1);
- long nr=fread(inbuf,1,n,fis);
- fclose(fis);
- if(nr!=n)err("nu pot citi tot continutul fisierului %s",fileName);
- inbuf[n]='\0';
- return inbuf;
- }else err("nu pot deschide fisierul %s",fileName);
- return NULL;
- }
- char *extract(const char *begin,const char *after){
- size_t n=after-begin;
- char *buf=safeAlloc(n+1);
- memcpy(buf,begin,n);
- buf[n]='\0';
- return buf;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement