tars.l 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. %option outfile="tars.lex.cpp"
  17. %option yylineno
  18. %{
  19. #include <map>
  20. #include <string>
  21. #include <sstream>
  22. #include <cassert>
  23. #include <errno.h>
  24. #include <math.h>
  25. #define YYSTYPE GrammarBasePtr
  26. #include "parse.h"
  27. #include "tars.tab.hpp"
  28. using namespace std;
  29. extern "C"
  30. {
  31. int yywrap()
  32. {
  33. return 1;
  34. }
  35. }
  36. struct include_file_state
  37. {
  38. YY_BUFFER_STATE state;
  39. string file;
  40. };
  41. #define MAX_INCLUDE_DEPTH 200
  42. include_file_state include_file_stack[MAX_INCLUDE_DEPTH];
  43. int include_file_stack_ptr = 0;
  44. int isatty(int)
  45. {
  46. return 0;
  47. }
  48. %}
  49. tars_identifiers [[:alpha:]_][[:alnum:]_]*
  50. tars_anychar .
  51. tars_const_int (\+|-)?((0[0-7]+)|(0x[[:xdigit:]]+)|([[:digit:]]+))
  52. tars_float_literal (\+|-)?(([[:digit:]]*\.[[:digit:]]+)|([[:digit:]]+\.))
  53. tars_float_exp (e|E)(\+|-)?[[:digit:]]+
  54. tars_const_float (({tars_float_literal}{tars_float_exp}?)|((\+|-)?[[:digit:]]+{tars_float_exp}))[fF]?
  55. %x INCL
  56. %%
  57. "#include"[ \t]* { BEGIN(INCL); }
  58. <INCL>"\"".*"\"" {
  59. if ( include_file_stack_ptr >= MAX_INCLUDE_DEPTH )
  60. {
  61. g_parse->error("Includes nested too deeply" );
  62. }
  63. string file;
  64. bool b = g_parse->getFilePath( yytext, file);
  65. g_parse->currentContextPtr()->addInclude(file);
  66. //该文件没解析过
  67. if(b)
  68. {
  69. include_file_stack[include_file_stack_ptr].state = YY_CURRENT_BUFFER;
  70. include_file_stack[include_file_stack_ptr].file = file;
  71. include_file_stack_ptr++;
  72. yyin = fopen( file.c_str(), "r" );
  73. if ( !yyin )
  74. {
  75. g_parse->error("can't open file:" + file);
  76. }
  77. yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
  78. g_parse->pushFile(file);
  79. }
  80. BEGIN(INITIAL);
  81. }
  82. <<EOF>> {
  83. --include_file_stack_ptr;
  84. if ( include_file_stack_ptr < 0 )
  85. {
  86. include_file_stack_ptr = 0;
  87. yyterminate();
  88. }
  89. else
  90. {
  91. yy_delete_buffer( YY_CURRENT_BUFFER );
  92. fclose(yyin);
  93. yy_switch_to_buffer(include_file_stack[include_file_stack_ptr].state );
  94. g_parse->popFile();
  95. }
  96. }
  97. "::" {
  98. return TARS_SCOPE_DELIMITER;
  99. }
  100. "//" {
  101. // C++ comment
  102. bool e = false;
  103. while(!e)
  104. {
  105. int input = yyinput();
  106. if(input == '\n')
  107. {
  108. g_parse->nextLine();
  109. }
  110. if(input == '\n' || input == EOF)
  111. {
  112. e = true;
  113. }
  114. }
  115. }
  116. "/*" {
  117. // C comment
  118. bool e = false;
  119. string comment = yytext + 2;
  120. while(!e)
  121. {
  122. int input = yyinput();
  123. switch(input)
  124. {
  125. case '*':
  126. {
  127. int nextInput = yyinput();
  128. if(nextInput == '/')
  129. {
  130. e = true;
  131. }
  132. else
  133. {
  134. comment += static_cast<char>(input);
  135. unput(nextInput);
  136. }
  137. break;
  138. }
  139. case '\n':
  140. {
  141. comment += static_cast<char>(input);
  142. g_parse->nextLine();
  143. break;
  144. }
  145. case EOF:
  146. {
  147. g_parse->error("EOF in comment");
  148. e = true;
  149. break;
  150. }
  151. default:
  152. {
  153. comment += static_cast<char>(input);
  154. break;
  155. }
  156. }
  157. }
  158. if(comment[0] == '*')
  159. {
  160. //todo
  161. }
  162. }
  163. {tars_identifiers} {
  164. StringGrammarPtr ident = new StringGrammar;
  165. ident->v = yytext;
  166. yylval = ident;
  167. return g_parse->checkKeyword(ident->v);
  168. }
  169. {tars_identifiers}[[:space:]]*"(" {
  170. StringGrammarPtr ident = new StringGrammar;
  171. ident->v = yytext;
  172. ident->v.erase(ident->v.find_first_of(" \t\v\n\r\f("));
  173. yylval = ident;
  174. return TARS_OP;
  175. }
  176. \" {
  177. StringGrammarPtr str = new StringGrammar;
  178. bool e = false;
  179. while(!e)
  180. {
  181. int input = yyinput();
  182. switch(input)
  183. {
  184. case '"':
  185. {
  186. e = true;
  187. break;
  188. }
  189. case '\n':
  190. {
  191. g_parse->error("newline in string");
  192. break;
  193. }
  194. case EOF:
  195. {
  196. g_parse->error("EOF in string");
  197. break;
  198. }
  199. case '\\':
  200. {
  201. static string specialChars = "nrtvfab?";
  202. static string octalChars = "0123";
  203. char nextInput = static_cast<char>(yyinput());
  204. if(nextInput == '\\' || nextInput == '"' || nextInput == '\'')
  205. {
  206. str->v += nextInput;
  207. }
  208. else if(specialChars.find(nextInput) != string::npos)
  209. {
  210. str->v += '\\';
  211. str->v += nextInput;
  212. }
  213. else if(octalChars.find(nextInput) != string::npos)
  214. {
  215. static string octalDigits = "01234567";
  216. unsigned short us = nextInput - '0';
  217. if(octalDigits.find_first_of(nextInput = static_cast<char>(yyinput())) != string::npos)
  218. {
  219. us = us * 8 + nextInput - '0';
  220. if(octalDigits.find_first_of(nextInput = static_cast<char>(yyinput())) != string::npos)
  221. {
  222. us = us * 8 + nextInput - '0';
  223. }
  224. else
  225. {
  226. unput(nextInput);
  227. }
  228. }
  229. else
  230. {
  231. unput(nextInput);
  232. }
  233. if(us == 0)
  234. {
  235. g_parse->error("illegal NUL character in string constant");
  236. }
  237. str->v += static_cast<char>(us);
  238. }
  239. else if(nextInput == 'x')
  240. {
  241. long long ull = 0;
  242. while(isxdigit(nextInput = static_cast<char>(yyinput())))
  243. {
  244. ull *= 16;
  245. if(isdigit(nextInput))
  246. {
  247. ull += nextInput - '0';
  248. }
  249. else if(islower(nextInput))
  250. {
  251. ull += nextInput - 'a' + 10;
  252. }
  253. else
  254. {
  255. ull += nextInput - 'A' + 10;
  256. }
  257. }
  258. unput(nextInput);
  259. if(ull == 0)
  260. {
  261. g_parse->error("illegal NUL character in string constant");
  262. }
  263. str->v += static_cast<char>(ull);
  264. }
  265. else
  266. {
  267. str->v += static_cast<char>(input);
  268. }
  269. break;
  270. }
  271. default:
  272. {
  273. str->v += static_cast<char>(input);
  274. break;
  275. }
  276. }
  277. }
  278. yylval = str;
  279. return TARS_STRING_LITERAL;
  280. }
  281. {tars_const_int} {
  282. errno = 0;
  283. IntergerGrammarPtr ptr = new IntergerGrammar;
  284. yylval = ptr;
  285. string value = yytext;
  286. const char* beg = value.c_str();
  287. char* e = 0;
  288. ptr->v = strtoll(beg, &e, 0);
  289. if(!(errno == 0 && beg != e))
  290. {
  291. assert(ptr->v != 0);
  292. string err = "integer constant `";
  293. err += value;
  294. err += "' out of range";
  295. g_parse->error(err);
  296. }
  297. return TARS_CONST_INTEGER;
  298. }
  299. {tars_const_float} {
  300. errno = 0;
  301. FloatGrammarPtr ptr = new FloatGrammar;
  302. yylval = ptr;
  303. string value(yytext);
  304. char lastChar = value[value.size() - 1];
  305. if(lastChar == 'f' || lastChar == 'F')
  306. {
  307. value = value.substr(0, value.size() - 1);
  308. }
  309. ptr->v = strtod(value.c_str(), 0);
  310. if((errno == ERANGE) && (ptr->v == HUGE_VAL || ptr->v == -HUGE_VAL))
  311. {
  312. string err = "float point constant `";
  313. err += value;
  314. err += "' too large (overflow)";
  315. g_parse->error(err);
  316. }
  317. else if(errno == ERANGE && ptr->v == 0)
  318. {
  319. string err = "float point constant `";
  320. err += value;
  321. err += "' too small (underflow)";
  322. g_parse->error(err);
  323. }
  324. return TARS_CONST_FLOAT;
  325. }
  326. [[:space:]] {
  327. if(yytext[0] == '\n')
  328. {
  329. g_parse->nextLine();
  330. }
  331. }
  332. {tars_anychar} {
  333. if(yytext[0] < 32 || yytext[0] > 126)
  334. {
  335. stringstream s;
  336. s << "illegal input character: '\\";
  337. s.width(3);
  338. s.fill('0');
  339. s << oct << static_cast<int>(static_cast<unsigned char>(yytext[0]));
  340. s << "'";
  341. g_parse->error(s.str());
  342. return BAD_CHAR;
  343. }
  344. return yytext[0];
  345. }
  346. %%