MMRivers

p.l

Oct 25th, 2019
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. %{
  2. #include <stdio.h> /* printf() */
  3. #include <string.h> /* strcpy */
  4. #include <stdlib.h> /* atoi(), atof() */
  5. #include "common.h" /* MAX_STR_LEN */
  6. #include "p.tab.h" /* declaration of terminal symbols */
  7.  
  8. int process_token(const char *text, const char *TokenType,
  9.                   const char *TokenVal, const int TokenID);
  10.  
  11. int comm_beg = 0; /* starting line of a comment */
  12. int text_beg = 0; /* starting line of a string */
  13. int yylineno;
  14. %}
  15. alpha [a-zA-Z]
  16. num [0-9]
  17. alphanum [a-zA-Z0-9]
  18. alphanum2 [a-zA-Z0-9_]
  19.  
  20. /* declaraction of additional start conditions */
  21. /* (INITIAL start condition does not need to be declared) */
  22. /* ..................... */
  23. %x ST_STRING_CONST ST_COMMENT_1 ST_COMMENT_2
  24.  
  25. %option yylineno
  26. %%
  27.  
  28.  
  29.  /* removal of multiline comments (*..*) */
  30.  /* using start conditions */
  31.  /* ..................... */
  32. <INITIAL>\(\* { BEGIN ST_COMMENT_1; comm_beg = yylineno;}
  33. <ST_COMMENT_1>\*\) BEGIN INITIAL;
  34. <ST_COMMENT_1>.|\n ;
  35.  
  36.  /* removal of multiline comments {..} */
  37.  /* z using start conditions */
  38.  /* ..................... */
  39. <INITIAL>\{ { BEGIN ST_COMMENT_2; comm_beg = yylineno; }
  40. <ST_COMMENT_2>\} BEGIN INITIAL;
  41. <ST_COMMENT_2>.|\n ;
  42.  
  43.  /* detecting an error: Unexpected closing of comment in the line */
  44.  /* ..................... */
  45.  <INITIAL>\}|(\*\)) printf("Unexpected closing of comment in the line %d\n", yylineno);
  46.  
  47.  /* detecting strings '..' */
  48.  /* using start conditions */
  49. <INITIAL>\' { BEGIN ST_STRING_CONST; yymore(); text_beg = yylineno;}
  50. <ST_STRING_CONST>\' { BEGIN INITIAL; return process_token(yytext, "STRING_CONST", yytext, STRING_CONST);}
  51. <ST_STRING_CONST>. yymore();
  52.  
  53.  /* not using start conditions */
  54.  /* (\'.*\') return process_token(yytext, "STRING_CONST", yytext, STRING_CONST); */
  55.  
  56.  /* detection of directives in form of {$I name.ext} */
  57.  /* (without start conditions) */
  58.  /* ..................... */
  59.  \{$I\ .+\} printf("Parsing include direcive\n");
  60.  
  61.  /* Detection of keywords (case-insensitive)! */
  62.  /* ..................... */
  63. (?i:PROGRAM) return process_token(yytext, "KW_PROGRAM", "", KW_PROGRAM);
  64. (?i:BEGIN) return process_token(yytext, "KW_BEGIN", "", KW_BEGIN);
  65. (?i:END) return process_token(yytext, "KW_END", "", KW_END);
  66. (?i:USES) return process_token(yytext, "KW_USES", "", KW_USES);
  67. (?i:VAR) return process_token(yytext, "KW_VAR", "", KW_VAR);
  68. (?i:CONST) return process_token(yytext, "KW_CONST", "", KW_CONST);
  69. (?i:IF) return process_token(yytext, "KW_IF", "", KW_IF);
  70. (?i:THEN) return process_token(yytext, "KW_THEN", "", KW_THEN);
  71. (?i:CHAR) return process_token(yytext, "KW_CHAR", "", KW_CHAR);
  72. (?i:INTEGER) return process_token(yytext, "KW_INTEGER", "", KW_INTEGER);
  73. (?i:REAL) return process_token(yytext, "KW_REAL", "", KW_REAL);
  74. (?i:FOR) return process_token(yytext, "KW_FOR", "", KW_FOR);
  75. (?i:TO) return process_token(yytext, "KW_TO", "", KW_TO);
  76. (?i:DO) return process_token(yytext, "KW_DO", "", KW_DO);
  77. (?i:FUNCTION) return process_token(yytext, "KW_FUNCTION", "", KW_FUNCTION);
  78. (?i:PROCEDURE) return process_token(yytext, "KW_PROCEDURE", "", KW_PROCEDURE);
  79. (?i:DOWNTO) return process_token(yytext, "KW_DOWNTO", "", KW_DOWNTO);
  80. (?i:ARRAY) return process_token(yytext, "KW_ARRAY", "", KW_ARRAY);
  81. (?i:RECORD) return process_token(yytext, "KW_RECORD", "", KW_RECORD);
  82. (?i:OF) return process_token(yytext, "KW_OF", "", KW_OF);
  83.  
  84.  /* detecting terminal symbols specified with regular expressions */
  85.  /* identifiers */
  86. [A-Za-z_]{alphanum2}*     return process_token(yytext, "IDENT", yytext, IDENT);
  87.  
  88.  /* intergers */
  89. {num}+ return process_token(yytext, "INTEGER_CONST", yytext, INTEGER_CONST);
  90.  /* real numbers */
  91. ({num}*\.{num}+)|({num}+\.) return process_token(yytext, "FLOAT_CONST", yytext, FLOAT_CONST);
  92.  
  93.  /* cutting out whitespace */
  94. [ \n\t] ;
  95.  
  96.  
  97.  /* multicharacter expressions, e.g.: :=, <= */
  98. \:\= return process_token(yytext, "ASSIGN", "", ASSIGN);
  99. \<\= return process_token(yytext, "LE", "", LE);
  100.  
  101.  /* one character operators and punctuation */
  102. [+\-*;,=:.(){}\[\]] return process_token(yytext, yytext, "", *yytext);
  103.  
  104. %%
  105.  
  106. /* Name:    strnncpy
  107.  * Purpose: Copies given number of characters from a stream appending
  108.  *      character with code 0.
  109.  * Parameters:  dst     - (o) string to be copied from;
  110.  *      src     - (i) string to be copied to;
  111.  *      n       - (i) max number of characters to copy.
  112.  * Returns: dst.
  113.  * Remarks: strncpy does not append character 0 to the copied string.
  114.  *      Destination string must have room for additional n+1 character.
  115.  */
  116. char *
  117. strnncpy(char *dst, const char *src, const int n)
  118. {
  119.   if (n > 0) {
  120.     strncpy(dst, src, n);
  121.   }
  122.   dst[n] = '\0';
  123.   return dst;
  124. }/*strnncpy*/
  125.  
  126. /* Name:    process_token
  127.  * Purpose: Print information about detected token and pass it up
  128.  *              with its value if present.
  129.  * Parameters:  text            - (i) matched text;
  130.  *              TokenType       - (i) string representing token name;
  131.  *              TokenVal        - (i) token value if present;
  132.  *              TokenID         - (i) token type identifier declared
  133.  *                                      using %token directive
  134.  *                                      in c.y file single character code
  135.  *                  (in the parser put into single quotes).
  136.  * Returns: Token type identifier (TokenID).
  137.  * Remarks: Info about detected token is printed in 3 columns.
  138.  *      The first one contains matched text, the second - token type,
  139.  *      the third - token value, if it exists.
  140.  */
  141. int process_token(const char *text, const char *TokenType,
  142.                   const char *TokenVal, const int TokenID)
  143. {
  144.   int l;
  145.   printf("%-20.20s%-15s %s\n", text, TokenType, TokenVal);
  146.   switch (TokenID) {
  147.  
  148.   case INTEGER_CONST:
  149.     yylval.i = atoi(TokenVal); break;
  150.  
  151.   case FLOAT_CONST:
  152.     yylval.d = atof(TokenVal); break;
  153.  
  154.   case IDENT:
  155.     strncpy(yylval.s, TokenVal, MAX_STR_LEN); break;
  156.  
  157.   case STRING_CONST:        /* rozpoznany napis zawiera cudzysłowy */
  158.     l = strlen(TokenVal);
  159.     strnncpy(yylval.s, TokenVal+1, l - 2 <= MAX_STR_LEN ? l - 1 : MAX_STR_LEN);
  160.     break;
  161.  
  162.   case CHARACTER_CONST:
  163.     yylval.i = TokenVal[1]; break;
  164.  
  165.   }
  166.   return(TokenID);
  167. }/*process_token*/
  168.  
  169.  
  170. int yywrap( void )
  171. { /* function called at the end of input stream */
  172.  
  173.   /* Checking whether the current start condition YY_START */
  174.     /* is different from INITIAL. If so, */
  175.     /* it means unclosed comment or string - */
  176.     /* print error message.*/
  177.     /* ..................... */
  178.   if (YYSTATE != INITIAL){
  179.     if (comm_beg < text_beg)
  180.       printf("Unclosed string in the line %d", text_beg);
  181.     else printf("Unclosed comment in the line %d", comm_beg);
  182.   }
  183.  
  184.   return( 1 ); /* needed to prevent restart of the analysis */
  185. }
Add Comment
Please, Sign In to add comment