parser.y 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. /* =============================================================================
  2. //
  3. // This file is part of the qlow compiler.
  4. //
  5. // Copyright (C) 2014-2015 Nicolas Winkler
  6. //
  7. // This program is free software: you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation, either version 3 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. //
  20. // ===========================================================================*/
  21. %{
  22. #include <string>
  23. #include <vector>
  24. #include <iostream>
  25. #include <cstdio>
  26. #include "Ast.h"
  27. #include "ErrorReporting.h"
  28. using namespace qlow::ast;
  29. extern int qlow_parser_lex();
  30. void yy_pop_state(void);
  31. int qlow_parser_error(const char* msg)
  32. {
  33. //throw msg;
  34. //printf("error happened: %s\n", msg);
  35. // throw msg;
  36. }
  37. std::unique_ptr<std::vector<std::unique_ptr<qlow::ast::AstObject>>> parsedClasses;
  38. const char* qlow_parser_filename = "";
  39. # define YYLLOC_DEFAULT(Cur, Rhs, N) \
  40. do \
  41. if (N) \
  42. { \
  43. (Cur).first_line = YYRHSLOC(Rhs, 1).first_line; \
  44. (Cur).first_column = YYRHSLOC(Rhs, 1).first_column; \
  45. (Cur).last_line = YYRHSLOC(Rhs, N).last_line; \
  46. (Cur).last_column = YYRHSLOC(Rhs, N).last_column; \
  47. (Cur).filename = YYRHSLOC(Rhs, 1).filename; \
  48. } \
  49. else \
  50. { \
  51. (Cur).first_line = (Cur).last_line = \
  52. YYRHSLOC(Rhs, 0).last_line; \
  53. (Cur).first_column = (Cur).last_column = \
  54. YYRHSLOC(Rhs, 0).last_column; \
  55. } \
  56. while (0)
  57. %}
  58. %define api.prefix {qlow_parser_}
  59. %define parse.error verbose
  60. // %define parse.lac full
  61. %locations
  62. %code requires {
  63. #include "Ast.h"
  64. typedef qlow::CodePosition QLOW_PARSER_LTYPE;
  65. #define QLOW_PARSER_LTYPE_IS_DECLARED
  66. }
  67. %initial-action
  68. {
  69. @$.filename = qlow_parser_filename;
  70. };
  71. //%define api.location.type {qlow::CodePosition}
  72. %union {
  73. std::vector<std::unique_ptr<qlow::ast::AstObject>>* topLevel;
  74. qlow::ast::Class* classDefinition;
  75. qlow::ast::Type* type;
  76. qlow::ast::ClassType* classType;
  77. qlow::ast::ArrayType* arrayType;
  78. qlow::ast::FeatureDeclaration* featureDeclaration;
  79. std::vector<std::unique_ptr<qlow::ast::FeatureDeclaration>>* featureList;
  80. std::vector<std::unique_ptr<qlow::ast::ArgumentDeclaration>>* argumentList;
  81. std::vector<std::unique_ptr<qlow::ast::Statement>>* statements;
  82. std::vector<std::unique_ptr<qlow::ast::Expression>>* expressionList;
  83. qlow::ast::ArgumentDeclaration* argumentDeclaration;
  84. qlow::ast::DoEndBlock* doEndBlock;
  85. qlow::ast::IfElseBlock* ifElseBlock;
  86. qlow::ast::WhileBlock* whileBlock;
  87. qlow::ast::Statement* statement;
  88. qlow::ast::Expression* expression;
  89. qlow::ast::Operation::Operator op;
  90. qlow::ast::FieldDeclaration* fieldDeclaration;
  91. qlow::ast::MethodDefinition* methodDefinition;
  92. qlow::ast::FeatureCall* featureCall;
  93. qlow::ast::AssignmentStatement* assignmentStatement;
  94. qlow::ast::ReturnStatement* returnStatement;
  95. qlow::ast::LocalVariableStatement* localVariableStatement;
  96. qlow::ast::UnaryOperation* unaryOperation;
  97. qlow::ast::BinaryOperation* binaryOperation;
  98. qlow::ast::NewArrayExpression* newArrayExpression;
  99. const char* cString;
  100. std::string* string;
  101. int token;
  102. }
  103. %token <string> IDENTIFIER
  104. %token <string> INT_LITERAL
  105. %token <token> TRUE FALSE
  106. %token <token> CLASS DO END IF ELSE WHILE RETURN NEW EXTERN
  107. %token <token> NEW_LINE
  108. %token <token> SEMICOLON COLON COMMA DOT ASSIGN EQUALS NOT_EQUALS
  109. %token <token> ROUND_LEFT ROUND_RIGHT SQUARE_LEFT SQUARE_RIGHT
  110. %token <string> UNEXPECTED_SYMBOL
  111. %type <topLevel> topLevel
  112. %type <classDefinition> classDefinition
  113. %type <type> type
  114. %type <featureDeclaration> featureDeclaration
  115. %type <fieldDeclaration> fieldDeclaration
  116. %type <methodDefinition> methodDefinition
  117. %type <methodDefinition> externMethodDeclaration
  118. %type <featureList> featureList
  119. %type <argumentList> argumentList
  120. %type <statements> statements
  121. %type <expressionList> expressionList
  122. %type <argumentDeclaration> argumentDeclaration
  123. %type <doEndBlock> doEndBlock
  124. %type <ifElseBlock> ifElseBlock
  125. %type <whileBlock> whileBlock
  126. %type <statement> statement
  127. %type <expression> expression operationExpression paranthesesExpression
  128. %type <op> operator
  129. %type <featureCall> featureCall
  130. %type <assignmentStatement> assignmentStatement
  131. %type <returnStatement> returnStatement
  132. %type <localVariableStatement> localVariableStatement
  133. %type <unaryOperation> unaryOperation
  134. %type <binaryOperation> binaryOperation
  135. %type <newArrayExpression> newArrayExpression
  136. %destructor { } <token>
  137. %destructor { } <op>
  138. %destructor { } <topLevel> // don't delete everything ;)
  139. %destructor { if ($$) delete $$; } <*>
  140. %left DOT
  141. %left ASTERISK SLASH
  142. %left PLUS MINUS
  143. %left EQUALS
  144. %left NOT
  145. %left AND
  146. %left OR XOR
  147. %start topLevel
  148. %%
  149. /* list of class definitions */
  150. topLevel:
  151. /* empty */ {
  152. parsedClasses = std::make_unique<std::vector<std::unique_ptr<qlow::ast::AstObject>>>();
  153. }
  154. |
  155. topLevel classDefinition {
  156. parsedClasses->push_back(std::move(std::unique_ptr<qlow::ast::Class>($2)));
  157. $2 = nullptr;
  158. }
  159. |
  160. topLevel methodDefinition {
  161. parsedClasses->push_back(std::move(std::unique_ptr<qlow::ast::MethodDefinition>($2)));
  162. $2 = nullptr;
  163. }
  164. |
  165. topLevel externMethodDeclaration {
  166. parsedClasses->push_back(std::move(std::unique_ptr<qlow::ast::MethodDefinition>($2)));
  167. $2 = nullptr;
  168. }
  169. |
  170. topLevel error methodDefinition {
  171. reportError(qlow::SyntaxError(@2));
  172. yyerrok;
  173. parsedClasses->push_back(std::move(std::unique_ptr<qlow::ast::MethodDefinition>($3)));
  174. $3 = nullptr;
  175. }
  176. |
  177. topLevel error classDefinition {
  178. reportError(qlow::SyntaxError(@2));
  179. yyerrok;
  180. parsedClasses->push_back(std::move(std::unique_ptr<qlow::ast::Class>($3)));
  181. $3 = nullptr;
  182. };
  183. classDefinition:
  184. CLASS IDENTIFIER featureList END {
  185. $$ = new Class(*$2, *$3, @$);
  186. delete $2; delete $3; $2 = 0; $3 = 0;
  187. }
  188. |
  189. CLASS error END {
  190. reportError(qlow::SyntaxError(@2));
  191. yyerrok;
  192. $$ = nullptr;
  193. };
  194. type:
  195. IDENTIFIER {
  196. $$ = new qlow::ast::ClassType(std::move(*$1), @$);
  197. delete $1; $1 = nullptr;
  198. }
  199. |
  200. SQUARE_LEFT type SQUARE_RIGHT {
  201. $$ = new qlow::ast::ArrayType(std::unique_ptr<qlow::ast::Type>($2), @$);
  202. }
  203. |
  204. SQUARE_LEFT error SQUARE_RIGHT {
  205. reportError(qlow::SyntaxError("invalid type", @2));
  206. };
  207. featureList:
  208. /* empty */ {
  209. $$ = new std::vector<std::unique_ptr<FeatureDeclaration>>();
  210. }
  211. |
  212. featureList featureDeclaration {
  213. $$ = $1;
  214. $$->push_back(std::move(std::unique_ptr<FeatureDeclaration>($2)));
  215. $2 = nullptr;
  216. }
  217. |
  218. featureList error featureDeclaration {
  219. $$ = $1;
  220. yyerrok;
  221. reportError(qlow::SyntaxError(@2));
  222. $$->push_back(std::move(std::unique_ptr<FeatureDeclaration>($3)));
  223. $3 = nullptr;
  224. };
  225. featureDeclaration:
  226. fieldDeclaration {
  227. $$ = $1;
  228. }
  229. |
  230. methodDefinition {
  231. $$ = $1;
  232. };
  233. fieldDeclaration:
  234. IDENTIFIER COLON type {
  235. $$ = new FieldDeclaration(std::unique_ptr<qlow::ast::Type>($3), std::move(*$1), @$);
  236. delete $1; $1 = nullptr;
  237. };
  238. externMethodDeclaration:
  239. EXTERN IDENTIFIER COLON type {
  240. $$ = new MethodDefinition(std::unique_ptr<qlow::ast::Type>($4), *$2, @$);
  241. delete $2; $2 = nullptr;
  242. }
  243. |
  244. EXTERN IDENTIFIER {
  245. $$ = new MethodDefinition(nullptr, *$2, @$);
  246. delete $2; $2 = nullptr;
  247. }
  248. |
  249. EXTERN IDENTIFIER ROUND_LEFT argumentList ROUND_RIGHT {
  250. $$ = new MethodDefinition(nullptr, *$2, std::move(*$4), @$);
  251. delete $2; delete $4; $2 = nullptr; $4 = nullptr;
  252. }
  253. |
  254. EXTERN IDENTIFIER ROUND_LEFT argumentList ROUND_RIGHT COLON type {
  255. $$ = new MethodDefinition(std::unique_ptr<qlow::ast::Type>($7),
  256. *$2, std::move(*$4), @$);
  257. delete $2; delete $4; $2 = nullptr; $4 = nullptr;
  258. };
  259. methodDefinition:
  260. IDENTIFIER COLON type doEndBlock {
  261. $$ = new MethodDefinition(std::unique_ptr<qlow::ast::Type>($3), *$1, std::unique_ptr<DoEndBlock>($4), @$);
  262. delete $1; $1 = nullptr;
  263. }
  264. |
  265. IDENTIFIER doEndBlock {
  266. $$ = new MethodDefinition(nullptr, *$1, std::move(std::unique_ptr<DoEndBlock>($2)), @$);
  267. delete $1; $1 = nullptr;
  268. }
  269. |
  270. IDENTIFIER
  271. ROUND_LEFT argumentList ROUND_RIGHT COLON type doEndBlock {
  272. $$ = new MethodDefinition(std::unique_ptr<qlow::ast::Type>($6),
  273. *$1, std::move(*$3),
  274. std::unique_ptr<DoEndBlock>($7),
  275. @$);
  276. delete $1; delete $3; $1 = nullptr; $3 = nullptr;
  277. }
  278. |
  279. IDENTIFIER ROUND_LEFT argumentList ROUND_RIGHT doEndBlock {
  280. $$ = new MethodDefinition(nullptr, *$1, std::move(*$3), std::move(std::unique_ptr<DoEndBlock>($5)), @$);
  281. delete $1; delete $3; $1 = nullptr; $3 = nullptr;
  282. };
  283. argumentList:
  284. argumentDeclaration {
  285. $$ = new std::vector<std::unique_ptr<ArgumentDeclaration>>();
  286. $$->push_back(std::unique_ptr<ArgumentDeclaration>($1));
  287. }
  288. |
  289. argumentList COMMA argumentDeclaration {
  290. $$ = $1;
  291. $$->push_back(std::unique_ptr<ArgumentDeclaration>($3));
  292. };
  293. argumentDeclaration:
  294. IDENTIFIER COLON type {
  295. $$ = new ArgumentDeclaration(std::unique_ptr<qlow::ast::Type>($3), std::move(*$1), @$);
  296. delete $1; $1 = nullptr; $3 = nullptr;
  297. };
  298. doEndBlock:
  299. DO statements END {
  300. $$ = new DoEndBlock(std::move(*$2), @$);
  301. delete $2; $2 = nullptr;
  302. };
  303. ifElseBlock:
  304. IF expression doEndBlock {
  305. $$ = new IfElseBlock(std::unique_ptr<Expression>($2),
  306. std::unique_ptr<DoEndBlock>($3),
  307. std::make_unique<DoEndBlock>(qlow::OwningList<qlow::ast::Statement>{}, @3), @$);
  308. $2 = nullptr; $3 = nullptr;
  309. }
  310. |
  311. IF expression DO statements ELSE statements END {
  312. $$ = new IfElseBlock(std::unique_ptr<Expression>($2),
  313. std::make_unique<DoEndBlock>(std::move(*$4), @4),
  314. std::make_unique<DoEndBlock>(std::move(*$6), @6), @$);
  315. $2 = nullptr;
  316. delete $4;
  317. delete $6;
  318. };
  319. whileBlock:
  320. WHILE expression doEndBlock {
  321. $$ = new WhileBlock(std::unique_ptr<Expression>($2),
  322. std::unique_ptr<DoEndBlock>($3), @$);
  323. $2 = nullptr; $3 = nullptr;
  324. };
  325. statements:
  326. pnl {
  327. $$ = new std::vector<std::unique_ptr<Statement>>();
  328. }
  329. |
  330. statements statement {
  331. $$ = $1;
  332. // statements can be null on errors
  333. if ($1 != nullptr)
  334. $$->push_back(std::unique_ptr<Statement>($2));
  335. };
  336. /*!
  337. * hacky way to allow for multiple empty lines between statements
  338. */
  339. pnl:
  340. /* empty */ {
  341. }
  342. |
  343. pnl NEW_LINE {
  344. }
  345. ;
  346. statement:
  347. featureCall statementEnd {
  348. $$ = $1;
  349. }
  350. |
  351. assignmentStatement statementEnd {
  352. $$ = $1;
  353. }
  354. |
  355. returnStatement statementEnd {
  356. $$ = $1;
  357. }
  358. |
  359. localVariableStatement statementEnd {
  360. $$ = $1;
  361. }
  362. |
  363. ifElseBlock statementEnd {
  364. $$ = $1;
  365. }
  366. |
  367. whileBlock statementEnd {
  368. $$ = $1;
  369. }
  370. |
  371. error statementEnd {
  372. $$ = nullptr;
  373. //printf("error happened here (%s): %d\n", qlow_parser_filename, @1.first_line);
  374. //throw qlow::SyntaxError(@1);
  375. reportError(qlow::SyntaxError(@1));
  376. printf("unexpected token: %d\n", $<token>1);
  377. }
  378. ;
  379. statementEnd:
  380. SEMICOLON pnl {}
  381. |
  382. NEW_LINE pnl {}
  383. ;
  384. featureCall:
  385. IDENTIFIER {
  386. $$ = new FeatureCall(nullptr, *$1, @$);
  387. delete $1; $1 = 0;
  388. }
  389. |
  390. IDENTIFIER ROUND_LEFT expressionList ROUND_RIGHT {
  391. $$ = new FeatureCall(nullptr, *$1, std::move(*$3), @$);
  392. delete $1; delete $3; $1 = 0; $3 = 0;
  393. }
  394. |
  395. expression DOT IDENTIFIER {
  396. $$ = new FeatureCall(std::unique_ptr<Expression>($1), *$3, @$);
  397. delete $3; $3 = 0;
  398. }
  399. |
  400. expression DOT IDENTIFIER ROUND_LEFT expressionList ROUND_RIGHT {
  401. $$ = new FeatureCall(std::unique_ptr<Expression>($1), *$3,
  402. std::move(*$5), @$);
  403. delete $3; $3 = 0; delete $5; $5 = 0;
  404. };
  405. /* list of effective arguments */
  406. expressionList:
  407. expression {
  408. $$ = new std::vector<std::unique_ptr<Expression>>();
  409. $$->push_back(std::unique_ptr<Expression>($1));
  410. }
  411. |
  412. expressionList COMMA expression {
  413. $$ = $1;
  414. $$->push_back(std::unique_ptr<Expression>($3));
  415. };
  416. expression:
  417. featureCall {
  418. $$ = $1;
  419. }
  420. |
  421. operationExpression {
  422. $$ = $1;
  423. }
  424. |
  425. paranthesesExpression {
  426. $$ = $1;
  427. }
  428. |
  429. newArrayExpression {
  430. $$ = $1;
  431. }
  432. |
  433. INT_LITERAL {
  434. $$ = new IntConst(std::move(*$1), @$);
  435. delete $1;
  436. };/*
  437. |
  438. error {
  439. $$ = nullptr;
  440. reportError(qlow::SyntaxError(@1));
  441. //throw qlow::SyntaxError(@1);
  442. }
  443. ;
  444. */
  445. operationExpression:
  446. binaryOperation {
  447. $$ = $1;
  448. }
  449. |
  450. unaryOperation {
  451. $$ = $1;
  452. };
  453. binaryOperation:
  454. expression operator expression {
  455. $$ = new BinaryOperation(std::unique_ptr<Expression>($1),
  456. std::unique_ptr<Expression>($3), $2, @$);
  457. };
  458. unaryOperation:
  459. expression operator {
  460. $$ = new UnaryOperation(std::unique_ptr<Expression>($1),
  461. UnaryOperation::SUFFIX, $2, @$);
  462. }
  463. |
  464. operator expression {
  465. $$ = new UnaryOperation(std::unique_ptr<Expression>($2),
  466. UnaryOperation::PREFIX, $1, @$);
  467. };
  468. operator:
  469. PLUS { $$ = qlow::ast::Operation::Operator::PLUS; }
  470. |
  471. MINUS { $$ = qlow::ast::Operation::Operator::MINUS; }
  472. |
  473. ASTERISK { $$ = qlow::ast::Operation::Operator::ASTERISK; }
  474. |
  475. SLASH { $$ = qlow::ast::Operation::Operator::SLASH; }
  476. |
  477. EQUALS { $$ = qlow::ast::Operation::Operator::EQUALS; }
  478. |
  479. NOT_EQUALS { $$ = qlow::ast::Operation::Operator::NOT_EQUALS; }
  480. |
  481. AND { $$ = qlow::ast::Operation::Operator::AND; }
  482. |
  483. OR { $$ = qlow::ast::Operation::Operator::OR; }
  484. |
  485. XOR { $$ = qlow::ast::Operation::Operator::XOR; };
  486. paranthesesExpression:
  487. ROUND_LEFT expression ROUND_RIGHT {
  488. $$ = $2;
  489. };
  490. newArrayExpression:
  491. NEW SQUARE_LEFT type SEMICOLON expression SQUARE_RIGHT {
  492. };
  493. assignmentStatement:
  494. expression ASSIGN expression {
  495. $$ = new AssignmentStatement(std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3), @$);
  496. };
  497. returnStatement:
  498. RETURN expression {
  499. $$ = new ReturnStatement(std::unique_ptr<Expression>($2), @$);
  500. };
  501. localVariableStatement:
  502. IDENTIFIER COLON type {
  503. $$ = new LocalVariableStatement(std::move(*$1), std::unique_ptr<qlow::ast::Type>($3), @$);
  504. delete $1; $3 = nullptr; $1 = nullptr;
  505. };
  506. %%