Advertisement
alexarcan

lexical an_almost done

Mar 31st, 2016
302
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.73 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5. #include<ctype.h>
  6. #include <malloc.h>
  7. #define SIZE 2046
  8.  
  9. #define SAFEALLOC(var,Type) if((var=(Type*)malloc(sizeof(Type)))==NULL)err("not enough memory");
  10.  
  11. enum{
  12.   ID, END,
  13.   //constants
  14.   CT_INT, CT_REAL, CT_CHAR, CT_STRING,
  15.   //keywords
  16.   BREAK, CHAR, DOUBLE, ELSE, FOR, IF, INT, RETURN, STRUCT, VOID, WHILE,
  17.   //delimiters
  18.   COMMA, SEMICOLON, LPAR, RPAR, LBRACKET, RBRACKET, LACC, RACC,
  19.   //operators
  20.   ADD, SUB, MUL, DIV, DOT, AND, OR, NOT, ASSIGN, EQUAL, NOTEQ, LESS, LESSEQ, GREATER, GREATEREQ,
  21.   SPACE, LINECOMMENT, COMMENT
  22. }; //tokens codes
  23.  
  24. typedef struct _Token
  25. {
  26.   int code;
  27.   union{
  28.     char *text;
  29.     long int i;
  30.     double r;
  31.   };
  32.   int line;
  33.   struct _Token *next;
  34. }Token;
  35.  
  36. Token *tokens;
  37. Token *lastToken = NULL;
  38. const char *pCrtCh;
  39. int line;
  40.  
  41. void err(const char *fmt,...)
  42. {
  43.   va_list va;
  44.   va_start(va,fmt);
  45.   fprintf(stderr,"error: ");
  46.   vfprintf(stderr,fmt,va);
  47.   fputc('\n',stderr);
  48.   va_end(va);
  49.   exit(-1);
  50. }
  51.  
  52.  
  53. void tkerr(const Token *tk,const char *fmt,...)
  54. {
  55.   va_list va;
  56.   va_start(va,fmt);
  57.   fprintf(stderr,"error in line %d: ",tk->line);
  58.   vfprintf(stderr,fmt,va);
  59.   fputc('\n',stderr);
  60.   va_end(va);
  61.   exit(-1);
  62. }
  63.  
  64.  
  65. Token *addTk(int code)
  66. {
  67.   Token *tk;
  68.   SAFEALLOC(tk,Token)
  69.   tk->code=code;
  70.   tk->line=line;
  71.   tk->next=NULL;
  72.   if(lastToken)
  73.   {
  74.     lastToken->next=tk;
  75.   }
  76.   else
  77.   {
  78.     tokens=tk;
  79.   }
  80.   lastToken=tk;
  81.   return tk;
  82. }
  83.  
  84. char* createString(const char *pStartCh,const char *pCrtCh)
  85. {
  86.   int nCh=pCrtCh-pStartCh+1;
  87.   char *str;
  88.   str=(char *)malloc(nCh*sizeof(char));
  89.   snprintf(str,nCh,"%s",pStartCh);
  90.   return str;
  91. }
  92.  
  93. char escCode(char ch)
  94. {
  95.   char newCh;
  96.   switch(ch)
  97.   {
  98.     case 'a': newCh='\a'; break;
  99.     case 'b': newCh='\b'; break;
  100.     case 'f': newCh='\f'; break;
  101.     case 'n': newCh='\n'; break;
  102.     case 'r': newCh='\r'; break;
  103.     case 't': newCh='\t'; break;
  104.     case '\'': newCh='\''; break;
  105.     case '\?': newCh='\?'; break;
  106.     case '\"': newCh='\"'; break;
  107.     case '\\': newCh='\\'; break;
  108.     case '0': newCh='\0'; break;
  109.   }
  110.   return newCh;
  111. }
  112.  
  113. void printTokens()
  114. {
  115.   Token *current=tokens;
  116.   while(current!=NULL)
  117.   {
  118.     //printf("%i", current->code);
  119.     switch(current->code)
  120.     {
  121.       case ID:
  122.     printf("ID:%s ",current->text);
  123.       case CT_STRING:
  124.     printf("CT_STRING:%s ",current->text);
  125.     break;
  126.       case CT_CHAR:
  127.     printf("CT_CHAR:%c ",(int)current->i);
  128.     break;
  129.       case CT_INT:
  130.     printf("CT_INT:%li ",current->i);
  131.     break;
  132.       case CT_REAL:
  133.     printf("CT_REAL:%lf",current->r);
  134.     break;
  135.       case LPAR:
  136.     printf("LPAR:%c ",(int)current->i);
  137.  
  138.     }
  139.     printf(" ");
  140.     current=current->next;
  141.   }
  142.   printf("\n");
  143. }
  144.  
  145.  
  146. int getNextToken()
  147. {
  148.   int state=0,nCh;
  149.   char ch;
  150.   const char *pStartCh;
  151.   Token *tk;
  152.  
  153.   long int ct_int;
  154.   double ct_real;
  155.   int ct_char;
  156.   char *ct_string;
  157.   char *p;
  158.   //int noBacks=0;
  159.   //int i; 
  160.  
  161.   while(1)
  162.   {
  163.     ch=*pCrtCh;
  164.     printf("state: %d, character:%c\n",state,ch);
  165.     switch(state)
  166.     {
  167.       case 0:
  168.     if(isalpha(ch)||ch=='_')
  169.     {
  170.       pStartCh=pCrtCh;
  171.       pCrtCh++;
  172.       state=22;
  173.     }
  174.    
  175.     else if(ch==' '||ch=='\r'||ch=='\t')
  176.     {
  177.       pCrtCh++; // consume the characterand remains in state 0
  178.     }
  179.     else if(ch=='\n')//handled separately in order to update the current line
  180.     {
  181.       line++;
  182.       pCrtCh++;
  183.     }
  184.     else if(ch>='1' || ch<='9')
  185.     {
  186.       pCrtCh++;
  187.       state=1;   
  188.     }
  189.     else if(ch=='0')
  190.     {
  191.       pCrtCh++;
  192.       state=2;
  193.     }
  194.     else if(ch=='/')
  195.     {
  196.       pCrtCh++;
  197.       state=24;        
  198.     }
  199.     else if(ch=='\'')
  200.     {
  201.       pStartCh=pCrtCh;
  202.       pCrtCh++;
  203.       state=14;        
  204.     }
  205.     else if(ch=='\"')
  206.     {
  207.       pStartCh=pCrtCh;
  208.       pCrtCh++;
  209.       state=18;
  210.     }
  211.    
  212.     else if(ch==',')
  213.     {
  214.       pCrtCh++;
  215.       addTk(COMMA);
  216.       return COMMA;
  217.     }
  218.     else if(ch==';')
  219.     {
  220.       pCrtCh++;
  221.       addTk(SEMICOLON);
  222.       return SEMICOLON;
  223.     }
  224.     else if(ch=='(')
  225.     {
  226.       pCrtCh++;
  227.       addTk(LPAR);
  228.       return LPAR;
  229.     }
  230.     else if(ch==')')
  231.     {
  232.       pCrtCh++;
  233.       addTk(RPAR);
  234.       return RPAR;
  235.     }
  236.     else if(ch=='[')
  237.     {
  238.       pCrtCh++;
  239.       addTk(LBRACKET);
  240.       return LBRACKET;
  241.     }
  242.     else if(ch==']')
  243.     {
  244.       pCrtCh++;
  245.       addTk(RBRACKET);
  246.       return RBRACKET;
  247.     }
  248.     else if(ch=='{')
  249.     {
  250.       pCrtCh++;
  251.       addTk(LACC);
  252.       return LACC;
  253.     }
  254.     else if(ch=='}')
  255.     {
  256.       pCrtCh++;
  257.       addTk(RACC);
  258.       return RACC;
  259.     }
  260.     else if(ch=='+')
  261.     {
  262.       pCrtCh++;
  263.       addTk(ADD);
  264.       return ADD;
  265.     }
  266.     else if(ch=='-')
  267.     {
  268.       pCrtCh++;
  269.       addTk(SUB);
  270.       return SUB;
  271.     }
  272.     else if(ch=='*')
  273.     {
  274.       pCrtCh++;
  275.       addTk(MUL);
  276.       return MUL;
  277.     }
  278.     else if(ch=='.')
  279.     {
  280.       pCrtCh++;
  281.       addTk(DOT);
  282.       return DOT;
  283.     }
  284.     else if(ch=='&')
  285.     {
  286.       pCrtCh++;
  287.       state=43;
  288.     }
  289.     else if(ch=='|')
  290.     {
  291.       pCrtCh++;
  292.       state=45;
  293.     }
  294.     else if(ch=='!')
  295.     {
  296.       pCrtCh++;
  297.       state=47;
  298.     }
  299.     else if(ch=='=')
  300.     {
  301.       pCrtCh++;
  302.       state=48;
  303.     }
  304.     else if(ch=='<')
  305.     {
  306.       pCrtCh++;
  307.       state=51;
  308.     }
  309.     else if(ch=='>')
  310.     {
  311.       pCrtCh++;
  312.       state=54;
  313.     }
  314.    
  315.     else if(ch==0) //the end of the input string
  316.     {
  317.       addTk(END);
  318.       return END;
  319.     }          
  320.     else
  321.     {
  322.       tkerr(addTk(END),"invalid character");
  323.       printf("invalid character ch=%c\n",ch);    
  324.     }
  325.    
  326.     break;
  327.    
  328.     case 1:
  329.       if(ch>='0'&&ch<='9')
  330.       {
  331.         pCrtCh++;
  332.         //state=1;
  333.       }
  334.       else if(ch=='.')
  335.       {
  336.         pCrtCh++;
  337.         state=8;
  338.       }
  339.       else if(ch=='e'||ch=='E')
  340.       {
  341.         pCrtCh++;
  342.         state=10;
  343.       }
  344.       else
  345.         state=6;
  346.       break;
  347.     case 2:
  348.       if(ch=='x'||ch=='X')
  349.       {
  350.         pCrtCh++;
  351.         state=4;
  352.       }
  353.       else
  354.         state=3;
  355.       break;
  356.     case 3:
  357.       if(ch>='0'&&ch<='7')
  358.       {
  359.         pCrtCh++;
  360.       }
  361.       else if(ch=='.')
  362.       {
  363.         pCrtCh++;
  364.         state=8;
  365.       }
  366.       else if(ch=='e'||ch=='E')
  367.       {
  368.         pCrtCh++;
  369.         state=10;
  370.       }
  371.       else
  372.         state=6;
  373.       break;
  374.     case 4:
  375.       if((ch>='0'&&ch<='9') || (ch>='a'&&ch<='f') || (ch>='A'&&ch<='F'))
  376.       {
  377.         pCrtCh++;
  378.         state=5;
  379.       }
  380.       else
  381.         tkerr(addTk(END),"not a valid int");
  382.       break;
  383.     case 5:
  384.       if((ch>='0'&&ch<='9') || (ch>='a'&&ch<='f') || (ch>='A'&&ch<='F'))
  385.       {
  386.         pCrtCh++;
  387.       }
  388.       else
  389.         state=6;
  390.       break;
  391.     case 6: //CT_INT
  392.       ct_int=strtol(pStartCh,NULL,0);
  393.       tk=addTk(CT_INT);
  394.       tk->i=ct_int;
  395.       return CT_INT;
  396.     case 8:
  397.       if(ch>='0'&&ch<='9')
  398.       {
  399.         pCrtCh++;
  400.         state=9;
  401.       }
  402.       else
  403.         tkerr(addTk(END),"after a point should be a digit");
  404.       break;
  405.     case 9:
  406.       if(ch=='e'||ch=='E')
  407.       {
  408.         pCrtCh++;
  409.         state=10;
  410.       }
  411.       else if(ch>='0'&&ch<='9')
  412.       {
  413.         pCrtCh++;
  414.       }
  415.       else state=13;
  416.       break;
  417.     case 10:
  418.       if(ch=='+'||ch=='-')
  419.       {
  420.         pCrtCh++;
  421.         state=11;
  422.       }
  423.       else
  424.         state=11;
  425.       break;
  426.     case 11:
  427.       if(ch>='0'&&ch<='9')
  428.       {
  429.         pCrtCh++;
  430.         state=12;
  431.       }
  432.       else
  433.         tkerr(addTk(END),"after + or - should come a digit");
  434.       break;   
  435.     case 12:
  436.       if(ch>='0'&&ch<='9')
  437.       {
  438.         pCrtCh++;
  439.       }
  440.       else
  441.         state=13;
  442.       break;
  443.     case 13:
  444.       ct_real=strtod(pStartCh,NULL);
  445.       tk=addTk(CT_REAL);
  446.       tk->r=ct_real;
  447.       return CT_REAL;  
  448.     case 14:
  449.       if(ch=='\\')
  450.       {
  451.         pCrtCh++;
  452.         state=15;
  453.       }
  454.       else if(ch!='\'')
  455.       {
  456.         ct_char=ch;
  457.         pCrtCh++;
  458.         state=16;
  459.       }
  460.       else                    
  461.         tkerr(addTk(END),"not a quote");
  462.       break;
  463.      
  464.     case 15:
  465.       if(strchr("abfnrtv'?\"\\0", ch))
  466.       {
  467.         ct_char=escCode(ch);
  468.         pCrtCh++;
  469.         state=17;
  470.       }
  471.       else
  472.         tkerr(addTk(END),"should come a character to be escaped");
  473.       break;
  474.     case 16:
  475.       if(ch=='\'')
  476.       {
  477.         pCrtCh++;
  478.         state=17;
  479.       }
  480.       else
  481.         tkerr(addTk(END),"not a quote");
  482.       break;
  483.      
  484.     case 17:
  485.       tk=addTk(CT_CHAR);
  486.       tk->i=ct_char;
  487.       return CT_CHAR;
  488.      
  489.     case 18:
  490.       if(ch=='\\')
  491.       {
  492.         pCrtCh++;
  493.         state=19;
  494.       }
  495.       else if(ch!='"' || ch!='\\')
  496.       {
  497.         pCrtCh++;
  498.         state=20;
  499.       }
  500.       else if (ch=='\"')
  501.       {
  502.         pCrtCh++;
  503.         state=21;
  504.       }
  505.       break;
  506.     case 19:
  507.       if(strchr("abfnrtv'?\"\\0", ch))
  508.       {
  509.         pCrtCh++;
  510.         state=20;
  511.       }
  512.       else
  513.         tkerr(addTk(END),"should come a character to be escaped");
  514.     case 20:
  515.       if(ch=='\"')
  516.       {
  517.         pCrtCh++;
  518.         state=21;
  519.       }
  520.       else
  521.         state=18;
  522.       break;
  523.      
  524.     case 21:
  525.       ct_string=createString(pStartCh+1,pCrtCh-1);
  526.       while((p=strchr(ct_string,'\\'))!=NULL)
  527.       {
  528.         //p=strchr(ct_string,'\\');
  529.         //puts(p);
  530.         memmove(p,p+1,strlen(p));
  531.         *p=escCode(*p);
  532.       }
  533.       tk=addTk(CT_STRING);
  534.       tk->text=ct_string;
  535.       return CT_STRING;
  536.      
  537.     case 22:
  538.       if(isalnum(ch)||ch=='_') pCrtCh++;
  539.       else state=23;
  540.       break;
  541.      
  542.     case 23:
  543.       nCh=pCrtCh-pStartCh;//the id length
  544.       //keywords tests
  545.       if(nCh==5&&!memcmp(pStartCh,"break",5))
  546.         tk=addTk(BREAK);
  547.       else if(nCh==4&&!memcmp(pStartCh,"char",4))
  548.         tk=addTk(CHAR);
  549.       else if(nCh==6&&!memcmp(pStartCh,"double",6))
  550.         tk=addTk(DOUBLE);
  551.       else if(nCh==4&&!memcmp(pStartCh,"else",4))
  552.         tk=addTk(ELSE);
  553.       else if(nCh==3&&!memcmp(pStartCh,"for",3))
  554.         tk=addTk(FOR);
  555.       else if(nCh==2&&!memcmp(pStartCh,"if",2))
  556.         tk=addTk(IF);
  557.       else if(nCh==3&&!memcmp(pStartCh,"int",3))
  558.         tk=addTk(INT);
  559.       else if(nCh==6&&!memcmp(pStartCh,"return",6))
  560.         tk=addTk(RETURN);
  561.       else if(nCh==6&&!memcmp(pStartCh,"struct",6))
  562.         tk=addTk(STRUCT);
  563.       else if(nCh==4&&!memcmp(pStartCh,"void",4))
  564.         tk=addTk(VOID);
  565.       else if(nCh==5&&!memcmp(pStartCh,"while",5))
  566.         tk=addTk(WHILE);
  567.       else //if no keyword, then it is an ID
  568.       {
  569.         tk=addTk(ID);
  570.         tk->text=createString(pStartCh,pCrtCh);
  571.       }
  572.       return tk->code;
  573.      
  574.     case 24:
  575.       if(ch=='*')
  576.       {
  577.         pCrtCh++;
  578.         state=27;
  579.       }
  580.       else if(ch=='/')
  581.       {
  582.         pCrtCh++;
  583.         state=25;
  584.       }
  585.       else
  586.       {
  587.         addTk(DIV);
  588.         return DIV;
  589.       }
  590.       break;
  591.     case 25: //LINECOMMENT
  592.       if(ch=='\r'||ch=='\0')
  593.       {
  594.         pCrtCh++;
  595.         state=0;
  596.       }
  597.       else if(ch=='\n')
  598.       {
  599.         line++;
  600.         pCrtCh++;
  601.         state=0;
  602.       }
  603.       else
  604.       {
  605.         pCrtCh++;                    
  606.       }
  607.       break;
  608.     case 27:
  609.       if(ch=='*')
  610.       {
  611.         pCrtCh++;
  612.         state=28;
  613.       }
  614.       else pCrtCh++;
  615.       break;
  616.      
  617.     case 28:
  618.       if(ch=='/')
  619.       {
  620.         pCrtCh++;
  621.         state=0; //COMMENT
  622.       }
  623.       else if(ch=='*')
  624.       {
  625.         pCrtCh++;
  626.         state=28;
  627.       }
  628.       else
  629.       {
  630.         pCrtCh++;
  631.         state=27;
  632.       }
  633.       break;
  634.      
  635.     case 43:
  636.       if(ch=='&')
  637.       {
  638.         pCrtCh++;
  639.         addTk(AND);
  640.       }
  641.       else
  642.         tkerr(addTk(END),"should come a &");
  643.       break;
  644.     case 45:
  645.       if(ch=='|')
  646.       {
  647.         pCrtCh++;
  648.         addTk(OR);
  649.       }
  650.       else
  651.         tkerr(addTk(END),"should come a |");
  652.       break;
  653.     case 47:
  654.       if(ch=='=')
  655.       {
  656.         pCrtCh++;
  657.         addTk(NOTEQ);
  658.         return NOTEQ;
  659.       }
  660.       else
  661.       {
  662.         addTk(NOT);
  663.         return NOT;
  664.       }
  665.      
  666.      
  667.     case 48:
  668.       if(ch=='=')
  669.       {
  670.         pCrtCh++;
  671.         addTk(EQUAL);
  672.         return EQUAL;
  673.       }
  674.       else
  675.       {
  676.         addTk(ASSIGN);
  677.         return ASSIGN;
  678.       }
  679.      
  680.     case 51:
  681.       if(ch=='=')
  682.       {
  683.         pCrtCh++;
  684.         addTk(LESSEQ);
  685.         return LESSEQ;
  686.       }
  687.       else
  688.       {
  689.         addTk(LESS);
  690.         return LESS;
  691.       }
  692.     case 54:
  693.       if(ch=='=')
  694.       {
  695.         pCrtCh++;
  696.         addTk(GREATEREQ);
  697.         return GREATEREQ;
  698.       }
  699.       else
  700.       {
  701.         addTk(GREATER);
  702.         return GREATER;
  703.       }
  704.     }  
  705.    
  706.   }
  707. }
  708.  
  709. void getTokens()
  710. {
  711.   do
  712.   {
  713.     getNextToken();
  714.   }while(*pCrtCh);
  715. }
  716.  
  717. int main()
  718. {
  719.   FILE *file=fopen("8.c","r+");
  720.   if(file==NULL)
  721.   {
  722.     printf("The file could not be opened.\n");
  723.     exit(1);
  724.   }
  725.   char *input;
  726.   int size;
  727.  
  728.   fseek(file, 0, SEEK_END); // seek to end of file
  729.   size = ftell(file); // get current file pointer
  730.   fseek(file, 0, SEEK_SET); // seek back to beginning of file
  731.  
  732.   input=(char *)malloc((size+1)*sizeof(char));
  733.   fread(input,sizeof(char),size,file);
  734.   input[size]='\0';
  735.   pCrtCh=input;
  736.   getTokens();
  737.   printTokens();
  738.   fclose(file);
  739.   return 0;
  740. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement