Advertisement
szilard-dobai

lftc

Mar 9th, 2020
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.84 KB | None | 0 0
  1. quick.c
  2. #include "quick.h"
  3.  
  4. void runFile(const char *fileName){
  5. char *inbuf=loadFile(fileName);
  6. puts(inbuf);
  7. getAtoms(inbuf);
  8. showAtoms();
  9. parse();
  10. }
  11.  
  12. int main(int argc,char *argv[]){
  13. int iArg;
  14. if(argc==1)err("nu exista fisiere de intrare");
  15. for(iArg=1;iArg<argc;++iArg){
  16. runFile(argv[iArg]);
  17. }
  18. return 0;
  19. }
  20.  
  21.  
  22.  
  23. parser.c
  24.  
  25. #include "quick.h"
  26.  
  27. Atom *crtAtom;
  28. Atom *consumed;
  29.  
  30. void tkerr(const char *fmt,...){
  31. va_list va;
  32. va_start(va,fmt);
  33. fprintf(stderr,"eroare linia %d: ",crtAtom->line);
  34. vfprintf(stderr,fmt,va);
  35. fputc('\n',stderr);
  36. va_end(va);
  37. exit(EXIT_FAILURE);
  38. }
  39.  
  40. bool consume(int code){
  41. if(crtAtom->code==code){
  42. consumed=crtAtom;
  43. crtAtom=crtAtom->next;
  44. return true;
  45. }
  46. return false;
  47. }
  48.  
  49. bool block();
  50. bool expr();
  51.  
  52. //factor ::= INT
  53. // | REAL
  54. // | STR
  55. // | LPAR expr RPAR
  56. // | ID ( LPAR ( expr ( COMMA expr )* )? RPAR )?
  57. bool factor(){
  58. if(consume(INT)){
  59. return true;
  60. }
  61. if(consume(REAL)){
  62. return true;
  63. }
  64. if(consume(STR)){
  65. return true;
  66. }
  67. if(consume(LPAR)){
  68. if(expr()){
  69. if(consume(RPAR)){
  70. return true;
  71. }else tkerr("expresie invalida dupa ( sau lipseste )");
  72. }else tkerr("expresie invalida dupa (");
  73. }
  74. if(consume(ID)){
  75. if(consume(LPAR)){
  76. if(expr()){
  77. while(consume(COMMA)){
  78. if(expr()){
  79. }else tkerr("expresie invalida dupa ,");
  80. }
  81. }
  82. if(consume(RPAR)){
  83. }else tkerr("expresie invalida pentru apel de functie sau lipseste )");
  84. }
  85. return true;
  86. }
  87. return false;
  88. }
  89.  
  90. //exprPrefix ::= ( SUB | NOT )? factor
  91. bool exprPrefix(){
  92. if(consume(SUB)){
  93. if(factor()){
  94. return true;
  95. }else tkerr("expresie invalida dupa -");
  96. }
  97. if(consume(NOT)){
  98. if(factor()){
  99. return true;
  100. }else tkerr("expresie invalida dupa !");
  101. }
  102. return factor();
  103. }
  104.  
  105. //exprMul ::= exprPrefix ( ( MUL | DIV ) exprPrefix )*
  106. bool exprMul(){
  107. if(exprPrefix()){
  108. for(;;){
  109. int op;
  110. if(consume(MUL)){
  111. op=MUL;
  112. }
  113. else if(consume(DIV)){
  114. op=DIV;
  115. }
  116. else break;
  117. if(exprPrefix()){
  118. }else tkerr("expresie invalida dupa %s",op==MUL?"*":"/");
  119. }
  120. return true;
  121. }
  122. return false;
  123. }
  124.  
  125. //exprAdd ::= exprMul ( ( ADD | SUB ) exprMul )*
  126. bool exprAdd(){
  127. if(exprMul()){
  128. for(;;){
  129. int op;
  130. if(consume(ADD)){
  131. op=ADD;
  132. }
  133. else if(consume(SUB)){
  134. op=SUB;
  135. }
  136. else break;
  137. if(exprMul()){
  138. }else tkerr("expresie invalida dupa %s",op==ADD?"+":"-");
  139. }
  140. return true;
  141. }
  142. return false;
  143. }
  144.  
  145. //exprComp ::= exprAdd ( ( LESS | EQUAL ) exprAdd )?
  146. bool exprComp(){
  147. if(exprAdd()){
  148. int op;
  149. if(consume(LESS)){
  150. op=LESS;
  151. }
  152. else if(consume(EQUAL)){
  153. op=EQUAL;
  154. }
  155. else return true;
  156. if(exprAdd()){
  157. }else tkerr("expresie invalida dupa %s",op==LESS?"<":"==");
  158. return true;
  159. }
  160. return false;
  161. }
  162.  
  163. //exprAssign ::= ( ID ASSIGN )? exprComp
  164. bool exprAssign(){
  165. Atom *start=crtAtom;
  166. if(consume(ID)){
  167. if(consume(ASSIGN)){
  168. if(exprComp()){
  169. return true;
  170. }else tkerr("expresie invalida dupa =");
  171. }
  172. crtAtom=start;
  173. }
  174. return exprComp();
  175. }
  176.  
  177. //exprLogic ::= exprAssign ( ( AND | OR ) exprAssign )*
  178. bool exprLogic(){
  179. if(exprAssign()){
  180. for(;;){
  181. int op;
  182. if(consume(AND)){
  183. op=AND;
  184. }
  185. else if(consume(OR)){
  186. op=OR;
  187. }
  188. else break;
  189. if(exprAssign()){
  190. }else tkerr("expresie invalida dupa %s",op==AND?"&&":"||");
  191. }
  192. return true;
  193. }
  194. return false;
  195. }
  196.  
  197.  
  198. //expr ::= exprLogic
  199. bool expr(){
  200. return exprLogic();
  201. }
  202.  
  203. //instr ::= expr? SEMICOLON
  204. // | IF LPAR expr RPAR block ( ELSE block )? END
  205. // | RETURN expr SEMICOLON
  206. // | WHILE LPAR expr RPAR block END
  207. bool instr(){
  208. if(expr()){
  209. if(consume(SEMICOLON)){
  210. return true;
  211. }else tkerr("expresie invalida sau lipseste ;");
  212. return true;
  213. }
  214. if(consume(SEMICOLON)){
  215. return true;
  216. }
  217. if(consume(IF)){
  218. if(consume(LPAR)){
  219. if(expr()){
  220. if(consume(RPAR)){
  221. if(block()){
  222. }else tkerr("bloc invalid pentru if");
  223. if(consume(ELSE)){
  224. if(block()){
  225. }else tkerr("bloc invalid pentru else");
  226. }
  227. if(consume(END)){
  228. }else tkerr("bloc invalid sau lipseste END dupa if");
  229. }else tkerr("expresie if invalida sau lipseste )");
  230. }else tkerr("expresie if invalida");
  231. }else tkerr("lipseste ( dupa if");
  232. return true;
  233. }
  234. if(consume(RETURN)){
  235. if(expr()){
  236. if(consume(SEMICOLON)){
  237. }else tkerr("expresie invalida pentru return sau lipseste ;");
  238. }else tkerr("expresie invalida pentru return");
  239. return true;
  240. }
  241. if(consume(WHILE)){
  242. if(consume(LPAR)){
  243. if(expr()){
  244. if(consume(RPAR)){
  245. if(block()){
  246. if(consume(END)){
  247. }else tkerr("bloc invalid pentru while sau lipseste end");
  248. }else tkerr("bloc invalid pentru while");
  249. }else tkerr("expresie while invalida sau lipseste )");
  250. }else tkerr("expresie while invalida");
  251. }else tkerr("lipseste ( dupa while");
  252. return true;
  253. }
  254. return false;
  255. }
  256.  
  257. //block ::= instr+
  258. bool block(){
  259. if(instr()){
  260. while(instr()){
  261. }
  262. return true;
  263. }
  264. return false;
  265. }
  266.  
  267. //baseType ::= TYPE_INT | TYPE_REAL | TYPE_STR
  268. bool baseType(){
  269. if(consume(TYPE_INT)){
  270. return true;
  271. }
  272. if(consume(TYPE_REAL)){
  273. return true;
  274. }
  275. if(consume(TYPE_STR)){
  276. return true;
  277. }
  278. return false;
  279. }
  280.  
  281. //defVar ::= VAR ID COLON baseType SEMICOLON
  282. bool defVar(){
  283. if(consume(VAR)){
  284. if(consume(ID)){
  285. if(consume(COLON)){
  286. if(baseType()){
  287. if(consume(SEMICOLON)){
  288. return true;
  289. }else tkerr("lipseste ; dupa definitia de variabila");
  290. }else tkerr("lipseste tipul variabilei");
  291. }else tkerr("lipseste : dupa numele variabilei");
  292. }else tkerr("lipseste numele variabilei");
  293. }
  294. return false;
  295. }
  296.  
  297. //funcParam ::= ID COLON baseType
  298. bool funcParam(){
  299. if(consume(ID)){
  300. if(consume(COLON)){
  301. if(baseType()){
  302. return true;
  303. }else tkerr("lipseste tipul parametrului");
  304. }else tkerr("lipseste : dupa numele parametrului");
  305. }
  306. return false;
  307. }
  308.  
  309. //funcParams ::= ( funcParam ( COMMA funcParam )* )?
  310. bool funcParams(){
  311. if(funcParam()){
  312. while(consume(COMMA)){
  313. if(funcParam()){
  314. }else tkerr("parametru invalid dupa ,");
  315. }
  316. }
  317. return true;
  318. }
  319.  
  320. //defFunc ::= FUNCTION ID LPAR funcParams RPAR COLON baseType defVar* block END
  321. bool defFunc(){
  322. if(consume(FUNCTION)){
  323. if(consume(ID)){
  324. if(consume(LPAR)){
  325. if(funcParams()){
  326. if(consume(RPAR)){
  327. if(consume(COLON)){
  328. if(baseType()){
  329. while(defVar()){}
  330. if(block()){
  331. if(consume(END)){
  332. return true;
  333. }else tkerr("instructiune invalida sau lipseste end dupa functie");
  334. }else tkerr("bloc invalid pentru functie");
  335. }else tkerr("tip invalid pentru functie");
  336. }else tkerr("lipseste : dupa parametrii functiei");
  337. }else tkerr("parametru invalid sau lipseste ) dupa parametrii functiei");
  338. }else tkerr("parametri invalizi in definitia functiei");
  339. }else tkerr("lipseste ( dupa numele functiei");
  340. }else tkerr("lipseste numele functiei");
  341. }
  342. return false;
  343. }
  344.  
  345. //program ::= ( defVar | defFunc | block )* FINISH
  346. bool program(){
  347. for(;;){
  348. if(defVar()){}
  349. else if(defFunc()){}
  350. else if(block()){}
  351. else break;
  352. }
  353. if(consume(FINISH))return true;
  354. tkerr("eroare de sintaxa");
  355. return false;
  356. }
  357.  
  358. void parse(){
  359. crtAtom=atoms;
  360. program();
  361. }
  362.  
  363.  
  364.  
  365. lexer.c
  366. #include "quick.h"
  367.  
  368. Atom *atoms, *lastAtom;
  369. int line=1;
  370.  
  371. Atom *addAtom(int code){
  372. Atom *a=safeAlloc(sizeof(Atom));
  373. a->code=code;
  374. a->line=line;
  375. a->next=NULL;
  376. if(lastAtom){
  377. lastAtom->next=a;
  378. }
  379. else{
  380. atoms=a;
  381. }
  382. lastAtom=a;
  383. return a;
  384. }
  385.  
  386. void getAtoms(const char *pch){ //se extrag atomii
  387. const char *start;
  388. Atom *a;
  389. char *aux;
  390. for(;;){
  391. char ch=*pch;
  392. switch(ch){
  393. case '\0':addAtom(FINISH);return;
  394. case ' ':case '\t':++pch;break;
  395. case '\r':
  396. if(pch[1]=='\n')++pch;
  397. case '\n':
  398. ++line;
  399. ++pch;
  400. break;
  401. case ':':addAtom(COLON);++pch;break;
  402. case ';':addAtom(SEMICOLON);++pch;break;
  403. case '(':addAtom(LPAR);++pch;break;
  404. case ')':addAtom(RPAR);++pch;break;
  405. case ',':addAtom(COMMA);++pch;break;
  406. case '<':addAtom(LESS);++pch;break;
  407. case '+':addAtom(ADD);++pch;break;
  408. case '-':addAtom(SUB);++pch;break;
  409. case '*':addAtom(MUL);++pch;break;
  410. case '/':addAtom(DIV);++pch;break;
  411. case '=':
  412. switch(pch[1]){
  413. case '=':addAtom(EQUAL);pch+=2;break;
  414. default:addAtom(ASSIGN);++pch;
  415. }
  416. break;
  417. case '!':
  418. switch(pch[1]){
  419. case '=':addAtom(NOTEQUAL);pch+=2;break;
  420. default:addAtom(NOT);++pch;
  421. }
  422. break;
  423. case '&':
  424. if(pch[1]!='&')err("caracter invalid dupa &");
  425. addAtom(AND);
  426. pch+=2;
  427. break;
  428. case '|':
  429. if(pch[1]!='|')err("caracter invalid dupa |");
  430. addAtom(OR);
  431. pch+=2;
  432. break;
  433. case '#':
  434. for(++pch;(ch=*pch)!='\n'&&ch!='\0';++pch){}
  435. break;
  436. case '"':
  437. for(start=++pch;*pch!='"';++pch){
  438. if(*pch=='\0')err("lipseste sfarsitul de sir");
  439. }
  440. a=addAtom(STR);
  441. a->text=extract(start,pch);
  442. ++pch;
  443. break;
  444. default:
  445. if(isalpha(ch)||ch=='_'){
  446. for(start=pch++;isalnum(ch=*pch)||ch=='_';++pch){}
  447. int n=pch-start;
  448. if(n==3&&!memcmp(start,"var",n))addAtom(VAR);
  449. else if(n==8&&!memcmp(start,"function",n))addAtom(FUNCTION);
  450. else if(n==2&&!memcmp(start,"if",n))addAtom(IF);
  451. else if(n==4&&!memcmp(start,"else",n))addAtom(ELSE);
  452. else if(n==5&&!memcmp(start,"while",n))addAtom(WHILE);
  453. else if(n==3&&!memcmp(start,"end",n))addAtom(END);
  454. else if(n==6&&!memcmp(start,"return",n))addAtom(RETURN);
  455. else if(n==3&&!memcmp(start,"int",n))addAtom(TYPE_INT);
  456. else if(n==4&&!memcmp(start,"real",n))addAtom(TYPE_REAL);
  457. else if(n==3&&!memcmp(start,"str",n))addAtom(TYPE_STR);
  458. else{
  459. a=addAtom(ID);
  460. a->text=extract(start,pch);
  461. }
  462. }
  463. else if(isdigit(ch)){
  464. for(start=pch++;isdigit(*pch);++pch){}
  465. if(*pch=='.'){
  466. for(++pch;isdigit(*pch);++pch){}
  467. a=addAtom(REAL);
  468. aux=extract(start,pch);
  469. a->r=atof(aux);
  470. }else{
  471. a=addAtom(INT);
  472. aux=extract(start,pch);
  473. a->i=atoi(aux);
  474. }
  475. free(aux);
  476. }
  477. else err("caracter invalid: %c (%d)",ch,ch);
  478. }
  479. }
  480. }
  481.  
  482. void showAtom(Atom *a){
  483. static const char *names[]={"ID","INT","REAL","STR","FINISH",
  484. // cuvinte cheie
  485. "VAR","FUNCTION","IF","ELSE","WHILE","END","RETURN","TYPE_INT","TYPE_REAL","TYPE_STR",
  486. // separatori si operatori
  487. "COLON","SEMICOLON","LPAR","RPAR","COMMA","OR","AND","NOT",
  488. "EQUAL","NOTEQUAL","LESS","ASSIGN","ADD","SUB","MUL","DIV"};
  489. printf("%d %s",a->line,names[a->code]);
  490. switch(a->code){
  491. case ID:
  492. case STR:
  493. printf(":%s",a->text);
  494. break;
  495. case INT:printf(":%d",a->i);break;
  496. case REAL:printf(":%g",a->r);break;
  497. }
  498. }
  499.  
  500. void showAtoms(){
  501. Atom *a;
  502. for(a=atoms;a;a=a->next){
  503. showAtom(a);
  504. putchar('\n');
  505. }
  506. }
  507.  
  508.  
  509. utils.c
  510. #include "quick.h"
  511.  
  512. void err(const char *fmt,...){
  513. va_list va;
  514. va_start(va,fmt);
  515. vfprintf(stderr,fmt,va);
  516. fputc('\n',stderr);
  517. va_end(va);
  518. exit(EXIT_FAILURE);
  519. }
  520.  
  521. void *safeAlloc(size_t nBytes){
  522. void *p=malloc(nBytes);
  523. if(!p)err("memorie insuficienta");
  524. return p;
  525. }
  526.  
  527. char *loadFile(const char *fileName){
  528. FILE *fis=fopen(fileName,"rb");
  529. if(fis){
  530. fseek(fis,0,SEEK_END);
  531. long n=ftell(fis);
  532. fseek(fis,0,SEEK_SET);
  533. char *inbuf=(char*)safeAlloc(n+1);
  534. long nr=fread(inbuf,1,n,fis);
  535. fclose(fis);
  536. if(nr!=n)err("nu pot citi tot continutul fisierului %s",fileName);
  537. inbuf[n]='\0';
  538. return inbuf;
  539. }else err("nu pot deschide fisierul %s",fileName);
  540. return NULL;
  541. }
  542.  
  543. char *extract(const char *begin,const char *after){
  544. size_t n=after-begin;
  545. char *buf=safeAlloc(n+1);
  546. memcpy(buf,begin,n);
  547. buf[n]='\0';
  548. return buf;
  549. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement