lexer.ll 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. %{
  2. #include <config.h>
  3. #include <math.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <iostream>
  7. #include "tree.hpp"
  8. #include "parser.hpp"
  9. #include "globals.hpp"
  10. // there seems to be a bug in flex that adds some ECHO directives
  11. // in some rules, we don't need debug output
  12. #define ECHO {}
  13. #define YY_NEVER_INTERACTIVE 1
  14. #define YY_DECL int yylex(YYSTYPE* yylval)
  15. #define YY_INPUT(buf, result, max_size) \
  16. { \
  17. input->read(buf, max_size); \
  18. result = input->gcount(); \
  19. }
  20. std::string last_docucomment;
  21. std::string original_file;
  22. std::string current_file;
  23. std::string comm;
  24. int offset_lnum;
  25. int getCurrentLine()
  26. {
  27. return yylineno - offset_lnum;
  28. }
  29. %}
  30. %option noyywrap
  31. %option yylineno
  32. /* %option never-interactive */
  33. %x comment
  34. %%
  35. #[ \t]+[0-9]+[ \t]+.* {
  36. int lnum;
  37. char file[1024];
  38. if(sscanf(yytext, "# %d \"%1023[^\"]\"", &lnum, file) == 2) {
  39. offset_lnum = yylineno - lnum + 1;
  40. current_file = file;
  41. if(original_file == "")
  42. original_file = file;
  43. } else {
  44. std::cerr << "Warning: Parse error in processor info directive.\n";
  45. }
  46. }
  47. #.* /* ignore preprocessor directives */
  48. [[:space:]]+ /* eat spaces */
  49. "/*" { BEGIN(comment); comm = ""; }
  50. <comment>[^*\n]* { comm += yytext; }
  51. <comment>"*"+[^*/]* { comm += yytext; }
  52. <comment>"*/" {
  53. BEGIN(INITIAL);
  54. if(comm[0] == '*') { // It's a docu comment...
  55. last_docucomment = "";
  56. bool linestart = true;
  57. for(size_t i = 1; i < comm.size(); ++i) {
  58. if(linestart && (comm[i] == '*' || isspace(comm[i]))) {
  59. continue;
  60. } else if(comm[i] == '\n') {
  61. linestart = true;
  62. } else {
  63. linestart = false;
  64. }
  65. last_docucomment += comm[i];
  66. }
  67. }
  68. }
  69. \/\/[^\n]*\n {
  70. if(yytext[2] == '/') { // it's a docu comment...
  71. last_docucomment = std::string(yytext+3, strlen(yytext)-4);
  72. }
  73. }
  74. class { return T_CLASS; }
  75. struct { return T_STRUCT; }
  76. static { return T_STATIC; }
  77. virtual { }
  78. final { }
  79. const { return T_CONST; }
  80. unsigned { return T_UNSIGNED; }
  81. signed { return T_SIGNED; }
  82. void { return T_VOID; }
  83. bool { return T_BOOL; }
  84. char { return T_CHAR; }
  85. short { return T_SHORT; }
  86. int { return T_INT; }
  87. long { return T_LONG; }
  88. float { return T_FLOAT; }
  89. double { return T_DOUBLE; }
  90. public { return T_PUBLIC; }
  91. protected { return T_PROTECTED; }
  92. private { return T_PRIVATE; }
  93. namespace { return T_NAMESPACE; }
  94. __suspend { return T_SUSPEND; }
  95. __custom { return T_CUSTOM; }
  96. [a-zA-Z_][a-zA-Z_0-9]* {
  97. Namespace* ns = search_namespace;
  98. if(ns == 0)
  99. ns = current_namespace;
  100. // is it a type?
  101. yylval->atomic_type = ns->_findType(yytext, search_down);
  102. if(yylval->atomic_type) {
  103. return T_ATOMIC_TYPE;
  104. }
  105. // or a namespace? (hack for now...)
  106. yylval->_namespace = ns->_findNamespace(yytext, search_down);
  107. if(yylval->_namespace) {
  108. return T_NAMESPACEREF;
  109. }
  110. // a new ID
  111. yylval->str = strdup(yytext);
  112. return T_ID;
  113. }
  114. \:\: { return T_DDCOL; }
  115. (0x)?[0-9]+ {
  116. sscanf(yytext, "%i", &(yylval->ival));
  117. return T_INT;
  118. }
  119. [0-9]*\.[0-9]+(e[0-9]+)? {
  120. sscanf(yytext, "%f", &(yylval->fval));
  121. return T_FLOAT;
  122. }
  123. \".*\" {
  124. yylval->str = strdup(yytext);
  125. return T_STRING;
  126. }
  127. . { return yytext[0]; }
  128. %%