gravity_parser.c 103 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708
  1. //
  2. // gravity_parser.c
  3. // gravity
  4. //
  5. // Created by Marco Bambini on 01/09/14.
  6. // Copyright (c) 2014 CreoLabs. All rights reserved.
  7. //
  8. #include "gravity_symboltable.h"
  9. #include "gravity_optionals.h"
  10. #include "gravity_parser.h"
  11. #include "gravity_macros.h"
  12. #include "gravity_lexer.h"
  13. #include "gravity_token.h"
  14. #include "gravity_utils.h"
  15. #include "gravity_array.h"
  16. #include "gravity_hash.h"
  17. #include "gravity_core.h"
  18. #include "gravity_ast.h"
  19. typedef marray_t(gravity_lexer_t*) lexer_r;
  20. struct gravity_parser_t {
  21. lexer_r *lexer; // stack of lexers (stack used in #include statements)
  22. gnode_r *declarations; // used to keep track of nodes hierarchy
  23. gnode_r *statements; // used to build AST
  24. gravity_delegate_t *delegate; // compiler delegate
  25. uint16_r vdecl; // to keep track of func expression in variable declaration nondes
  26. double time;
  27. uint32_t nerrors;
  28. uint32_t unique_id;
  29. uint32_t last_error_lineno;
  30. uint32_t depth; // to keep track of maximum statements depth
  31. uint32_t expr_depth; // to keep track of maximum expression depth
  32. // state ivars used by Pratt parser
  33. gtoken_t current_token;
  34. gnode_t *current_node;
  35. };
  36. // MARK: - PRATT parser specs -
  37. // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
  38. // http://javascript.crockford.com/tdop/tdop.html
  39. // Precedence table as defined in Swift
  40. // http://nshipster.com/swift-operators/
  41. typedef enum {
  42. PREC_LOWEST,
  43. PREC_ASSIGN = 90, // = *= /= %= += -= <<= >>= &= ^= |= (11 cases)
  44. PREC_TERNARY = 100, // ?: (1 case)
  45. PREC_LOGICAL_OR = 110, // || (1 case)
  46. PREC_LOGICAL_AND = 120, // && (1 case)
  47. PREC_COMPARISON = 130, // < <= > >= == != === !== ~= (9 cases)
  48. PREC_ISA = 132, // isa (1 case)
  49. PREC_RANGE = 135, // ..< ... (2 cases)
  50. PREC_TERM = 140, // + - | ^ (4 cases)
  51. PREC_FACTOR = 150, // * / % & (4 cases)
  52. PREC_SHIFT = 160, // << >> (2 cases)
  53. PREC_UNARY = 170, // + - ! ~ (4 cases)
  54. PREC_CALL = 200 // . ( [ (3 cases)
  55. } prec_level;
  56. typedef gnode_t* (*parse_func) (gravity_parser_t *parser);
  57. typedef struct {
  58. parse_func prefix;
  59. parse_func infix;
  60. prec_level precedence;
  61. const char *name;
  62. bool right;
  63. } grammar_rule;
  64. // This table defines all of the parsing rules for the prefix and infix expressions in the grammar.
  65. #define RULE(prec, fn1, fn2) (grammar_rule){ fn1, fn2, prec, NULL, false}
  66. #define PREFIX(prec, fn) (grammar_rule){ fn, NULL, prec, NULL, false}
  67. #define INFIX(prec, fn) (grammar_rule){ NULL, fn, prec, NULL, false}
  68. #define INFIX_OPERATOR(prec, name) (grammar_rule){ NULL, parse_infix, prec, name, false}
  69. #define INFIX_OPERATOR_RIGHT(prec,name) (grammar_rule){ NULL, parse_infix, prec, name, true}
  70. #define PREFIX_OPERATOR(name) (grammar_rule){ parse_unary, NULL, PREC_LOWEST, name, false}
  71. #define OPERATOR(prec, name) (grammar_rule){ parse_unary, parse_infix, prec, name, false}
  72. // Global singleton grammar rule table
  73. static grammar_rule rules[TOK_END];
  74. // MARK: - Internal macros -
  75. #define MAX_RECURSION_DEPTH 1000
  76. #define MAX_EXPRESSION_DEPTH 512
  77. #define MAX_NUMBER_LENGTH 512
  78. #define SEMICOLON_IS_OPTIONAL 1
  79. #define REPORT_ERROR(_tok,...) report_error(parser, GRAVITY_ERROR_SYNTAX, _tok, __VA_ARGS__)
  80. #define REPORT_WARNING(_tok,...) report_error(parser, GRAVITY_WARNING, _tok, __VA_ARGS__)
  81. #define PUSH_DECLARATION(_decl) marray_push(gnode_t*, *parser->declarations, (gnode_t*)_decl)
  82. #define POP_DECLARATION() marray_pop(*parser->declarations)
  83. #define LAST_DECLARATION() (marray_size(*parser->declarations) ? marray_last(*parser->declarations) : NULL)
  84. #define IS_FUNCTION_ENCLOSED() (get_enclosing(parser, NODE_FUNCTION_DECL))
  85. #define IS_CLASS_ENCLOSED() (get_enclosing(parser, NODE_CLASS_DECL))
  86. #define CHECK_NODE(_n) if (!_n) return NULL
  87. #define POP_LEXER (gravity_lexer_t *)marray_pop(*parser->lexer)
  88. #define CURRENT_LEXER (gravity_lexer_t *)marray_last(*parser->lexer)
  89. #define DECLARE_LEXER gravity_lexer_t *lexer = CURRENT_LEXER; DEBUG_LEXER(lexer)
  90. #define PARSER_CALL_CALLBACK(_t) if (parser->delegate && parser->delegate->parser_callback) parser->delegate->parser_callback(&_t, parser->delegate->xdata)
  91. #define STATIC_TOKEN_CSTRING(_s,_n,_l,_b,_t) char _s[_n] = {0}; uint32_t _l = 0; \
  92. const char *_b = token_string(_t, &_l); \
  93. if (_l) memcpy(_s, _b, MINNUM(_n, _l))
  94. // MARK: - Prototypes -
  95. static const char *parse_identifier (gravity_parser_t *parser);
  96. static gnode_t *parse_statement (gravity_parser_t *parser);
  97. static gnode_r *parse_optional_parameter_declaration (gravity_parser_t *parser, bool is_implicit, bool *has_default_values);
  98. static gnode_t *parse_compound_statement (gravity_parser_t *parser);
  99. static gnode_t *parse_expression (gravity_parser_t *parser);
  100. static gnode_t *parse_declaration_statement (gravity_parser_t *parser);
  101. static gnode_t *parse_function (gravity_parser_t *parser, bool is_declaration, gtoken_t access_specifier, gtoken_t storage_specifier);
  102. static gnode_t *adjust_assignment_expression (gravity_parser_t *parser, gtoken_t tok, gnode_t *lnode, gnode_t *rnode);
  103. static gnode_t *parse_literal_expression (gravity_parser_t *parser);
  104. static gnode_t *parse_macro_statement (gravity_parser_t *parser);
  105. // MARK: - Utils functions -
  106. static gnode_t *get_enclosing (gravity_parser_t *parser, gnode_n tag) {
  107. int32_t n = (int32_t)gnode_array_size(parser->declarations);
  108. if (!n) return NULL;
  109. --n;
  110. while (n >= 0) {
  111. gnode_t *decl = gnode_array_get(parser->declarations, n);
  112. if (!decl) return NULL;
  113. if (decl->tag == tag) return decl;
  114. --n;
  115. }
  116. return NULL;
  117. }
  118. static void patch_token_node (gnode_t *node, gtoken_s token) {
  119. node->token = token;
  120. if (node->tag == NODE_POSTFIX_EXPR) {
  121. gnode_postfix_expr_t *expr = (gnode_postfix_expr_t *)node;
  122. if (expr->id) expr->id->token = token;
  123. size_t count = gnode_array_size(expr->list);
  124. for (size_t i=0; i<count; ++i) {
  125. gnode_t *subnode = (gnode_t *)gnode_array_get(expr->list, i);
  126. if (subnode) subnode->token = token;
  127. }
  128. }
  129. }
  130. static void report_error (gravity_parser_t *parser, error_type_t error_type, gtoken_s token, const char *format, ...) {
  131. // just one error for each line
  132. if (parser->last_error_lineno == token.lineno) return;
  133. // increment internal error counter (and save last reported line) only if it was a real error
  134. if (error_type != GRAVITY_WARNING) {
  135. parser->last_error_lineno = token.lineno;
  136. ++parser->nerrors;
  137. }
  138. // get error callback (if any)
  139. void *data = (parser->delegate) ? parser->delegate->xdata : NULL;
  140. gravity_error_callback error_fn = (parser->delegate) ? ((gravity_delegate_t *)parser->delegate)->error_callback : NULL;
  141. // build error message
  142. char buffer[1024];
  143. va_list arg;
  144. if (format) {
  145. va_start (arg, format);
  146. vsnprintf(buffer, sizeof(buffer), format, arg);
  147. va_end (arg);
  148. }
  149. // setup error struct
  150. error_desc_t error_desc = {
  151. .lineno = token.lineno,
  152. .colno = token.colno,
  153. .fileid = token.fileid,
  154. .offset = token.position
  155. };
  156. // finally call error callback
  157. if (error_fn) error_fn(NULL, error_type, buffer, error_desc, data);
  158. else printf("%s\n", buffer);
  159. }
  160. static gnode_t *parse_error (gravity_parser_t *parser) {
  161. DECLARE_LEXER;
  162. gravity_lexer_next(lexer);
  163. gtoken_s token = gravity_lexer_token(lexer);
  164. REPORT_ERROR(token, "%s", token.value);
  165. return NULL;
  166. }
  167. // RETURN:
  168. // - true if next token is equal to token passed as parameter (token is also consumed)
  169. // - false if next token is not equal (and no error is reported)
  170. //
  171. static bool parse_optional (gravity_parser_t *parser, gtoken_t token) {
  172. DECLARE_LEXER;
  173. gtoken_t peek = gravity_lexer_peek(lexer);
  174. if (token_iserror(peek)) {
  175. parse_error(parser);
  176. peek = gravity_lexer_peek(lexer);
  177. }
  178. if (peek == token) {
  179. gravity_lexer_next(lexer); // consume expected token
  180. return true;
  181. }
  182. // do not report any error in this case
  183. return false;
  184. }
  185. static bool parse_skip_until (gravity_parser_t *parser, gtoken_t token) {
  186. DECLARE_LEXER;
  187. while (1) {
  188. gtoken_t tok = gravity_lexer_next(lexer);
  189. if (tok == token) return true;
  190. if (tok == TOK_EOF) return false;
  191. }
  192. return false;
  193. }
  194. static bool parse_required (gravity_parser_t *parser, gtoken_t token) {
  195. if (parse_optional(parser, token)) return true;
  196. // token not found (and not consumed) so an error strategy must be implemented here
  197. // simple (but not simpler) error recovery
  198. // parser should keep track of what I am parsing
  199. // so based on tok I could have a token list of terminal symbols
  200. // call next until first sync symbol (or EOF or start of another terminal symbol is found)
  201. // simple error recovery, just consume next and report error
  202. DECLARE_LEXER;
  203. gtoken_t next = gravity_lexer_next(lexer);
  204. gtoken_s unexpected_token = gravity_lexer_token(lexer);
  205. REPORT_ERROR(unexpected_token, "Expected %s but found %s.", token_name(token), token_name(next));
  206. return false;
  207. }
  208. static bool parse_semicolon (gravity_parser_t *parser) {
  209. #if SEMICOLON_IS_OPTIONAL
  210. DECLARE_LEXER;
  211. if (gravity_lexer_peek(lexer) == TOK_OP_SEMICOLON) {gravity_lexer_next(lexer); return true;}
  212. return false;
  213. #else
  214. return parse_required(parser, TOK_OP_SEMICOLON);
  215. #endif
  216. }
  217. gnode_t *parse_function (gravity_parser_t *parser, bool is_declaration, gtoken_t access_specifier, gtoken_t storage_specifier) {
  218. DECLARE_LEXER;
  219. // access_specifier? storage_specifier? already parsed
  220. // 'function' IDENTIFIER '(' parameter_declaration_clause? ')' compound_statement
  221. // consume FUNC keyword (or peek for OPEN_CURLYBRACE)
  222. bool is_implicit = (gravity_lexer_peek(lexer) == TOK_OP_OPEN_CURLYBRACE);
  223. gtoken_s token = gravity_lexer_token(lexer);
  224. if (!is_implicit) {
  225. gtoken_t type = gravity_lexer_next(lexer);
  226. token = gravity_lexer_token(lexer);
  227. if (type != TOK_KEY_FUNC) {
  228. REPORT_ERROR(token, "Invalid function expression.");
  229. return NULL;
  230. }
  231. }
  232. // parse IDENTIFIER
  233. const char *identifier = NULL;
  234. if (is_declaration) {
  235. gtoken_t peek = gravity_lexer_peek(lexer);
  236. identifier = (token_isoperator(peek)) ? string_dup(token_name(gravity_lexer_next(lexer))) : parse_identifier(parser);
  237. DEBUG_PARSER("parse_function_declaration %s", identifier);
  238. }
  239. // create func declaration node
  240. gnode_function_decl_t *func = (gnode_function_decl_t *) gnode_function_decl_create(token, identifier, access_specifier, storage_specifier, NULL, NULL, LAST_DECLARATION());
  241. // check and consume TOK_OP_OPEN_PARENTHESIS
  242. if (!is_implicit) parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
  243. // parse optional parameter declaration clause
  244. bool has_default_values = false;
  245. gnode_r *params = parse_optional_parameter_declaration(parser, is_implicit, &has_default_values);
  246. // check and consume TOK_OP_CLOSED_PARENTHESIS
  247. if (!is_implicit) parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  248. // parse compound statement
  249. PUSH_DECLARATION(func);
  250. gnode_compound_stmt_t *compound = (gnode_compound_stmt_t*)parse_compound_statement(parser);
  251. POP_DECLARATION();
  252. // if func is declarared inside a variable declaration node then the semicolon check must be
  253. // performed once at variable declaration node level ad not inside the func node
  254. bool is_inside_var_declaration = ((marray_size(parser->vdecl) > 0) && (marray_last(parser->vdecl) == 1));
  255. func->is_closure = is_inside_var_declaration;
  256. // parse optional semicolon
  257. if (!is_inside_var_declaration) parse_semicolon(parser);
  258. // finish func setup
  259. func->has_defaults = has_default_values;
  260. func->params = params;
  261. func->block = compound;
  262. return (gnode_t *)func;
  263. }
  264. static char *cstring_from_token (gravity_parser_t *parser, gtoken_s token) {
  265. #pragma unused(parser)
  266. uint32_t len = 0;
  267. const char *buffer = token_string(token, &len);
  268. char *str = (char *)mem_alloc(NULL, len+1);
  269. memcpy(str, buffer, len);
  270. return str;
  271. }
  272. static gnode_t *local_store_declaration (gravity_parser_t *parser, const char *identifier, const char *annotation_type, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_t *declaration) {
  273. gnode_r *decls = gnode_array_create();
  274. gnode_variable_decl_t *vdecl = (gnode_variable_decl_t *)gnode_variable_decl_create(declaration->token, TOK_KEY_VAR, access_specifier, storage_specifier, decls, LAST_DECLARATION());
  275. gnode_t *decl = gnode_variable_create(declaration->token, identifier ? string_dup(identifier) : NULL, annotation_type, declaration, LAST_DECLARATION(), vdecl);
  276. gnode_array_push(decls, decl);
  277. return (gnode_t *)vdecl;
  278. }
  279. static gnode_t *decl_check_access_specifier (gnode_t *node) {
  280. // set proper access specifiers
  281. // default is PUBLIC but if IDENTIFIER begins with _ then set it to PRIVATE
  282. if (node->tag == NODE_VARIABLE_DECL) {
  283. // default access specifier for variables is TOK_KEY_PUBLIC
  284. gnode_variable_decl_t *vdec_node = (gnode_variable_decl_t *)node;
  285. if (vdec_node->access == 0) {
  286. bool is_private = false;
  287. if (gnode_array_size(vdec_node->decls) > 0) {
  288. gnode_var_t *var = (gnode_var_t *)gnode_array_get(vdec_node->decls, 0);
  289. is_private = (var->identifier && var->identifier[0] == '_');
  290. }
  291. vdec_node->access = (is_private) ? TOK_KEY_PRIVATE : TOK_KEY_PUBLIC;
  292. }
  293. } else if (node->tag == NODE_FUNCTION_DECL) {
  294. // default access specifier for functions is PUBLIC
  295. gnode_function_decl_t *fdec_node = (gnode_function_decl_t *)node;
  296. if (!fdec_node->identifier) return node;
  297. bool is_private = (fdec_node->identifier[0] == '_');
  298. if (fdec_node->access == 0) fdec_node->access = (is_private) ? TOK_KEY_PRIVATE : TOK_KEY_PUBLIC;
  299. } else if (node->tag == NODE_CLASS_DECL) {
  300. // default access specifier for inner class declarations is PUBLIC
  301. gnode_class_decl_t *cdec_node = (gnode_class_decl_t *)node;
  302. if (!cdec_node->identifier) return node;
  303. bool is_private = (cdec_node->identifier[0] == '_');
  304. if (cdec_node->access == 0) cdec_node->access = (is_private) ? TOK_KEY_PRIVATE : TOK_KEY_PUBLIC;
  305. }
  306. return node;
  307. }
  308. static gliteral_t decode_number_binary (gtoken_s token, int64_t *n) {
  309. // from 2 in order to skip 0b
  310. *n = number_from_bin(&token.value[2], token.bytes-2);
  311. return LITERAL_INT;
  312. }
  313. static gliteral_t decode_number_octal (gtoken_s token, int64_t *n) {
  314. STATIC_TOKEN_CSTRING(str, 512, len, buffer, token);
  315. if (len) *n = (int64_t) number_from_oct(&str[2], len-2);
  316. return LITERAL_INT;
  317. }
  318. static gliteral_t decode_number_hex (gtoken_s token, int64_t *n, double *d) {
  319. #pragma unused(d)
  320. STATIC_TOKEN_CSTRING(str, 512, len, buffer, token);
  321. if (len) *n = (int64_t) number_from_hex(str, token.bytes);
  322. return LITERAL_INT;
  323. }
  324. // MARK: - Expressions -
  325. static gnode_t *parse_ternary_expression (gravity_parser_t *parser) {
  326. DEBUG_PARSER("parse_ternary_expression");
  327. DECLARE_LEXER;
  328. // conditional expression already parsed
  329. gnode_t *cond = parser->current_node;
  330. if (!cond) return NULL;
  331. // '?' expression ':' expression
  332. // '?' already consumed
  333. gtoken_s token = gravity_lexer_token(lexer);
  334. // parse expression 1
  335. gnode_t *expr1 = parse_expression(parser);
  336. CHECK_NODE(expr1);
  337. parse_required(parser, TOK_OP_COLON);
  338. // parse expression 2
  339. gnode_t *expr2 = parse_expression(parser);
  340. CHECK_NODE(expr2);
  341. // read current token to extract node total length
  342. gtoken_s end_token = gravity_lexer_token(lexer);
  343. return gnode_flow_stat_create(token, cond, expr1, expr2, LAST_DECLARATION(), end_token.position + end_token.length - token.position);
  344. }
  345. static gnode_t *parse_file_expression (gravity_parser_t *parser) {
  346. DEBUG_PARSER("parse_file_expression");
  347. DECLARE_LEXER;
  348. // at least one identifier is mandatory
  349. // 'file' ('.' IDENTIFIER)+
  350. gravity_lexer_next(lexer);
  351. gtoken_s token = gravity_lexer_token(lexer);
  352. if (gravity_lexer_peek(lexer) != TOK_OP_DOT) {
  353. REPORT_ERROR(token, "A .identifier list is expected here.");
  354. return NULL;
  355. }
  356. cstring_r *list = cstring_array_create();
  357. while (gravity_lexer_peek(lexer) == TOK_OP_DOT) {
  358. gravity_lexer_next(lexer); // consume TOK_OP_DOT
  359. const char *identifier = parse_identifier(parser);
  360. if (!identifier) {
  361. mem_free(list);
  362. return NULL;
  363. }
  364. cstring_array_push(list, identifier);
  365. }
  366. return gnode_file_expr_create(token, list, LAST_DECLARATION());
  367. }
  368. static const char *parse_identifier (gravity_parser_t *parser) {
  369. DECLARE_LEXER;
  370. // parse IDENTIFIER is always mandatory
  371. gtoken_t type = gravity_lexer_peek(lexer);
  372. if (type != TOK_IDENTIFIER) {
  373. if (type == TOK_ERROR) parse_error(parser);
  374. else REPORT_ERROR(gravity_lexer_token(lexer), "Expected identifier but found %s", token_name(type));
  375. return NULL;
  376. }
  377. gravity_lexer_next(lexer);
  378. gtoken_s token = gravity_lexer_token(lexer);
  379. const char *identifier = cstring_from_token(parser, token);
  380. return identifier;
  381. }
  382. static const char *parse_optional_type_annotation (gravity_parser_t *parser) {
  383. DECLARE_LEXER;
  384. const char *type_annotation = NULL;
  385. gtoken_t peek = gravity_lexer_peek(lexer);
  386. // type annotation
  387. // function foo (a: string, b: number)
  388. // check for optional type_annotation
  389. if (peek == TOK_OP_COLON) {
  390. gravity_lexer_next(lexer); // consume TOK_OP_COLON
  391. // parse identifier
  392. type_annotation = parse_identifier(parser);
  393. }
  394. return type_annotation;
  395. }
  396. static gnode_t *parse_optional_default_value (gravity_parser_t *parser) {
  397. DECLARE_LEXER;
  398. gnode_t *default_value = NULL;
  399. gtoken_t peek = gravity_lexer_peek(lexer);
  400. // optional literal default value
  401. // function foo (a: string = "Hello", b: number = 3)
  402. // type annotation not enforced here
  403. // check for optional default value
  404. if (peek == TOK_OP_ASSIGN) {
  405. gravity_lexer_next(lexer); // consume TOK_OP_ASSIGN
  406. // parse literal value
  407. default_value = parse_literal_expression(parser);
  408. }
  409. return default_value;
  410. }
  411. static gnode_t *parse_parentheses_expression (gravity_parser_t *parser) {
  412. DEBUG_PARSER("parse_parentheses_expression");
  413. // check and consume TOK_OP_OPEN_PARENTHESIS
  414. parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
  415. // parse expression
  416. gnode_t *expr = parse_expression(parser);
  417. CHECK_NODE(expr);
  418. // check and consume TOK_OP_CLOSED_PARENTHESIS
  419. parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  420. return expr;
  421. }
  422. static gnode_t *parse_list_expression (gravity_parser_t *parser) {
  423. DEBUG_PARSER("parse_list_expression");
  424. DECLARE_LEXER;
  425. /*
  426. list_expression
  427. : '[' ((expression) (',' expression)*)? ']' // array or empty array
  428. | '[' ((map_entry (',' map_entry)*) | ':') ']' // map or empty map
  429. ;
  430. map_entry
  431. : STRING ':' expression
  432. ;
  433. */
  434. // consume first '['
  435. parse_required(parser, TOK_OP_OPEN_SQUAREBRACKET);
  436. // this saved token is necessary to save start of the list/map
  437. gtoken_s token = gravity_lexer_token(lexer);
  438. // check for special empty list
  439. if (gravity_lexer_peek(lexer) == TOK_OP_CLOSED_SQUAREBRACKET) {
  440. gravity_lexer_next(lexer); // consume TOK_OP_CLOSED_SQUAREBRACKET
  441. return gnode_list_expr_create(token, NULL, NULL, false, LAST_DECLARATION());
  442. }
  443. // check for special empty map
  444. if (gravity_lexer_peek(lexer) == TOK_OP_COLON) {
  445. gravity_lexer_next(lexer); // consume TOK_OP_COLON
  446. parse_required(parser, TOK_OP_CLOSED_SQUAREBRACKET);
  447. return gnode_list_expr_create(token, NULL, NULL, true, LAST_DECLARATION());
  448. }
  449. // parse first expression (if any) outside of the list/map loop
  450. // in order to check if it is a list or map expression
  451. gnode_t *expr1 = parse_expression(parser);
  452. // if next token is a colon then assume a map
  453. bool ismap = (gravity_lexer_peek(lexer) == TOK_OP_COLON);
  454. // a list expression can be an array [expr1, expr2] or a map [string1: expr1, string2: expr2]
  455. // cannot be mixed so be very restrictive here
  456. gnode_r *list1 = gnode_array_create();
  457. gnode_r *list2 = (ismap) ? gnode_array_create() : NULL;
  458. if (expr1) gnode_array_push(list1, expr1);
  459. if (ismap) {
  460. parse_required(parser, TOK_OP_COLON);
  461. gnode_t *expr2 = parse_expression(parser);
  462. if (expr2) gnode_array_push(list2, expr2);
  463. }
  464. while (gravity_lexer_peek(lexer) == TOK_OP_COMMA) {
  465. gravity_lexer_next(lexer); // consume TOK_OP_COMMA
  466. // parse first expression
  467. expr1 = parse_expression(parser);
  468. if (expr1) gnode_array_push(list1, expr1);
  469. if (ismap) {
  470. parse_required(parser, TOK_OP_COLON);
  471. gnode_t *expr2 = parse_expression(parser);
  472. if (expr2) gnode_array_push(list2, expr2);
  473. }
  474. }
  475. parse_required(parser, TOK_OP_CLOSED_SQUAREBRACKET);
  476. return gnode_list_expr_create(token, list1, list2, ismap, LAST_DECLARATION());
  477. }
  478. static gnode_t *parse_function_expression (gravity_parser_t *parser) {
  479. DEBUG_PARSER("parse_function_expression");
  480. // 'func' '(' parameter_declaration_clause? ')' compound_statement
  481. // or
  482. // compound_statement (implicit func and implicit parameters)
  483. /*
  484. example:
  485. func foo () {
  486. var bar = func(x) {return x*2;}
  487. return bar(3);
  488. }
  489. it is equivalent to:
  490. func foo () {
  491. func bar(x) {return x*2;}
  492. return bar(3);
  493. }
  494. */
  495. // check if func is a function expression or
  496. // if it is a func keyword used to refers to
  497. // the current executing function
  498. gnode_t *node = parse_function(parser, false, 0, 0);
  499. return node;
  500. }
  501. static gnode_t *parse_identifier_expression (gravity_parser_t *parser) {
  502. DEBUG_PARSER("parse_identifier_expression");
  503. DECLARE_LEXER;
  504. const char *identifier = parse_identifier(parser);
  505. if (!identifier) return NULL;
  506. DEBUG_PARSER("IDENTIFIER: %s", identifier);
  507. gtoken_s token = gravity_lexer_token(lexer);
  508. return gnode_identifier_expr_create(token, identifier, NULL, LAST_DECLARATION());
  509. }
  510. static gnode_t *parse_identifier_or_keyword_expression (gravity_parser_t *parser) {
  511. DEBUG_PARSER("parse_identifier_expression");
  512. DECLARE_LEXER;
  513. // check if token is a keyword
  514. uint32_t idx_start, idx_end;
  515. token_keywords_indexes(&idx_start, &idx_end);
  516. gtoken_t peek = gravity_lexer_peek(lexer);
  517. if (((uint32_t)peek >= idx_start) && ((uint32_t)peek <= idx_end)) {
  518. // consume token keyword
  519. gtoken_t keyword = gravity_lexer_next(lexer);
  520. gtoken_s token = gravity_lexer_token(lexer);
  521. // convert from keyword to identifier
  522. const char *identifier = string_dup(token_name(keyword));
  523. return gnode_identifier_expr_create(token, identifier, NULL, LAST_DECLARATION());
  524. }
  525. // default case
  526. return parse_identifier_expression(parser);
  527. }
  528. static gnode_t *parse_number_expression (gravity_parser_t *parser, gtoken_s token) {
  529. DEBUG_PARSER("parse_number_expression");
  530. // check for special built-in cases first
  531. if (token.builtin != BUILTIN_NONE) {
  532. if (token.builtin == BUILTIN_LINE) return gnode_literal_int_expr_create(token, token.lineno, LAST_DECLARATION());
  533. else if (token.builtin == BUILTIN_COLUMN) return gnode_literal_int_expr_create(token, token.colno, LAST_DECLARATION());
  534. }
  535. // what I know here is that token is a well formed NUMBER
  536. // so I just need to properly decode it
  537. const char *value = token.value;
  538. gliteral_t type;
  539. int64_t n = 0;
  540. double d = 0;
  541. if (value[0] == '0') {
  542. int c = toupper(value[1]);
  543. if (c == 'B') {type = decode_number_binary(token, &n); goto report_node;}
  544. else if (c == 'O') {type = decode_number_octal(token, &n); goto report_node;}
  545. else if (c == 'X') {type = decode_number_hex(token, &n, &d); goto report_node;}
  546. }
  547. // number is decimal (check if it is float)
  548. bool isfloat = false;
  549. for (uint32_t i=0; i<token.bytes; ++i) {
  550. if (value[i] == '.') {isfloat = true; break;}
  551. if (value[i] == 'e') {isfloat = true; break;}
  552. }
  553. STATIC_TOKEN_CSTRING(str, MAX_NUMBER_LENGTH, len, buffer, token);
  554. if (len >= MAX_NUMBER_LENGTH) {
  555. REPORT_ERROR(token, "Malformed numeric expression.");
  556. return NULL;
  557. }
  558. if (isfloat) {
  559. d = strtod(str, NULL);
  560. type = LITERAL_FLOAT;
  561. DEBUG_PARSER("FLOAT: %.2f", d);
  562. }
  563. else {
  564. n = (int64_t) strtoll(str, NULL, 0);
  565. type = LITERAL_INT;
  566. DEBUG_PARSER("INT: %lld", n);
  567. }
  568. report_node:
  569. if (type == LITERAL_FLOAT) return gnode_literal_float_expr_create(token, (double)d, LAST_DECLARATION());
  570. else if (type == LITERAL_INT) return gnode_literal_int_expr_create(token, n, LAST_DECLARATION());
  571. else assert(0);
  572. return NULL;
  573. }
  574. static gnode_t *parse_analyze_literal_string (gravity_parser_t *parser, gtoken_s token, const char *s, uint32_t len) {
  575. // check for special built-in cases first
  576. if (token.builtin != BUILTIN_NONE) {
  577. if (token.builtin == BUILTIN_FILE) {
  578. if (parser->delegate && parser->delegate->filename_callback) {
  579. const char *filename = parser->delegate->filename_callback(token.fileid, parser->delegate->xdata);
  580. if (!filename) filename = "";
  581. return gnode_literal_string_expr_create(token, (char *)filename, (uint32_t)strlen(filename), false, LAST_DECLARATION());
  582. }
  583. }
  584. else if (token.builtin == BUILTIN_FUNC) {
  585. gnode_function_decl_t *node = (gnode_function_decl_t *)get_enclosing(parser, NODE_FUNCTION_DECL);
  586. const char *identifier = (node && node->identifier) ? (node->identifier) : "";
  587. return gnode_literal_string_expr_create(token, (char *)identifier, (uint32_t)strlen(identifier), false, LAST_DECLARATION());
  588. }
  589. else if (token.builtin == BUILTIN_CLASS) {
  590. gnode_class_decl_t *node = (gnode_class_decl_t *)get_enclosing(parser, NODE_CLASS_DECL);
  591. const char *identifier = (node && node->identifier) ? (node->identifier) : "";
  592. return gnode_literal_string_expr_create(token, (char *)identifier, (uint32_t)strlen(identifier), false, LAST_DECLARATION());
  593. }
  594. }
  595. // used in string interpolation
  596. gnode_r *r = NULL;
  597. // analyze s (of length len) for escaped characters or for interpolations
  598. char *buffer = mem_alloc(NULL, len+1);
  599. uint32_t length = 0;
  600. for (uint32_t i=0; i<len;) {
  601. int c = s[i];
  602. if (c == '\\') {
  603. // handle escape sequence here
  604. if (i+1 >= len) {REPORT_ERROR(token, "Unexpected EOF inside a string literal"); goto return_string;}
  605. switch (s[i+1]) {
  606. case '\'': c = '\''; ++i; break;
  607. case '"': c = '"'; ++i; break;
  608. case '\\': c = '\\'; ++i; break;
  609. case 'a': c = '\a'; ++i; break;
  610. case 'b': c = '\b'; ++i; break;
  611. case 'f': c = '\f'; ++i; break;
  612. case 'n': c = '\n'; ++i; break;
  613. case 'r': c = '\r'; ++i; break;
  614. case 't': c = '\t'; ++i; break;
  615. case 'v': c = '\v'; ++i; break;
  616. case 'x': {
  617. // double hex digits sequence
  618. // \XFF
  619. if (i+1+2 >= len) {REPORT_ERROR(token, "Unexpected EOF inside a string literal"); goto return_string;}
  620. // setup a static buffer assuming the next two characters are hex
  621. char b[3] = {s[i+2], s[i+3], 0};
  622. // convert from base 16 to base 10 (FF is at maximum 255)
  623. c = (int)strtoul(b, NULL, 16);
  624. buffer[length] = c;
  625. // i+2 is until \x plus 2 hex characters
  626. i+=2+2; ++length;
  627. continue;
  628. }
  629. case 'u': {
  630. // 4 digits unicode sequence
  631. // \uXXXX
  632. if (i+1+4 >= len) {REPORT_ERROR(token, "Unexpected EOF inside a string literal"); goto return_string;}
  633. // setup a static buffer assuming the next four characters are hex
  634. char b[5] = {s[i+2], s[i+3], s[i+4], s[i+5], 0};
  635. // convert from base 16 to base 10 (FFFF is at maximum 65535)
  636. uint32_t n = (uint32_t)strtoul(b, NULL, 16);
  637. length += utf8_encode(&buffer[length], n);
  638. i+=2+4;
  639. continue;
  640. }
  641. case 'U': {
  642. // 8 digits unicode sequence
  643. // \uXXXXXXXX
  644. if (i+1+8 >= len) {REPORT_ERROR(token, "Unexpected EOF inside a string literal"); goto return_string;}
  645. // setup a static buffer assuming the next height characters are hex
  646. char b[9] = {s[i+2], s[i+3], s[i+4], s[i+5], s[i+6], s[i+7], s[i+8], s[i+9], 0};
  647. // convert from base 16 to base 10 (FFFF is at maximum 4294967295)
  648. uint32_t n = (uint32_t)strtoul(b, NULL, 16);
  649. length += utf8_encode(&buffer[length], n);
  650. i+=2+8;
  651. continue;
  652. }
  653. case '(': {
  654. // string interpolation case
  655. i+=2; // skip \ and (
  656. uint32_t j=i;
  657. uint32_t nesting_level = 0;
  658. bool subfound = false;
  659. while (i<len) {
  660. if (s[i] == ')') {
  661. if (nesting_level == 0) subfound = true;
  662. else --nesting_level;
  663. }
  664. else if (s[i] == '(') {
  665. ++nesting_level;
  666. }
  667. ++i;
  668. if (subfound) break;
  669. }
  670. if (!subfound || nesting_level != 0) {
  671. REPORT_ERROR(token, "Malformed interpolation string not closed by )");
  672. goto return_string;
  673. }
  674. uint32_t sublen = i - j;
  675. // create a new temp lexer
  676. gravity_lexer_t *sublexer = gravity_lexer_create(&s[j], sublen, 0, true);
  677. marray_push(gravity_lexer_t*, *parser->lexer, sublexer);
  678. // parse interpolated expression
  679. gnode_t *subnode = parse_expression(parser);
  680. // add expression to r
  681. if (subnode) {
  682. // subnode contains information from a temp lexer so let's fix it
  683. patch_token_node(subnode, token);
  684. if (!r) r = gnode_array_create();
  685. if (length) gnode_array_push(r, gnode_literal_string_expr_create(token, buffer, length, true, LAST_DECLARATION()));
  686. gnode_array_push(r, subnode);
  687. }
  688. // free temp lexer
  689. marray_pop(*parser->lexer);
  690. gravity_lexer_free(sublexer);
  691. if (!subnode) goto return_string;
  692. buffer = mem_alloc(NULL, len+1);
  693. length = 0;
  694. continue;
  695. }
  696. default:
  697. // ignore unknown sequence
  698. break;
  699. }
  700. }
  701. buffer[length] = c;
  702. ++i; ++length;
  703. }
  704. return_string:
  705. // append the last string if any and if interpolation mode is on
  706. if (r && length) gnode_array_push(r, gnode_literal_string_expr_create(token, buffer, length, true, LAST_DECLARATION()));
  707. // return a node (even in case of error) so its memory will be automatically freed
  708. return (r) ? gnode_string_interpolation_create(token, r, LAST_DECLARATION()) : gnode_literal_string_expr_create(token, buffer, length, true, LAST_DECLARATION());
  709. }
  710. gnode_t *parse_literal_expression (gravity_parser_t *parser) {
  711. DEBUG_PARSER("parse_literal_expression");
  712. DECLARE_LEXER;
  713. gtoken_t type = gravity_lexer_next(lexer);
  714. gtoken_s token = gravity_lexer_token(lexer);
  715. if (type == TOK_STRING) {
  716. uint32_t len = 0;
  717. const char *value = token_string(token, &len);
  718. DEBUG_PARSER("STRING: %.*s", len, value);
  719. // run string analyzer because string is returned as is from the lexer
  720. // but string can contains escaping sequences and interpolations that
  721. // need to be processed
  722. return parse_analyze_literal_string(parser, token, value, len);
  723. }
  724. if (type == TOK_KEY_TRUE || type == TOK_KEY_FALSE) {
  725. return gnode_literal_bool_expr_create(token, (int32_t)(type == TOK_KEY_TRUE) ? 1 : 0, LAST_DECLARATION());
  726. }
  727. if (type != TOK_NUMBER) {
  728. REPORT_ERROR(token, "Expected literal expression but found %s.", token_name(type));
  729. return NULL;
  730. }
  731. return parse_number_expression(parser, token);
  732. }
  733. static gnode_t *parse_keyword_expression (gravity_parser_t *parser) {
  734. DEBUG_PARSER("parse_keyword_expression");
  735. DECLARE_LEXER;
  736. gravity_lexer_next(lexer);
  737. gtoken_s token = gravity_lexer_token(lexer);
  738. return gnode_keyword_expr_create(token, LAST_DECLARATION());
  739. }
  740. static gnode_r *parse_arguments_expression (gravity_parser_t *parser) {
  741. DEBUG_PARSER("parse_arguments_expression");
  742. DECLARE_LEXER;
  743. // it's OK for a call_expression_list to be empty
  744. if (gravity_lexer_peek(lexer) == TOK_OP_CLOSED_PARENTHESIS) return NULL;
  745. // https://en.wikipedia.org/wiki/Named_parameter
  746. // with the introduction of named parameters there are a lot
  747. // of sub-cases to handle here, for example I cannot know in
  748. // advance if a call has named parameters or not from the
  749. // beginning because we also support mixed calls (both position
  750. // and named parameters)
  751. // so basically I collect two arrays here
  752. // one for names (or positions) and one for values
  753. // if the call is not a named call then the useless
  754. // array is discarded
  755. bool arg_expected = true;
  756. gnode_r *list = gnode_array_create();
  757. uint32_t index = 0;
  758. while (1) {
  759. gtoken_t peek = gravity_lexer_peek(lexer);
  760. if (peek == TOK_OP_COMMA) {
  761. // added the ability to convert ,, to ,undefined,
  762. gnode_array_push(list, gnode_keyword_expr_create(UNDEF_TOKEN, LAST_DECLARATION()));
  763. arg_expected = true;
  764. // consume next TOK_OP_COMMA and check for special ,) case
  765. gravity_lexer_next(lexer);
  766. if (gravity_lexer_peek(lexer) == TOK_OP_CLOSED_PARENTHESIS)
  767. gnode_array_push(list, gnode_keyword_expr_create(UNDEF_TOKEN, LAST_DECLARATION()));
  768. } else {
  769. // check exit condition
  770. if ((peek == TOK_EOF) || (peek == TOK_OP_CLOSED_PARENTHESIS))
  771. break;
  772. // I am going to parse and expression but is it allowed?
  773. if (!arg_expected) {
  774. REPORT_ERROR(gravity_lexer_token_next(lexer), "Missing , in function call.");
  775. return list;
  776. }
  777. // parse expression
  778. gnode_t *expr = parse_expression(parser);
  779. if (expr) gnode_array_push(list, expr);
  780. // consume next TOK_OP_COMMA and check for special ,) case
  781. peek = gravity_lexer_peek(lexer);
  782. if (peek == TOK_OP_COMMA) {
  783. gravity_lexer_next(lexer);
  784. if (gravity_lexer_peek(lexer) == TOK_OP_CLOSED_PARENTHESIS)
  785. gnode_array_push(list, gnode_keyword_expr_create(UNDEF_TOKEN, LAST_DECLARATION()));
  786. }
  787. // arg is expected only if a comma is consumed
  788. // this fixes syntax errors like System.print("Hello" " World")
  789. arg_expected = (peek == TOK_OP_COMMA);
  790. }
  791. ++index;
  792. }
  793. return list;
  794. }
  795. static gnode_t *parse_postfix_expression (gravity_parser_t *parser, gtoken_t tok) {
  796. DEBUG_PARSER("parse_postfix_expression");
  797. DECLARE_LEXER;
  798. // '[' assignment_expression ']' => Subscript operator
  799. // '(' expression_list? ')' => Function call operator
  800. // '.' IDENTIFIER => Member access operator
  801. // tok already consumed and used to identify postfix sub-expression
  802. gnode_t *lnode = parser->current_node;
  803. gtoken_s token = gravity_lexer_token(lexer);
  804. // a postfix expression is an expression followed by a list of other expressions (separated by specific tokens)
  805. gnode_r *list = gnode_array_create();
  806. while (1) {
  807. gnode_t *node = NULL;
  808. if (tok == TOK_OP_OPEN_SQUAREBRACKET) {
  809. gnode_t *expr = parse_expression(parser);
  810. gtoken_s subtoken = gravity_lexer_token(lexer);
  811. parse_required(parser, TOK_OP_CLOSED_SQUAREBRACKET);
  812. node = gnode_postfix_subexpr_create(subtoken, NODE_SUBSCRIPT_EXPR, expr, NULL, LAST_DECLARATION());
  813. } else if (tok == TOK_OP_OPEN_PARENTHESIS) {
  814. gnode_r *args = parse_arguments_expression(parser); // can be NULL and it's OK
  815. gtoken_s subtoken = gravity_lexer_token(lexer);
  816. parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  817. node = gnode_postfix_subexpr_create(subtoken, NODE_CALL_EXPR, NULL, args, LAST_DECLARATION());
  818. } else if (tok == TOK_OP_DOT) {
  819. // was parse_identifier_expression but we need to allow also keywords here in order
  820. // to be able to supports expressions like name.repeat (repeat is a keyword but in this
  821. // context it should be interpreted as an identifier)
  822. gnode_t *expr = parse_identifier_or_keyword_expression(parser);
  823. gtoken_s subtoken = gravity_lexer_token(lexer);
  824. node = gnode_postfix_subexpr_create(subtoken, NODE_ACCESS_EXPR, expr, NULL, LAST_DECLARATION());
  825. } else {
  826. // should never reach this point
  827. assert(0);
  828. }
  829. // add subnode to list
  830. gnode_array_push(list, node);
  831. // check if postifx expression has more sub-nodes
  832. gtoken_t peek = gravity_lexer_peek(lexer);
  833. if ((peek != TOK_OP_OPEN_SQUAREBRACKET) && (peek != TOK_OP_OPEN_PARENTHESIS) && (peek != TOK_OP_DOT)) break;
  834. tok = gravity_lexer_next(lexer);
  835. }
  836. return gnode_postfix_expr_create(token, lnode, list, LAST_DECLARATION());
  837. }
  838. static gnode_t *parse_postfix_subscript (gravity_parser_t *parser) {
  839. // NOTE:
  840. // Gravity does not support a syntax like m[1,2] for matrix access (not m[1,2,3])
  841. // but it supports a syntax like m[1][2] (or m[1][2][3])
  842. DEBUG_PARSER("parse_postfix_subscript");
  843. return parse_postfix_expression(parser, TOK_OP_OPEN_SQUAREBRACKET);
  844. }
  845. static gnode_t *parse_postfix_access (gravity_parser_t *parser) {
  846. DEBUG_PARSER("parse_postfix_access");
  847. return parse_postfix_expression(parser, TOK_OP_DOT);
  848. }
  849. static gnode_t *parse_postfix_call (gravity_parser_t *parser) {
  850. DEBUG_PARSER("parse_postfix_call");
  851. return parse_postfix_expression(parser, TOK_OP_OPEN_PARENTHESIS);
  852. }
  853. static gnode_t *parse_precedence(gravity_parser_t *parser, prec_level precedence) {
  854. DEBUG_PARSER("parse_precedence (level %d)", precedence);
  855. DECLARE_LEXER;
  856. // peek next and check for EOF
  857. gtoken_t type = gravity_lexer_peek(lexer);
  858. if (type == TOK_EOF) return NULL;
  859. // execute prefix callback (if any)
  860. parse_func prefix = rules[type].prefix;
  861. // to protect stack from excessive recursion
  862. if (prefix && (++parser->expr_depth > MAX_EXPRESSION_DEPTH)) {
  863. // consume next token to avoid infinite loops
  864. gravity_lexer_next(lexer);
  865. REPORT_ERROR(gravity_lexer_token(lexer), "Maximum expression depth reached.");
  866. return NULL;
  867. }
  868. gnode_t *node = (prefix) ? prefix(parser) : NULL;
  869. if (prefix) --parser->expr_depth;
  870. if (!prefix || !node) {
  871. // we need to consume next token because error was triggered in peek
  872. gravity_lexer_next(lexer);
  873. REPORT_ERROR(gravity_lexer_token(lexer), "Expected expression but found %s.", token_name(type));
  874. return NULL;
  875. }
  876. // peek next and check for EOF
  877. gtoken_t peek = gravity_lexer_peek(lexer);
  878. if (peek == TOK_EOF) return node;
  879. while (precedence < rules[peek].precedence) {
  880. gtoken_t tok = gravity_lexer_next(lexer);
  881. grammar_rule *rule = &rules[tok];
  882. // execute infix callback
  883. parser->current_token = tok;
  884. parser->current_node = node;
  885. node = rule->infix(parser);
  886. // peek next and check for EOF
  887. peek = gravity_lexer_peek(lexer);
  888. if (peek == TOK_EOF) break;
  889. }
  890. return node;
  891. }
  892. static gnode_t *parse_expression (gravity_parser_t *parser) {
  893. DEBUG_PARSER("parse_expression");
  894. return parse_precedence(parser, PREC_LOWEST);
  895. }
  896. static gnode_t *parse_unary (gravity_parser_t *parser) {
  897. DEBUG_PARSER("parse_unary");
  898. DECLARE_LEXER;
  899. gtoken_t tok = gravity_lexer_next(lexer);
  900. gnode_t *node = parse_precedence(parser, PREC_UNARY);
  901. return gnode_unary_expr_create(tok, node, LAST_DECLARATION());
  902. }
  903. static gnode_t *parse_infix (gravity_parser_t *parser) {
  904. DEBUG_PARSER("parse_infix");
  905. gtoken_t tok = parser->current_token;
  906. gnode_t *lnode = parser->current_node;
  907. // we can make right associative operators by reducing the right binding power
  908. grammar_rule *rule = &rules[tok];
  909. prec_level precedence = (rule->right) ? rule->precedence-1 : rule->precedence;
  910. gnode_t *rnode = parse_precedence(parser, precedence);
  911. if ((tok != TOK_OP_ASSIGN) && token_isassignment(tok)) return adjust_assignment_expression(parser, tok, lnode, rnode);
  912. return gnode_binary_expr_create(tok, lnode, rnode, LAST_DECLARATION());
  913. }
  914. // MARK: -
  915. static gnode_t *adjust_assignment_expression (gravity_parser_t *parser, gtoken_t tok, gnode_t *lnode, gnode_t *rnode) {
  916. DEBUG_PARSER("adjust_assignment_expression");
  917. // called when tok is an assignment != TOK_OP_ASSIGN
  918. // convert expressions:
  919. // a += 1 => a = a + 1
  920. // a -= 1 => a = a - 1
  921. // a *= 1 => a = a * 1
  922. // a /= 1 => a = a / 1
  923. // a %= 1 => a = a % 1
  924. // a <<=1 => a = a << 1
  925. // a >>=1 => a = a >> 1
  926. // a &= 1 => a = a & 1
  927. // a |= 1 => a = a | 1
  928. // a ^= 1 => a = a ^ 1
  929. gtoken_t t;
  930. switch (tok) {
  931. case TOK_OP_MUL_ASSIGN: t = TOK_OP_MUL; break;
  932. case TOK_OP_DIV_ASSIGN: t = TOK_OP_DIV; break;
  933. case TOK_OP_REM_ASSIGN: t = TOK_OP_REM; break;
  934. case TOK_OP_ADD_ASSIGN: t = TOK_OP_ADD; break;
  935. case TOK_OP_SUB_ASSIGN: t = TOK_OP_SUB; break;
  936. case TOK_OP_SHIFT_LEFT_ASSIGN: t = TOK_OP_SHIFT_LEFT; break;
  937. case TOK_OP_SHIFT_RIGHT_ASSIGN: t = TOK_OP_SHIFT_RIGHT; break;
  938. case TOK_OP_BIT_AND_ASSIGN: t = TOK_OP_BIT_AND; break;
  939. case TOK_OP_BIT_OR_ASSIGN: t = TOK_OP_BIT_OR; break;
  940. case TOK_OP_BIT_XOR_ASSIGN: t = TOK_OP_BIT_XOR; break;
  941. // should never reach this point
  942. default: assert(0); break;
  943. }
  944. // duplicate node is mandatory here, otherwise the deallocator will try to free memory occopied by the same node twice
  945. gnode_t *duplicate = gnode_duplicate(lnode, true);
  946. if (!duplicate) {DECLARE_LEXER; REPORT_ERROR(gravity_lexer_token(lexer), "An unexpected error occurred in %s", token_name(tok)); return NULL;}
  947. rnode = gnode_binary_expr_create(t, duplicate, rnode, LAST_DECLARATION());
  948. tok = TOK_OP_ASSIGN;
  949. // its an assignment expression so switch the order
  950. return gnode_binary_expr_create(tok, lnode, rnode, LAST_DECLARATION());
  951. }
  952. static void init_grammer_rules (void) {
  953. static bool created = false;
  954. if (created) return;
  955. created = true;
  956. // rules is a static variable initialized to 0
  957. // so we automatically have all members initialized to UNUSED
  958. rules[TOK_OP_OPEN_PARENTHESIS] = RULE(PREC_CALL, parse_parentheses_expression, parse_postfix_call);
  959. rules[TOK_OP_OPEN_SQUAREBRACKET] = RULE(PREC_CALL, parse_list_expression, parse_postfix_subscript);
  960. rules[TOK_OP_DOT] = RULE(PREC_CALL, parse_literal_expression, parse_postfix_access);
  961. rules[TOK_OP_OPEN_CURLYBRACE] = PREFIX(PREC_LOWEST, parse_function_expression);
  962. rules[TOK_KEY_FUNC] = PREFIX(PREC_LOWEST, parse_function_expression);
  963. rules[TOK_IDENTIFIER] = PREFIX(PREC_LOWEST, parse_identifier_expression);
  964. rules[TOK_STRING] = PREFIX(PREC_LOWEST, parse_literal_expression);
  965. rules[TOK_NUMBER] = PREFIX(PREC_LOWEST, parse_literal_expression);
  966. rules[TOK_KEY_UNDEFINED] = PREFIX(PREC_LOWEST, parse_keyword_expression);
  967. rules[TOK_KEY_CURRARGS] = PREFIX(PREC_LOWEST, parse_keyword_expression);
  968. rules[TOK_KEY_CURRFUNC] = PREFIX(PREC_LOWEST, parse_keyword_expression);
  969. rules[TOK_KEY_SUPER] = PREFIX(PREC_LOWEST, parse_keyword_expression);
  970. rules[TOK_KEY_FILE] = PREFIX(PREC_LOWEST, parse_file_expression);
  971. rules[TOK_KEY_NULL] = PREFIX(PREC_LOWEST, parse_keyword_expression);
  972. rules[TOK_KEY_TRUE] = PREFIX(PREC_LOWEST, parse_keyword_expression);
  973. rules[TOK_KEY_FALSE] = PREFIX(PREC_LOWEST, parse_keyword_expression);
  974. rules[TOK_OP_SHIFT_LEFT] = INFIX_OPERATOR(PREC_SHIFT, "<<");
  975. rules[TOK_OP_SHIFT_RIGHT] = INFIX_OPERATOR(PREC_SHIFT, ">>");
  976. rules[TOK_OP_MUL] = INFIX_OPERATOR(PREC_FACTOR, "*");
  977. rules[TOK_OP_DIV] = INFIX_OPERATOR(PREC_FACTOR, "/");
  978. rules[TOK_OP_REM] = INFIX_OPERATOR(PREC_FACTOR, "%");
  979. rules[TOK_OP_BIT_AND] = INFIX_OPERATOR(PREC_FACTOR, "&");
  980. rules[TOK_OP_ADD] = OPERATOR(PREC_TERM, "+");
  981. rules[TOK_OP_SUB] = OPERATOR(PREC_TERM, "-");
  982. rules[TOK_OP_BIT_OR] = INFIX_OPERATOR(PREC_TERM, "|");
  983. rules[TOK_OP_BIT_XOR] = INFIX_OPERATOR(PREC_TERM, "^");
  984. rules[TOK_OP_BIT_NOT] = PREFIX_OPERATOR("~");
  985. rules[TOK_OP_RANGE_EXCLUDED] = INFIX_OPERATOR(PREC_RANGE, "..<");
  986. rules[TOK_OP_RANGE_INCLUDED] = INFIX_OPERATOR(PREC_RANGE, "...");
  987. rules[TOK_KEY_ISA] = INFIX_OPERATOR(PREC_ISA, "is");
  988. rules[TOK_OP_LESS] = INFIX_OPERATOR(PREC_COMPARISON, "<");
  989. rules[TOK_OP_LESS_EQUAL] = INFIX_OPERATOR(PREC_COMPARISON, "<=");
  990. rules[TOK_OP_GREATER] = INFIX_OPERATOR(PREC_COMPARISON, ">");
  991. rules[TOK_OP_GREATER_EQUAL] = INFIX_OPERATOR(PREC_COMPARISON, ">=");
  992. rules[TOK_OP_ISEQUAL] = INFIX_OPERATOR(PREC_COMPARISON, "==");
  993. rules[TOK_OP_ISNOTEQUAL] = INFIX_OPERATOR(PREC_COMPARISON, "!=");
  994. rules[TOK_OP_ISIDENTICAL] = INFIX_OPERATOR(PREC_COMPARISON, "===");
  995. rules[TOK_OP_ISNOTIDENTICAL] = INFIX_OPERATOR(PREC_COMPARISON, "!==");
  996. rules[TOK_OP_PATTERN_MATCH] = INFIX_OPERATOR(PREC_COMPARISON, "~=");
  997. rules[TOK_OP_AND] = INFIX_OPERATOR_RIGHT(PREC_LOGICAL_AND, "&&");
  998. rules[TOK_OP_OR] = INFIX_OPERATOR_RIGHT(PREC_LOGICAL_OR, "||");
  999. rules[TOK_OP_TERNARY] = INFIX(PREC_TERNARY, parse_ternary_expression);
  1000. rules[TOK_OP_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "=");
  1001. rules[TOK_OP_MUL_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "*=");
  1002. rules[TOK_OP_DIV_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "/=");
  1003. rules[TOK_OP_REM_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "%=");
  1004. rules[TOK_OP_ADD_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "+=");
  1005. rules[TOK_OP_SUB_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "-=");
  1006. rules[TOK_OP_SHIFT_LEFT_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "<<=");
  1007. rules[TOK_OP_SHIFT_RIGHT_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, ">>=");
  1008. rules[TOK_OP_BIT_AND_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "=&");
  1009. rules[TOK_OP_BIT_OR_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "|=");
  1010. rules[TOK_OP_BIT_XOR_ASSIGN] = INFIX_OPERATOR(PREC_ASSIGN, "^=");
  1011. rules[TOK_OP_NOT] = PREFIX_OPERATOR("!");
  1012. }
  1013. // MARK: - Declarations -
  1014. static gnode_t *parse_getter_setter (gravity_parser_t *parser) {
  1015. DEBUG_PARSER("parse_getter_setter");
  1016. DECLARE_LEXER;
  1017. gnode_t *getter = NULL;
  1018. gnode_t *setter = NULL;
  1019. gtoken_s token_block = gravity_lexer_token(lexer);
  1020. while (gravity_lexer_peek(lexer) != TOK_OP_CLOSED_CURLYBRACE) {
  1021. const char *identifier = parse_identifier(parser);
  1022. if (!identifier) goto parse_error;
  1023. bool is_getter = false;
  1024. gtoken_s token = gravity_lexer_token(lexer);
  1025. gnode_r *params = NULL;
  1026. // getter case: does not have explicit parameters (only implicit self)
  1027. if (strcmp(identifier, GETTER_FUNCTION_NAME) == 0) {
  1028. is_getter = true;
  1029. params = gnode_array_create(); // add implicit SELF param
  1030. gnode_array_push(params, gnode_variable_create(NO_TOKEN, string_dup(SELF_PARAMETER_NAME), NULL, NULL, LAST_DECLARATION(), NULL));
  1031. }
  1032. // setter case: could have explicit parameters (otherwise value is implicit)
  1033. if (strcmp(identifier, SETTER_FUNCTION_NAME) == 0) {
  1034. is_getter = false;
  1035. // check if parameters are explicit
  1036. if (gravity_lexer_peek(lexer) == TOK_OP_OPEN_PARENTHESIS) {
  1037. parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
  1038. params = parse_optional_parameter_declaration(parser, false, NULL); // add implicit SELF
  1039. parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  1040. } else {
  1041. params = gnode_array_create(); // add implicit SELF and VALUE params
  1042. gnode_array_push(params, gnode_variable_create(NO_TOKEN, string_dup(SELF_PARAMETER_NAME), NULL, NULL, LAST_DECLARATION(), NULL));
  1043. gnode_array_push(params, gnode_variable_create(NO_TOKEN, string_dup(SETTER_PARAMETER_NAME), NULL, NULL, LAST_DECLARATION(), NULL));
  1044. }
  1045. }
  1046. mem_free(identifier);
  1047. // create getter/setter func declaration
  1048. gnode_t *f = gnode_function_decl_create(token, NULL, 0, 0, params, NULL, LAST_DECLARATION());
  1049. // set storage to var so I can identify f as a special getter/setter function
  1050. ((gnode_function_decl_t *)f)->storage = TOK_KEY_VAR;
  1051. // parse compound statement
  1052. PUSH_DECLARATION(f);
  1053. gnode_compound_stmt_t *compound = (gnode_compound_stmt_t*)parse_compound_statement(parser);
  1054. POP_DECLARATION();
  1055. // finish func setup
  1056. ((gnode_function_decl_t *)f)->block = compound;
  1057. // assign f to the right function
  1058. if (is_getter) getter = f; else setter = f;
  1059. }
  1060. gnode_r *functions = gnode_array_create();
  1061. gnode_array_push(functions, (getter) ? getter : NULL); // getter is at index 0
  1062. gnode_array_push(functions, (setter) ? setter : NULL); // setter is at index 1
  1063. // read current token to extract node total length
  1064. gtoken_s end_token = gravity_lexer_token(lexer);
  1065. // a compound node is used to capture getter and setter
  1066. return gnode_block_stat_create(NODE_COMPOUND_STAT, token_block, functions, LAST_DECLARATION(), end_token.position + end_token.length - token_block.position);
  1067. parse_error:
  1068. return NULL;
  1069. }
  1070. static gnode_t *parse_variable_declaration (gravity_parser_t *parser, bool isstatement, gtoken_t access_specifier, gtoken_t storage_specifier) {
  1071. DEBUG_PARSER("parse_variable_declaration");
  1072. DECLARE_LEXER;
  1073. gnode_r *decls = NULL;
  1074. gnode_t *decl = NULL;
  1075. gnode_t *expr = NULL;
  1076. const char *identifier = NULL;
  1077. const char *type_annotation = NULL;
  1078. gtoken_t type;
  1079. gtoken_t peek;
  1080. gtoken_s token, token2;
  1081. // access_specifier? storage_specifier? variable_declaration ';'
  1082. // variable_declaration: variable_declarator decl_item
  1083. // variable_declarator: 'const' | 'var'
  1084. // decl_item: (IDENTIFIER assignment?) (',' IDENTIFIER assignment?)*
  1085. // assignment
  1086. // sanity check on variable type
  1087. type = gravity_lexer_next(lexer);
  1088. if (!token_isvariable_declaration(type)) {
  1089. REPORT_ERROR(gravity_lexer_token(lexer), "VAR or CONST expected here but found %s.", token_name(type));
  1090. return NULL;
  1091. }
  1092. token = gravity_lexer_token(lexer);
  1093. // create node variable declaration
  1094. gnode_variable_decl_t *node = (gnode_variable_decl_t *) gnode_variable_decl_create(token, type, access_specifier, storage_specifier, NULL, LAST_DECLARATION());
  1095. // initialize node array
  1096. decls = gnode_array_create();
  1097. loop:
  1098. identifier = parse_identifier(parser);
  1099. if (!identifier) return NULL;
  1100. token2 = gravity_lexer_token(lexer);
  1101. // type annotation is optional so it can be NULL
  1102. type_annotation = parse_optional_type_annotation(parser);
  1103. DEBUG_PARSER("IDENTIFIER: %s %s", identifier, (type_annotation) ? type_annotation : "");
  1104. if (type_annotation && parser->delegate && parser->delegate->type_callback) {
  1105. parser->delegate->type_callback(&token2, type_annotation, parser->delegate->xdata);
  1106. }
  1107. // check for optional assignment or getter/setter declaration (ONLY = is ALLOWED here!)
  1108. expr = NULL;
  1109. bool is_computed = false;
  1110. peek = gravity_lexer_peek(lexer);
  1111. if (token_isvariable_assignment(peek)) {
  1112. gravity_lexer_next(lexer); // consume ASSIGNMENT
  1113. marray_push(uint16_t, parser->vdecl, 1);
  1114. expr = parse_expression(parser);
  1115. marray_pop(parser->vdecl);
  1116. } else if (peek == TOK_OP_OPEN_CURLYBRACE) {
  1117. gravity_lexer_next(lexer); // consume TOK_OP_OPEN_CURLYBRACE
  1118. expr = parse_getter_setter(parser);
  1119. parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
  1120. is_computed = true;
  1121. }
  1122. // sanity checks
  1123. // 1. CONST must be followed by an assignment expression ?
  1124. // 2. check if identifier is unique inside variable declarations
  1125. decl = gnode_variable_create(token2, identifier, type_annotation, expr, LAST_DECLARATION(), node);
  1126. if (decl) {
  1127. ((gnode_var_t *)decl)->iscomputed = is_computed;
  1128. gnode_array_push(decls, decl);
  1129. }
  1130. peek = gravity_lexer_peek(lexer);
  1131. if (peek == TOK_OP_COMMA) {
  1132. gravity_lexer_next(lexer); // consume TOK_OP_COMMA
  1133. goto loop;
  1134. }
  1135. // check and consume TOK_OP_SEMICOLON (ALWAYS required for assignments)
  1136. // Aaron: I would keep it consistent, even if it's not strictly required.
  1137. // Otherwise we end up with all of JavaScript's terrible ideas. ;-)
  1138. // So I would require the semicolon at the end of any assignment statement.
  1139. if (isstatement) parse_semicolon(parser);
  1140. // finish to setup declaration
  1141. node->decls = decls;
  1142. return (gnode_t *)node;
  1143. }
  1144. static gnode_t *parse_enum_declaration (gravity_parser_t *parser, gtoken_t access_specifier, gtoken_t storage_specifier) {
  1145. DEBUG_PARSER("parse_enum_declaration");
  1146. DECLARE_LEXER;
  1147. // enum is a bit different than the traditional C like enum statements
  1148. // in Gravity enum can contains String, Integer, Boolean and Float BUT cannot be mixed
  1149. // Integer case can also skip values and autoincrement will be applied
  1150. // String and Float must have a default value
  1151. // this code will take care of parsing and syntax check for the above restrictions
  1152. // in order to simplify node struct all the sematic checks are performed here
  1153. // even if it is not a best practice, I find a lot easier to perform all the checks
  1154. // directly into the parser
  1155. // parse_enum_declaration is the only reason why gravity_symboltable.h is included here
  1156. // checks are:
  1157. // 1: unique internal identifiers
  1158. // 2: if not INT then a default value is mandatory
  1159. // 3: all values must be literals
  1160. // 'enum' IDENTIFIER '{' enum_list '}' ';'
  1161. // enum_list: enum_list_item (',' enum_list_item)*
  1162. // enum_list_item: IDENTIFIER ('=' LITERAL)?
  1163. // NODE_ENUM_DECL
  1164. // optional scope already consumed
  1165. gtoken_t type = gravity_lexer_next(lexer);
  1166. gtoken_s token = gravity_lexer_token(lexer);
  1167. assert(type == TOK_KEY_ENUM);
  1168. // parse IDENTIFIER
  1169. const char *identifier = parse_identifier(parser);
  1170. DEBUG_PARSER("parse_enum_declaration %s", identifier);
  1171. // check and consume TOK_OP_OPEN_CURLYBRACE
  1172. if (parse_required(parser, TOK_OP_OPEN_CURLYBRACE) == false) return NULL;
  1173. symboltable_t *symtable = symboltable_create(SYMTABLE_TAG_ENUM); // enum symbol table (symtable is OK because order is not important inside an enum)
  1174. int64_t enum_autoint = 0; // autoincrement value (in case of INT enum)
  1175. uint32_t enum_counter = 0; // enum internal counter (first value (if any) determines enum type)
  1176. gliteral_t enum_type = LITERAL_INT; // enum type (default to int)
  1177. // create enum node
  1178. gnode_enum_decl_t *node = (gnode_enum_decl_t *)gnode_enum_decl_create(token, identifier, access_specifier, storage_specifier, symtable, LAST_DECLARATION());
  1179. while (1) {
  1180. // check for empty enum
  1181. if (gravity_lexer_peek(lexer) == TOK_OP_CLOSED_CURLYBRACE) break;
  1182. // identifier is mandatory here
  1183. const char *enum_id = NULL;
  1184. gtoken_t peek = gravity_lexer_peek(lexer);
  1185. gtoken_s enumid_token = NO_TOKEN;
  1186. if (peek == TOK_IDENTIFIER) {
  1187. enum_id = parse_identifier(parser);
  1188. enumid_token = gravity_lexer_token(lexer);
  1189. }
  1190. if (!enum_id) {
  1191. REPORT_ERROR(enumid_token, "Identifier expected here (found %s).", token_name(peek));
  1192. }
  1193. // peek next that can be only = or , or }
  1194. peek = gravity_lexer_peek(lexer);
  1195. gtoken_s enum_token = gravity_lexer_token(lexer);
  1196. if (!token_isvariable_assignment(peek) && (peek != TOK_OP_COMMA) && (peek != TOK_OP_CLOSED_CURLYBRACE)) {
  1197. REPORT_ERROR(enum_token, "Token %s not allowed here.", token_name(peek));
  1198. }
  1199. // check for assignment (ONLY = is ALLOWED here!)
  1200. // assignment is optional ONLY for LITERAL_TYPE_INT case
  1201. if ((!token_isvariable_assignment(peek)) && (enum_type != LITERAL_INT)) {
  1202. REPORT_ERROR(enum_token, "A default value is expected here (found %s).", token_name(peek));
  1203. }
  1204. // check for optional default value (optional only in LITERAL_INT case)
  1205. gnode_base_t *enum_value = NULL;
  1206. if (token_isvariable_assignment(peek)) {
  1207. gravity_lexer_next(lexer); // consume ASSIGNMENT
  1208. enum_value = (gnode_base_t *)parse_expression(parser);
  1209. }
  1210. if (enum_value) {
  1211. // make sure that value is a literal (or a unary expression like +num or -num)
  1212. gnode_literal_expr_t *enum_literal = NULL;
  1213. if (enum_value->base.tag == NODE_LITERAL_EXPR) {
  1214. enum_literal = (gnode_literal_expr_t *)enum_value;
  1215. } else if (enum_value->base.tag == NODE_UNARY_EXPR) {
  1216. gnode_unary_expr_t *unary = (gnode_unary_expr_t *)enum_value;
  1217. gnode_base_t *expr = (gnode_base_t *)unary->expr;
  1218. // sanity check on unary expression
  1219. if (expr->base.tag != NODE_LITERAL_EXPR) {
  1220. REPORT_ERROR(enum_token, "Literal value expected here.");
  1221. continue;
  1222. }
  1223. if ((unary->op != TOK_OP_SUB) && (unary->op != TOK_OP_ADD)) {
  1224. REPORT_ERROR(enum_token, "Only + or - allowed in enum value definition.");
  1225. continue;
  1226. }
  1227. enum_literal = (gnode_literal_expr_t *)expr;
  1228. if ((enum_literal->type != LITERAL_FLOAT) && (enum_literal->type != LITERAL_INT)) {
  1229. REPORT_ERROR(enum_token, "A number is expected after a + or - unary expression in an enum definition.");
  1230. continue;
  1231. }
  1232. if (unary->op == TOK_OP_SUB) {
  1233. gnode_t *temp = NULL;
  1234. if (enum_literal->type == LITERAL_FLOAT) {
  1235. //enum_literal->value.d = -enum_literal->value.d;
  1236. temp = gnode_literal_float_expr_create(enum_value->base.token, -enum_literal->value.d, LAST_DECLARATION());
  1237. }
  1238. else if (enum_literal->type == LITERAL_INT) {
  1239. //enum_literal->value.n64 = -enum_literal->value.n64;
  1240. temp = gnode_literal_int_expr_create(enum_value->base.token, -enum_literal->value.n64, LAST_DECLARATION());
  1241. }
  1242. if (temp) {
  1243. gnode_free((gnode_t *)enum_value);
  1244. enum_value = (gnode_base_t *)temp;
  1245. enum_literal = (gnode_literal_expr_t *)temp;
  1246. }
  1247. }
  1248. } else {
  1249. REPORT_ERROR(enum_token, "Literal value expected here.");
  1250. continue;
  1251. }
  1252. // first assignment (if any) determines enum type, otherwise default INT case is assumed
  1253. if (enum_counter == 0) {
  1254. if (enum_literal->type == LITERAL_STRING) enum_type = LITERAL_STRING;
  1255. else if (enum_literal->type == LITERAL_FLOAT) enum_type = LITERAL_FLOAT;
  1256. else if (enum_literal->type == LITERAL_BOOL) enum_type = LITERAL_BOOL;
  1257. }
  1258. // check if literal value conforms to enum type
  1259. if (enum_literal->type != enum_type) {
  1260. REPORT_ERROR(enum_token, "Literal value of type %s expected here.", token_literal_name(enum_type));
  1261. }
  1262. // update enum_autoint value to next value
  1263. if (enum_literal->type == LITERAL_INT) {
  1264. enum_autoint = enum_literal->value.n64 + 1;
  1265. }
  1266. } else {
  1267. enum_value = (gnode_base_t *)gnode_literal_int_expr_create(NO_TOKEN, enum_autoint, LAST_DECLARATION());
  1268. ++enum_autoint;
  1269. }
  1270. // update internal enum counter
  1271. ++enum_counter;
  1272. // enum identifier could be NULL due to an already reported error
  1273. if (enum_id) {
  1274. if (!symboltable_insert(symtable, enum_id, (void *)enum_value)) {
  1275. REPORT_ERROR(enumid_token, "Identifier %s redeclared.", enum_id);
  1276. gnode_free((gnode_t *)enum_value); // free value here because it has not beed saved into symbol table
  1277. }
  1278. mem_free(enum_id); // because key is duplicated inside internal hash table
  1279. }
  1280. peek = gravity_lexer_peek(lexer);
  1281. if (peek != TOK_OP_COMMA) break;
  1282. // consume TOK_OP_COMMA and continue loop
  1283. gravity_lexer_next(lexer);
  1284. }
  1285. // check and consume TOK_OP_CLOSED_CURLYBRACE
  1286. parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
  1287. // consume semicolon
  1288. parse_semicolon(parser);
  1289. // check for empty enum (not allowed)
  1290. if (enum_counter == 0) {
  1291. REPORT_ERROR(token, "Empty enum %s not allowed.", identifier);
  1292. }
  1293. if (IS_FUNCTION_ENCLOSED()) return local_store_declaration(parser, identifier, NULL, access_specifier, storage_specifier, (gnode_t *)node);
  1294. return (gnode_t *)node;
  1295. }
  1296. static gnode_t *parse_module_declaration (gravity_parser_t *parser, gtoken_t access_specifier, gtoken_t storage_specifier) {
  1297. DEBUG_PARSER("parse_module_declaration");
  1298. // module parsed but not yet supported
  1299. // 'module' IDENTIFIER '{' declaration_statement* '}' ';'
  1300. // optional scope already consumed
  1301. DECLARE_LEXER;
  1302. gtoken_t type = gravity_lexer_next(lexer);
  1303. gtoken_s token = gravity_lexer_token(lexer);
  1304. assert(type == TOK_KEY_MODULE);
  1305. // parse IDENTIFIER
  1306. const char *identifier = parse_identifier(parser);
  1307. DEBUG_PARSER("parse_module_declaration %s", identifier);
  1308. #pragma unused(identifier)
  1309. // parse optional curly brace
  1310. bool curly_brace = parse_optional(parser, TOK_OP_OPEN_CURLYBRACE);
  1311. // create array of declarations nodes
  1312. gnode_r *declarations = gnode_array_create();
  1313. // create module node
  1314. gnode_t *node = NULL;//gnode_module_decl_create(token, identifier, access_specifier, storage_specifier, declarations, meta, LAST_DECLARATION());
  1315. #pragma unused(access_specifier,storage_specifier)
  1316. while (token_isdeclaration_statement(gravity_lexer_peek(lexer))) {
  1317. gnode_t *decl = parse_declaration_statement(parser);
  1318. if (decl) gnode_array_push(declarations, decl);
  1319. }
  1320. // check and consume TOK_OP_CLOSED_CURLYBRACE
  1321. if (curly_brace) parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
  1322. parse_semicolon(parser);
  1323. REPORT_ERROR(token, "Module declarations not yet supported.");
  1324. return node;
  1325. }
  1326. static gnode_t *parse_event_declaration (gravity_parser_t *parser, gtoken_t access_specifier, gtoken_t storage_specifier) {
  1327. #pragma unused(parser, access_specifier, storage_specifier)
  1328. // 'event' IDENTIFIER '(' parameter_declaration_clause? ')' ';'
  1329. // NODE_EVENT_DECL
  1330. DECLARE_LEXER;
  1331. gtoken_t type = gravity_lexer_next(lexer);
  1332. gtoken_s token = gravity_lexer_token(lexer);
  1333. assert(type == TOK_KEY_EVENT);
  1334. REPORT_ERROR(token, "Event declarations not yet supported.");
  1335. return NULL;
  1336. }
  1337. static gnode_t *parse_function_declaration (gravity_parser_t *parser, gtoken_t access_specifier, gtoken_t storage_specifier) {
  1338. // convert a function declaration within another function to a local variable assignment
  1339. // for example:
  1340. //
  1341. // func foo() {
  1342. // func bar() {...}
  1343. // }
  1344. //
  1345. // is converter to:
  1346. //
  1347. // func foo() {
  1348. // var bar = func() {...}
  1349. // }
  1350. //
  1351. // conversion is performed inside the parser
  1352. // so next semantic checks can perform
  1353. // identifier uniqueness checks
  1354. gnode_t *node = parse_function(parser, true, access_specifier, storage_specifier);
  1355. if (IS_FUNCTION_ENCLOSED()) {
  1356. gnode_function_decl_t *func = (gnode_function_decl_t *)node;
  1357. func->is_closure = true;
  1358. return local_store_declaration(parser, func->identifier, NULL, access_specifier, storage_specifier, node);
  1359. }
  1360. return node;
  1361. }
  1362. static gnode_t *parse_id (gravity_parser_t *parser) {
  1363. DECLARE_LEXER;
  1364. const char *identifier1 = NULL;
  1365. const char *identifier2 = NULL;
  1366. gtoken_t peek;
  1367. gtoken_s token;
  1368. // IDENTIFIER | (IDENTIFIER)('.' IDENTIFIER)
  1369. DEBUG_PARSER("parse_id");
  1370. identifier1 = parse_identifier(parser);
  1371. token = gravity_lexer_token(lexer);
  1372. peek = gravity_lexer_peek(lexer);
  1373. if (peek == TOK_OP_DOT) {
  1374. gravity_lexer_next(lexer); // consume TOK_OP_DOT
  1375. identifier2 = parse_identifier(parser);
  1376. }
  1377. DEBUG_PARSER("ID: %s %s", identifier1, (identifier2) ? identifier2 : "");
  1378. return gnode_identifier_expr_create(token, identifier1, identifier2, LAST_DECLARATION());
  1379. }
  1380. static gnode_r *parse_protocols (gravity_parser_t *parser) {
  1381. DECLARE_LEXER;
  1382. gtoken_t peek;
  1383. gnode_t *node = NULL;
  1384. gnode_r *list = NULL;
  1385. // (id) (',' id)*
  1386. peek = gravity_lexer_peek(lexer);
  1387. if (peek == TOK_OP_GREATER) return NULL; // just an empty protocols implementation statement
  1388. list = gnode_array_create();
  1389. loop:
  1390. if (!token_isidentifier(peek)) goto abort;
  1391. node = parse_id(parser);
  1392. if (node) gnode_array_push(list, node);
  1393. peek = gravity_lexer_peek(lexer);
  1394. if (peek == TOK_OP_COMMA) {
  1395. gravity_lexer_next(lexer); // consume TOK_OP_COMMA
  1396. goto loop;
  1397. }
  1398. return list;
  1399. abort:
  1400. if (list) gnode_array_free(list);
  1401. return NULL;
  1402. }
  1403. static gnode_t *parse_class_declaration (gravity_parser_t *parser, gtoken_t access_specifier, gtoken_t storage_specifier) {
  1404. DEBUG_PARSER("parse_class_declaration");
  1405. DECLARE_LEXER;
  1406. // access_specifier? storage_specifier? 'class' IDENTIFIER class_superclass? class_protocols? '{' declaration_statement* '}' ';'
  1407. // class_superclass: (':') id
  1408. // class_protocols: '<' (id) (',' id)* '>'
  1409. // optional scope already consumed (when here I am sure type is TOK_KEY_CLASS or TOK_KEY_STRUCT)
  1410. gtoken_t type = gravity_lexer_next(lexer);
  1411. gtoken_s token = gravity_lexer_token(lexer);
  1412. bool is_struct = (type == TOK_KEY_STRUCT);
  1413. // parse IDENTIFIER
  1414. const char *identifier = parse_identifier(parser);
  1415. // check for optional superclass
  1416. gnode_t *super = NULL;
  1417. gnode_r *protocols = NULL;
  1418. gtoken_t peek = gravity_lexer_peek(lexer);
  1419. if (peek == TOK_OP_COLON) {
  1420. gravity_lexer_next(lexer); // consume TOK_OP_COLON
  1421. super = parse_id(parser);
  1422. }
  1423. // check for optional protocols (not supported in this version)
  1424. peek = gravity_lexer_peek(lexer);
  1425. if (peek == TOK_OP_LESS) {
  1426. gravity_lexer_next(lexer); // consume '<'
  1427. protocols = parse_protocols(parser);
  1428. parse_required(parser, TOK_OP_GREATER); // consume '>'
  1429. }
  1430. // check and consume TOK_OP_OPEN_CURLYBRACE
  1431. if (storage_specifier != TOK_KEY_EXTERN) parse_required(parser, TOK_OP_OPEN_CURLYBRACE);
  1432. gnode_r *declarations = gnode_array_create();
  1433. // if class is declared inside another class then a hidden implicit private "outer" instance var at index 0
  1434. // is automatically added
  1435. if (IS_CLASS_ENCLOSED()) {
  1436. gnode_r *decls = gnode_array_create();
  1437. gnode_t *outer_var = gnode_variable_create(NO_TOKEN, string_dup(OUTER_IVAR_NAME), NULL, NULL, LAST_DECLARATION(), NULL);
  1438. gnode_array_push(decls, outer_var);
  1439. gnode_t *outer_decl = gnode_variable_decl_create(NO_TOKEN, TOK_KEY_VAR, TOK_KEY_PRIVATE, 0, decls, LAST_DECLARATION());
  1440. gnode_array_push(declarations, outer_decl);
  1441. }
  1442. // create class declaration node
  1443. gnode_class_decl_t *node = (gnode_class_decl_t*) gnode_class_decl_create(token, identifier, access_specifier, storage_specifier, super, protocols, NULL, is_struct, LAST_DECLARATION());
  1444. if (storage_specifier != TOK_KEY_EXTERN) {
  1445. PUSH_DECLARATION(node);
  1446. peek = gravity_lexer_peek(lexer);
  1447. while (token_isdeclaration_statement(peek) || token_ismacro(peek)) {
  1448. gnode_t *decl = parse_declaration_statement(parser);
  1449. if (decl) gnode_array_push(declarations, decl_check_access_specifier(decl));
  1450. peek = gravity_lexer_peek(lexer);
  1451. }
  1452. POP_DECLARATION();
  1453. }
  1454. // check and consume TOK_OP_CLOSED_CURLYBRACE
  1455. if (storage_specifier != TOK_KEY_EXTERN) parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
  1456. // to check
  1457. parse_semicolon(parser);
  1458. // finish setup node class
  1459. node->decls = declarations;
  1460. const char *class_manifest_type = gravity_class_class->identifier;
  1461. if (IS_FUNCTION_ENCLOSED()) return local_store_declaration(parser, identifier, string_dup(class_manifest_type), access_specifier, storage_specifier, (gnode_t *)node);
  1462. return (gnode_t *)node;
  1463. }
  1464. static gnode_r *parse_optional_parameter_declaration (gravity_parser_t *parser, bool is_implicit, bool *has_default_values) {
  1465. DEBUG_PARSER("parse_parameter_declaration");
  1466. DECLARE_LEXER;
  1467. gtoken_s token = NO_TOKEN;
  1468. gnode_t *node = NULL;
  1469. gnode_t *default_value = NULL;
  1470. const char *identifier = NULL;
  1471. const char *type_annotation = NULL;
  1472. // (IDENTIFIER type_annotation?) (',' type_annotation)*
  1473. // type_annotation: ':' identifier
  1474. gnode_r *params = gnode_array_create();
  1475. assert(params);
  1476. // check if implicit self parameter must be added
  1477. // was if (IS_CLASS_ENCLOSED()*/) { ... add SELF PARAMETER ...}
  1478. // but we decided to ALWAYS pass SELF because it simplified cases
  1479. // like c1().p1.p1.p1(1234);
  1480. // ALWAYS add an implicit SELF parameter
  1481. // string_dup mandatory here because when the node will be freed
  1482. // memory for the identifier will be deallocated
  1483. node = gnode_variable_create(token, string_dup(SELF_PARAMETER_NAME), type_annotation, NULL, LAST_DECLARATION(), NULL);
  1484. DEBUG_PARSER("PARAMETER: %s %s", SELF_PARAMETER_NAME, (type_annotation) ? type_annotation : "");
  1485. if (node) gnode_array_push(params, node);
  1486. if (is_implicit) return params;
  1487. // parameter declaration clause is ALWAYS optional
  1488. gtoken_t peek = gravity_lexer_peek(lexer);
  1489. if (peek == TOK_OP_CLOSED_PARENTHESIS) return params;
  1490. // so there is at leat one explicit parameter
  1491. loop:
  1492. // initialize variables
  1493. type_annotation = NULL;
  1494. // parse identifier
  1495. identifier = parse_identifier(parser);
  1496. token = gravity_lexer_token(lexer);
  1497. // parse optional type annotation
  1498. type_annotation = parse_optional_type_annotation(parser);
  1499. if (type_annotation && parser->delegate && parser->delegate->type_callback) {
  1500. parser->delegate->type_callback(&token, type_annotation, parser->delegate->xdata);
  1501. }
  1502. // parse optional default LITERAL value
  1503. default_value = parse_optional_default_value(parser);
  1504. if (default_value && has_default_values) *has_default_values = true;
  1505. // fill parameters array with the new node
  1506. node = gnode_variable_create(token, identifier, type_annotation, default_value, LAST_DECLARATION(), NULL);
  1507. if (node) gnode_array_push(params, node);
  1508. DEBUG_PARSER("PARAMETER: %s %s", identifier, (type_annotation) ? type_annotation : "");
  1509. // check for optional comma in order to decide
  1510. // if the loop should continue or not
  1511. peek = gravity_lexer_peek(lexer);
  1512. if (peek == TOK_OP_COMMA) {
  1513. gravity_lexer_next(lexer); // consume TOK_OP_COMMA
  1514. goto loop;
  1515. }
  1516. return params;
  1517. }
  1518. // MARK: - Macro -
  1519. typedef enum {
  1520. UNITTEST_NONE,
  1521. UNITTEST_NAME,
  1522. UNITTEST_ERROR,
  1523. UNITTEST_RESULT,
  1524. UNITTEST_ERROR_ROW,
  1525. UNITTEST_ERROR_COL,
  1526. UNITTEST_NOTE
  1527. } unittest_t;
  1528. static unittest_t parse_unittest_identifier (const char *identifier) {
  1529. if (string_cmp(identifier, "name") == 0) return UNITTEST_NAME;
  1530. if (string_cmp(identifier, "note") == 0) return UNITTEST_NOTE;
  1531. if (string_cmp(identifier, "error") == 0) return UNITTEST_ERROR;
  1532. if (string_cmp(identifier, "error_row") == 0) return UNITTEST_ERROR_ROW;
  1533. if (string_cmp(identifier, "error_col") == 0) return UNITTEST_ERROR_COL;
  1534. if (string_cmp(identifier, "result") == 0) return UNITTEST_RESULT;
  1535. return UNITTEST_NONE;
  1536. }
  1537. static gnode_t *parse_unittest_macro (gravity_parser_t *parser) {
  1538. DEBUG_PARSER("parse_unittest_macro");
  1539. DECLARE_LEXER;
  1540. // #unittest {
  1541. // name: "Unit test name";
  1542. // note: "Some notes here";
  1543. // error: NONE, SYNTAX, RUNTIME, WARNING;
  1544. // error_row: number;
  1545. // error_col: number;
  1546. // result: LITERAL;
  1547. // '}' ';'?
  1548. // sanity check: unittest macro must be root of the document
  1549. // 1. parse_statement
  1550. // 2. parse_macro_statement
  1551. if (marray_size(*parser->statements) != 2) {
  1552. REPORT_ERROR(gravity_lexer_token(lexer), "#unittest macro cannot be embedded in a statement (it must be the root of the document).");
  1553. return NULL;
  1554. }
  1555. gnode_literal_expr_t *name_node = NULL;
  1556. gnode_literal_expr_t *note_node = NULL;
  1557. gnode_identifier_expr_t *err_node = NULL;
  1558. gnode_literal_expr_t *row_node = NULL;
  1559. gnode_literal_expr_t *col_node = NULL;
  1560. gnode_literal_expr_t *value_node = NULL;
  1561. parse_required(parser, TOK_OP_OPEN_CURLYBRACE);
  1562. while (gravity_lexer_peek(lexer) != TOK_OP_CLOSED_CURLYBRACE) {
  1563. const char *id = parse_identifier(parser);
  1564. if (id == NULL) goto handle_error;
  1565. parse_required(parser, TOK_OP_COLON);
  1566. unittest_t type = parse_unittest_identifier(id);
  1567. mem_free(id);
  1568. if (type == UNITTEST_NAME) {
  1569. name_node = (gnode_literal_expr_t *)parse_literal_expression(parser);
  1570. if (name_node == NULL) goto handle_error;
  1571. }
  1572. else if (type == UNITTEST_NOTE) {
  1573. note_node = (gnode_literal_expr_t *)parse_literal_expression(parser);
  1574. if (note_node == NULL) goto handle_error;
  1575. }
  1576. else if (type == UNITTEST_ERROR) {
  1577. err_node = (gnode_identifier_expr_t *)parse_identifier_expression(parser);
  1578. if (err_node == NULL) goto handle_error;
  1579. }
  1580. else if (type == UNITTEST_ERROR_ROW) {
  1581. row_node = (gnode_literal_expr_t *)parse_literal_expression(parser);
  1582. if (row_node == NULL) goto handle_error;
  1583. }
  1584. else if (type == UNITTEST_ERROR_COL) {
  1585. col_node = (gnode_literal_expr_t *)parse_literal_expression(parser);
  1586. if (col_node == NULL) goto handle_error;
  1587. }
  1588. else if (type == UNITTEST_RESULT) {
  1589. gtoken_t op = TOK_EOF;
  1590. gtoken_t peek = gravity_lexer_peek(lexer);
  1591. // check if peek is a + or - sign
  1592. if ((peek == TOK_OP_SUB) || (peek == TOK_OP_ADD))
  1593. op = gravity_lexer_next(lexer);
  1594. else if (peek == TOK_KEY_NULL) {
  1595. // an expected return value can now be keyword NULL
  1596. gravity_lexer_next(lexer); // consume NULL keyword
  1597. value_node = NULL;
  1598. goto handle_continue;
  1599. }
  1600. value_node = (gnode_literal_expr_t *)parse_literal_expression(parser);
  1601. if (value_node == NULL) goto handle_error;
  1602. // if a negative sign has been parsed then manually fix the literal expression (if it is a number)
  1603. if (op == TOK_OP_SUB) {
  1604. if (value_node->type == LITERAL_INT) value_node->value.n64 = -value_node->value.n64;
  1605. else if (value_node->type == LITERAL_FLOAT) value_node->value.d = -value_node->value.d;
  1606. }
  1607. }
  1608. else {
  1609. REPORT_ERROR(gravity_lexer_token(lexer), "Unknown token found in #unittest declaration.");
  1610. goto handle_error;
  1611. }
  1612. handle_continue:
  1613. parse_semicolon(parser);
  1614. }
  1615. parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
  1616. parse_semicolon(parser);
  1617. // decode unit array and report error/unittest
  1618. // unit test name max length is 1024
  1619. const char *description = NULL;
  1620. const char *note = NULL;
  1621. char buffer[1024];
  1622. char buffer2[1024];
  1623. error_type_t expected_error = GRAVITY_ERROR_NONE;
  1624. gravity_value_t expected_value = VALUE_FROM_NULL;
  1625. int32_t expected_nrow = -1;
  1626. int32_t expected_ncol = -1;
  1627. // unittest name should be a literal string
  1628. if ((name_node) && (name_node->type == LITERAL_STRING)) {
  1629. // no more C strings in AST so we need a static buffer
  1630. snprintf(buffer, sizeof(buffer), "%.*s", name_node->len, name_node->value.str);
  1631. description = buffer;
  1632. }
  1633. // note (optional) should be a literal string
  1634. if ((note_node) && (note_node->type == LITERAL_STRING)) {
  1635. // no more C strings in AST so we need a static buffer
  1636. snprintf(buffer2, sizeof(buffer2), "%.*s", note_node->len, note_node->value.str);
  1637. note = buffer2;
  1638. }
  1639. // decode expected error: NONE, SYNTAX, SEMANTIC, RUNTIME, WARNING
  1640. if (err_node) {
  1641. if (string_cmp(err_node->value, "NONE") == 0)
  1642. expected_error = GRAVITY_ERROR_NONE;
  1643. else if (string_cmp(err_node->value, "SYNTAX") == 0)
  1644. expected_error = GRAVITY_ERROR_SYNTAX;
  1645. else if (string_cmp(err_node->value, "SEMANTIC") == 0)
  1646. expected_error = GRAVITY_ERROR_SEMANTIC;
  1647. else if (string_cmp(err_node->value, "RUNTIME") == 0)
  1648. expected_error = GRAVITY_ERROR_RUNTIME;
  1649. else if (string_cmp(err_node->value, "WARNING") == 0)
  1650. expected_error = GRAVITY_WARNING;
  1651. }
  1652. // decode error line/col
  1653. if ((row_node) && (row_node->type == LITERAL_INT)) {
  1654. expected_nrow = (int32_t)row_node->value.n64;
  1655. }
  1656. if ((col_node) && (col_node->type == LITERAL_INT)) {
  1657. expected_ncol = (int32_t)col_node->value.n64;
  1658. }
  1659. // decode unittest expected result
  1660. if (value_node) {
  1661. if (value_node->type == LITERAL_STRING)
  1662. expected_value = VALUE_FROM_CSTRING(NULL, value_node->value.str);
  1663. else if (value_node->type == LITERAL_INT)
  1664. expected_value = VALUE_FROM_INT((gravity_int_t)value_node->value.n64);
  1665. else if (value_node->type == LITERAL_FLOAT)
  1666. expected_value = VALUE_FROM_FLOAT((gravity_float_t)value_node->value.d);
  1667. else if (value_node->type == LITERAL_BOOL)
  1668. expected_value = (value_node->value.n64) ? VALUE_FROM_TRUE : VALUE_FROM_FALSE;
  1669. }
  1670. // report unittest to delegate
  1671. if ((parser->delegate) && (parser->delegate->unittest_callback)) {
  1672. gravity_unittest_callback unittest_cb = parser->delegate->unittest_callback;
  1673. unittest_cb(NULL, expected_error, description, note, expected_value, expected_nrow, expected_ncol, parser->delegate->xdata);
  1674. } else {
  1675. // it was unit test responsability to free expected_value but if no unit test delegate is set I should take care of it
  1676. gravity_value_free(NULL, expected_value);
  1677. }
  1678. // free temp nodes
  1679. if (name_node) gnode_free((gnode_t*)name_node);
  1680. if (note_node) gnode_free((gnode_t*)note_node);
  1681. if (err_node) gnode_free((gnode_t*)err_node);
  1682. if (row_node) gnode_free((gnode_t*)row_node);
  1683. if (col_node) gnode_free((gnode_t*)col_node);
  1684. if (value_node) gnode_free((gnode_t*)value_node);
  1685. // always return NULL
  1686. return NULL;
  1687. handle_error:
  1688. parse_skip_until(parser, TOK_OP_CLOSED_CURLYBRACE);
  1689. return NULL;
  1690. }
  1691. static gnode_t *parse_include_macro (gravity_parser_t *parser) {
  1692. DEBUG_PARSER("parse_include_macro");
  1693. DECLARE_LEXER;
  1694. // process filename (can be an identifier or a literal string)
  1695. // only literals are supported in this version
  1696. gtoken_t type;
  1697. gtoken_s token;
  1698. const char *module_name;
  1699. gravity_lexer_t *newlexer;
  1700. loop:
  1701. newlexer = NULL;
  1702. type = gravity_lexer_next(lexer);
  1703. token = gravity_lexer_token(lexer);
  1704. // check if it is a string token
  1705. if (type != TOK_STRING) {
  1706. REPORT_ERROR(token, "Expected file name but found %s.", token_name(type));
  1707. return NULL;
  1708. }
  1709. // check pre-requisites
  1710. if ((!parser->delegate) || (!parser->delegate->loadfile_callback)) {
  1711. REPORT_ERROR(gravity_lexer_token(lexer), "Unable to load file because no loadfile callback registered in delegate.");
  1712. return NULL;
  1713. }
  1714. // parse string
  1715. module_name = cstring_from_token(parser, token);
  1716. size_t size = 0;
  1717. uint32_t fileid = 0;
  1718. // module_name is a filename and it is used by lexer to store filename into tokens
  1719. // tokens are then stored inside AST nodes in order to locate errors into source code
  1720. // AST can live a lot longer than both lexer and parser so we need a way to persistent
  1721. // store these chuncks of memory
  1722. bool is_static = false;
  1723. const char *source = parser->delegate->loadfile_callback(module_name, &size, &fileid, parser->delegate->xdata, &is_static);
  1724. if (source) newlexer = gravity_lexer_create(source, size, fileid, is_static);
  1725. if (newlexer) {
  1726. // push new lexer into lexer stack
  1727. marray_push(gravity_lexer_t*, *parser->lexer, newlexer);
  1728. } else {
  1729. REPORT_ERROR(token, "Unable to load file %s.", module_name);
  1730. }
  1731. // cleanup memory
  1732. if (module_name) mem_free(module_name);
  1733. // check for optional comma
  1734. if (gravity_lexer_peek(lexer) == TOK_OP_COMMA) {
  1735. gravity_lexer_next(lexer); // consume TOK_OP_COMMA
  1736. goto loop;
  1737. }
  1738. // parse semicolon
  1739. parse_semicolon(parser);
  1740. return NULL;
  1741. }
  1742. // MARK: - Statements -
  1743. static gnode_t *parse_label_statement (gravity_parser_t *parser) {
  1744. DEBUG_PARSER("parse_label_statement");
  1745. // 'case' expression ':' statement
  1746. // 'default' ':' statement
  1747. DECLARE_LEXER;
  1748. gtoken_t type = gravity_lexer_next(lexer);
  1749. gtoken_s token = gravity_lexer_token(lexer);
  1750. assert((type == TOK_KEY_CASE) || (type == TOK_KEY_DEFAULT));
  1751. // case specific expression
  1752. gnode_t *expr = NULL;
  1753. if (type == TOK_KEY_CASE) {
  1754. expr = parse_expression(parser);
  1755. }
  1756. // common part
  1757. parse_required(parser, TOK_OP_COLON);
  1758. gnode_t *stmt = parse_statement(parser);
  1759. return gnode_label_stat_create(token, expr, stmt, LAST_DECLARATION());
  1760. }
  1761. static gnode_t *parse_flow_statement (gravity_parser_t *parser) {
  1762. DEBUG_PARSER("parse_flow_statement");
  1763. // 'if' '(' expression ')' statement ('else' statement)?
  1764. // 'switch' '(' expression ')' statement
  1765. DECLARE_LEXER;
  1766. gtoken_t type = gravity_lexer_next(lexer);
  1767. gtoken_s token = gravity_lexer_token(lexer);
  1768. assert((type == TOK_KEY_IF) || (type == TOK_KEY_SWITCH));
  1769. // check required TOK_OP_OPEN_PARENTHESIS
  1770. parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
  1771. // parse common expression
  1772. gnode_t *cond = parse_expression(parser);
  1773. // check and consume TOK_OP_CLOSED_PARENTHESIS
  1774. parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  1775. // parse common statement
  1776. gnode_t *stmt1 = parse_statement(parser);
  1777. gnode_t *stmt2 = NULL;
  1778. if ((type == TOK_KEY_IF) && (gravity_lexer_peek(lexer) == TOK_KEY_ELSE)) {
  1779. gravity_lexer_next(lexer); // consume TOK_KEY_ELSE
  1780. stmt2 = parse_statement(parser);
  1781. }
  1782. // read current token to extract node total length
  1783. gtoken_s end_token = gravity_lexer_token(lexer);
  1784. return gnode_flow_stat_create(token, cond, stmt1, stmt2, LAST_DECLARATION(), end_token.position + end_token.length - token.position);
  1785. }
  1786. static gnode_t *parse_loop_statement (gravity_parser_t *parser) {
  1787. DEBUG_PARSER("parse_loop_statement");
  1788. // 'while' '(' expression ')' statement
  1789. // 'repeat' statement 'while' '(' expression ')' ';'
  1790. // 'for' '(' condition 'in' expression ')' statement
  1791. DECLARE_LEXER;
  1792. gnode_t *cond = NULL;
  1793. gnode_t *stmt = NULL;
  1794. gnode_t *expr = NULL;
  1795. gtoken_t type = gravity_lexer_next(lexer);
  1796. gtoken_s token = gravity_lexer_token(lexer);
  1797. gtoken_s end_token;
  1798. assert((type == TOK_KEY_WHILE) || (type == TOK_KEY_REPEAT) || (type == TOK_KEY_FOR));
  1799. // 'while' '(' expression ')' statement
  1800. if (type == TOK_KEY_WHILE) {
  1801. // check optional TOK_OP_OPEN_PARENTHESIS
  1802. bool is_parenthesize = parse_optional(parser, TOK_OP_OPEN_PARENTHESIS);
  1803. // parse while condition
  1804. cond = parse_expression(parser);
  1805. // check and consume TOK_OP_CLOSED_PARENTHESIS
  1806. if (is_parenthesize) parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  1807. // parse while statement
  1808. stmt = parse_statement(parser);
  1809. goto return_node;
  1810. }
  1811. // 'repeat' statement 'while' '(' expression ')' ';'
  1812. if (type == TOK_KEY_REPEAT) {
  1813. // parse repeat statement
  1814. stmt = parse_statement(parser);
  1815. // check and consume TOK_KEY_WHILE
  1816. parse_required(parser, TOK_KEY_WHILE);
  1817. // check optional TOK_OP_OPEN_PARENTHESIS
  1818. bool is_parenthesize = parse_optional(parser, TOK_OP_OPEN_PARENTHESIS);
  1819. // parse while expression
  1820. expr = parse_expression(parser);
  1821. // check and consume TOK_OP_CLOSED_PARENTHESIS
  1822. if (is_parenthesize) parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  1823. // semicolon
  1824. parse_semicolon(parser);
  1825. goto return_node;
  1826. }
  1827. // 'for' '(' condition 'in' expression ')' statement
  1828. if (type == TOK_KEY_FOR) {
  1829. // check optional TOK_OP_OPEN_PARENTHESIS
  1830. bool is_parenthesize = parse_optional(parser, TOK_OP_OPEN_PARENTHESIS);
  1831. // parse condition (means parse variable declaration or expression)
  1832. if (token_isvariable_declaration(gravity_lexer_peek(lexer))) {
  1833. cond = parse_variable_declaration(parser, false, 0, 0);
  1834. } else {
  1835. cond = parse_expression(parser);
  1836. }
  1837. // check and consume TOK_KEY_IN
  1838. parse_required(parser, TOK_KEY_IN);
  1839. // parse expression
  1840. expr = parse_expression(parser);
  1841. // check and consume TOK_OP_CLOSED_PARENTHESIS
  1842. if (is_parenthesize) parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
  1843. // parse for statement
  1844. stmt = parse_statement(parser);
  1845. }
  1846. return_node:
  1847. // read current token to extract node total length
  1848. end_token = gravity_lexer_token(lexer);
  1849. // return loop node
  1850. return gnode_loop_stat_create(token, cond, stmt, expr, LAST_DECLARATION(), end_token.position + end_token.length - token.position);
  1851. }
  1852. static gnode_t *parse_jump_statement (gravity_parser_t *parser) {
  1853. DEBUG_PARSER("parse_jump_statement");
  1854. // 'break' ';'
  1855. // 'continue' ';'
  1856. // 'return' expression? ';'
  1857. DECLARE_LEXER;
  1858. gtoken_t type = gravity_lexer_next(lexer);
  1859. gtoken_s token = gravity_lexer_token(lexer);
  1860. assert((type == TOK_KEY_BREAK) || (type == TOK_KEY_CONTINUE) || (type == TOK_KEY_RETURN));
  1861. gnode_t *expr = NULL;
  1862. if ((type == TOK_KEY_RETURN) && (gravity_lexer_peek(lexer) != TOK_OP_SEMICOLON) && (gravity_lexer_peek(lexer) != TOK_OP_CLOSED_CURLYBRACE)) {
  1863. expr = parse_expression(parser);
  1864. }
  1865. parse_semicolon(parser);
  1866. return gnode_jump_stat_create(token, expr, LAST_DECLARATION());
  1867. }
  1868. static gnode_t *parse_compound_statement (gravity_parser_t *parser) {
  1869. DEBUG_PARSER("parse_compound_statement");
  1870. // '{' (statement+)? '}'
  1871. // check and consume TOK_OP_OPEN_CURLYBRACE
  1872. parse_required(parser, TOK_OP_OPEN_CURLYBRACE);
  1873. DECLARE_LEXER;
  1874. gtoken_s token = gravity_lexer_token(lexer);
  1875. gnode_r *stmts = gnode_array_create();
  1876. while (token_isstatement(gravity_lexer_peek(lexer))) {
  1877. if (++parser->depth > MAX_RECURSION_DEPTH) {
  1878. REPORT_ERROR(gravity_lexer_token(lexer), "Maximum statement recursion depth reached.");
  1879. return NULL;
  1880. }
  1881. gnode_t *node = parse_statement(parser);
  1882. if (node) gnode_array_push(stmts, node);
  1883. --parser->depth;
  1884. }
  1885. // check and consume TOK_OP_CLOSED_CURLYBRACE
  1886. parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
  1887. // read current token to extract node total length
  1888. gtoken_s end_token = gravity_lexer_token(lexer);
  1889. return gnode_block_stat_create(NODE_COMPOUND_STAT, token, stmts, LAST_DECLARATION(), end_token.position + end_token.length - token.position);
  1890. }
  1891. static gnode_t *parse_empty_statement (gravity_parser_t *parser) {
  1892. DEBUG_PARSER("parse_empty_statement");
  1893. // ;
  1894. DECLARE_LEXER;
  1895. gravity_lexer_next(lexer);
  1896. gtoken_s token = gravity_lexer_token(lexer);
  1897. return gnode_empty_stat_create(token, LAST_DECLARATION());
  1898. }
  1899. static gnode_t *parse_declaration_statement (gravity_parser_t *parser) {
  1900. DEBUG_PARSER("parse_declaration_statement");
  1901. DECLARE_LEXER;
  1902. gtoken_t peek = gravity_lexer_peek(lexer);
  1903. gtoken_t access_specifier = 0; // 0 means no access specifier set
  1904. gtoken_t storage_specifier = 0; // 0 means no storage specifier set
  1905. // check if an access specifier is set
  1906. if (token_isaccess_specifier(peek)) {
  1907. access_specifier = gravity_lexer_next(lexer);
  1908. peek = gravity_lexer_peek(lexer);
  1909. }
  1910. // check if a storage specifier is set
  1911. if (token_isstorage_specifier(peek)) {
  1912. storage_specifier = gravity_lexer_next(lexer);
  1913. peek = gravity_lexer_peek(lexer);
  1914. }
  1915. // it is a syntax error to specify an access or storage specifier followed by an empty declaration
  1916. if ((peek == TOK_OP_SEMICOLON) && ((access_specifier) || (storage_specifier))) {
  1917. REPORT_ERROR(gravity_lexer_token(lexer), "Access or storage specifier cannot be used here.");
  1918. }
  1919. switch (peek) {
  1920. case TOK_MACRO: return parse_macro_statement(parser);
  1921. case TOK_KEY_FUNC: return parse_function_declaration(parser, access_specifier, storage_specifier);
  1922. case TOK_KEY_ENUM: return parse_enum_declaration(parser, access_specifier, storage_specifier);
  1923. case TOK_KEY_MODULE: return parse_module_declaration(parser, access_specifier, storage_specifier);
  1924. case TOK_KEY_EVENT: return parse_event_declaration(parser, access_specifier, storage_specifier);
  1925. case TOK_KEY_CLASS:
  1926. case TOK_KEY_STRUCT: return parse_class_declaration(parser, access_specifier, storage_specifier);
  1927. case TOK_OP_SEMICOLON: return parse_empty_statement(parser);
  1928. case TOK_KEY_VAR:
  1929. case TOK_KEY_CONST: return parse_variable_declaration(parser, true, access_specifier, storage_specifier);
  1930. default: REPORT_ERROR(gravity_lexer_token(lexer), "Unrecognized token %s.", token_name(peek)); return NULL;
  1931. }
  1932. // should never reach this point
  1933. assert(0);
  1934. return NULL;
  1935. }
  1936. static gnode_t *parse_import_statement (gravity_parser_t *parser) {
  1937. #pragma unused(parser)
  1938. DEBUG_PARSER("parse_import_statement");
  1939. DECLARE_LEXER;
  1940. // import is a syntactic sugar for System.import
  1941. gravity_lexer_next(lexer);
  1942. return NULL;
  1943. }
  1944. static gnode_t *parse_macro_statement (gravity_parser_t *parser) {
  1945. typedef enum {
  1946. MACRO_UNKNOWN = 0,
  1947. MACRO_UNITEST = 1,
  1948. MACRO_INCLUDE = 2,
  1949. MACRO_PUSH = 3,
  1950. MACRO_POP = 4
  1951. } builtin_macro;
  1952. DEBUG_PARSER("parse_macro_statement");
  1953. DECLARE_LEXER;
  1954. // consume special # symbol
  1955. gtoken_t type = gravity_lexer_next(lexer);
  1956. assert(type == TOK_MACRO);
  1957. // check for #! and interpret #! shebang bash as one line comment
  1958. // only if found on first line
  1959. if (gravity_lexer_peek(lexer) == TOK_OP_NOT && gravity_lexer_lineno(lexer) == 1) {
  1960. // consume special ! symbol
  1961. type = gravity_lexer_next(lexer);
  1962. assert(type == TOK_OP_NOT);
  1963. // skip until EOL
  1964. gravity_lexer_skip_line(lexer);
  1965. return NULL;
  1966. }
  1967. // macro has its own parser because I don't want to mess standard syntax
  1968. const char *macroid = parse_identifier(parser);
  1969. if (macroid == NULL) goto handle_error;
  1970. // check macro
  1971. builtin_macro macro_type = MACRO_UNKNOWN;
  1972. if (string_cmp(macroid, "unittest") == 0) macro_type = MACRO_UNITEST;
  1973. else if (string_cmp(macroid, "include") == 0) macro_type = MACRO_INCLUDE;
  1974. else if (string_cmp(macroid, "push") == 0) macro_type = MACRO_PUSH;
  1975. else if (string_cmp(macroid, "pop") == 0) macro_type = MACRO_POP;
  1976. mem_free(macroid);
  1977. gtoken_s token = gravity_lexer_token(lexer);
  1978. token.type = TOK_MACRO;
  1979. PARSER_CALL_CALLBACK(token);
  1980. switch (macro_type) {
  1981. case MACRO_UNITEST:
  1982. return parse_unittest_macro(parser);
  1983. break;
  1984. case MACRO_INCLUDE:
  1985. return parse_include_macro(parser);
  1986. break;
  1987. case MACRO_PUSH:
  1988. break;
  1989. case MACRO_POP:
  1990. break;
  1991. case MACRO_UNKNOWN:
  1992. break;
  1993. }
  1994. handle_error:
  1995. REPORT_WARNING(gravity_lexer_token(lexer), "%s", "Unknown macro token. Declaration will be ignored.");
  1996. return NULL;
  1997. }
  1998. static gnode_t *parse_special_statement (gravity_parser_t *parser) {
  1999. DEBUG_PARSER("parse_special_statement");
  2000. DECLARE_LEXER;
  2001. // consume special @ symbol
  2002. gtoken_t type = gravity_lexer_next(lexer);
  2003. assert(type == TOK_SPECIAL);
  2004. // special is really special so it has its own parser
  2005. // because I don't want to mess standard syntax
  2006. const char *specialid = parse_identifier(parser);
  2007. if (specialid == NULL) goto handle_error;
  2008. handle_error:
  2009. REPORT_WARNING(gravity_lexer_token(lexer), "%s", "Unknown special token. Declaration will be ignored.");
  2010. return NULL;
  2011. }
  2012. static gnode_t *parse_expression_statement (gravity_parser_t *parser) {
  2013. DEBUG_PARSER("parse_expression_statement");
  2014. gnode_t *expr = parse_expression(parser);
  2015. parse_semicolon(parser);
  2016. return expr;
  2017. }
  2018. static gnode_t *parse_statement (gravity_parser_t *parser) {
  2019. DEBUG_PARSER("parse_statement");
  2020. // label_statement
  2021. // flow_statement
  2022. // loop_statement
  2023. // jump_statement
  2024. // compound_statement
  2025. // declaration_statement
  2026. // empty_statement
  2027. // import_statement
  2028. // expression_statement (default)
  2029. DECLARE_LEXER;
  2030. gtoken_t token = gravity_lexer_peek(lexer);
  2031. if (token_iserror(token)) return parse_error(parser);
  2032. if (token_islabel_statement(token)) return parse_label_statement(parser);
  2033. else if (token_isflow_statement(token)) return parse_flow_statement(parser);
  2034. else if (token_isloop_statement(token)) return parse_loop_statement(parser);
  2035. else if (token_isjump_statement(token)) return parse_jump_statement(parser);
  2036. else if (token_iscompound_statement(token)) return parse_compound_statement(parser);
  2037. else if (token_isdeclaration_statement(token)) return parse_declaration_statement(parser);
  2038. else if (token_isempty_statement(token)) return parse_empty_statement(parser);
  2039. else if (token_isimport_statement(token)) return parse_import_statement(parser);
  2040. else if (token_isspecial_statement(token)) return parse_special_statement(parser);
  2041. else if (token_ismacro(token)) return parse_macro_statement(parser);
  2042. return parse_expression_statement(parser); // DEFAULT
  2043. }
  2044. // MARK: - Internal functions -
  2045. static void parser_register_core_classes (gravity_parser_t *parser) {
  2046. const char **list = gravity_core_identifiers();
  2047. // for each core identifier create a dummy extern variable node
  2048. gnode_r *decls = gnode_array_create();
  2049. uint32_t i = 0;
  2050. while (list[i]) {
  2051. const char *identifier = list[i];
  2052. gnode_t *node = gnode_variable_create(NO_TOKEN, string_dup(identifier), NULL, NULL, LAST_DECLARATION(), NULL);
  2053. gnode_array_push(decls, node);
  2054. ++i;
  2055. }
  2056. // register a variable declaration node in global statements
  2057. gnode_t *node = gnode_variable_decl_create(NO_TOKEN, TOK_KEY_VAR, 0, TOK_KEY_EXTERN, decls, LAST_DECLARATION());;
  2058. gnode_array_push(parser->statements, (gnode_t *)node);
  2059. }
  2060. static void parser_register_optional_classes (gravity_parser_t *parser) {
  2061. // for each optional identifier create a dummy extern variable node
  2062. gnode_r *decls = gnode_array_create();
  2063. // compile time optional classes
  2064. const char **list = gravity_optional_identifiers();
  2065. uint32_t i = 0;
  2066. while (list[i]) {
  2067. const char *identifier = list[i];
  2068. gnode_t *decl = gnode_variable_create(NO_TOKEN, string_dup(identifier), NULL, NULL, LAST_DECLARATION(), NULL);
  2069. gnode_array_push(decls, decl);
  2070. ++i;
  2071. }
  2072. // check if optional classes callback is registered (runtime optional classes)
  2073. if (parser->delegate && parser->delegate->optional_classes) {
  2074. list = parser->delegate->optional_classes(parser->delegate->xdata);
  2075. i = 0;
  2076. while (list[i]) {
  2077. const char *identifier = list[i];
  2078. gnode_t *decl_node = gnode_variable_create(NO_TOKEN, string_dup(identifier), NULL, NULL, LAST_DECLARATION(), NULL);
  2079. gnode_array_push(decls, decl_node);
  2080. ++i;
  2081. }
  2082. }
  2083. // register a variable declaration node in global statements
  2084. gnode_t *node = gnode_variable_decl_create(NO_TOKEN, TOK_KEY_VAR, 0, TOK_KEY_EXTERN, decls, LAST_DECLARATION());;
  2085. gnode_array_push(parser->statements, (gnode_t *)node);
  2086. }
  2087. static uint32_t parser_run (gravity_parser_t *parser) {
  2088. DEBUG_PARSER("=== BEGIN PARSING ===");
  2089. // register core and optional classes as extern globals
  2090. parser_register_core_classes(parser);
  2091. parser_register_optional_classes(parser);
  2092. nanotime_t t1 = nanotime();
  2093. do {
  2094. while (gravity_lexer_peek(CURRENT_LEXER)) {
  2095. gnode_t *node = parse_statement(parser);
  2096. if (node) gnode_array_push(parser->statements, node);
  2097. }
  2098. // since it is a stack of lexers then check if it is a real EOF
  2099. gravity_lexer_t *lexer = CURRENT_LEXER;
  2100. gravity_lexer_free(lexer);
  2101. marray_pop(*parser->lexer);
  2102. } while (marray_size(*parser->lexer));
  2103. nanotime_t t2 = nanotime();
  2104. parser->time = millitime(t1, t2);
  2105. DEBUG_PARSER("=== END PARSING ===\n");
  2106. return parser->nerrors;
  2107. }
  2108. static void parser_cleanup (gravity_parser_t *parser) {
  2109. // in case of error (so AST is not returned)
  2110. // then cleanup internal nodes
  2111. gnode_t *node= gnode_block_stat_create(NODE_LIST_STAT, NO_TOKEN, parser->statements, LAST_DECLARATION(), 0);
  2112. gnode_free(node);
  2113. }
  2114. static void parser_appendcode (const char *source, gravity_parser_t *parser) {
  2115. if (source == NULL) return;
  2116. size_t len = strlen(source);
  2117. if (len <= 0) return;
  2118. // build a new lexer based on source code to prepend
  2119. gravity_lexer_t *lexer1 = gravity_lexer_create(source, len, 0, true);
  2120. if (!lexer1) return;
  2121. // pop current lexer
  2122. gravity_lexer_t *lexer2 = POP_LEXER;
  2123. // swap lexer2 with lexer1
  2124. marray_push(gravity_lexer_t*, *parser->lexer, lexer1);
  2125. marray_push(gravity_lexer_t*, *parser->lexer, lexer2);
  2126. }
  2127. // MARK: - Public functions -
  2128. gravity_parser_t *gravity_parser_create (const char *source, size_t len, uint32_t fileid, bool is_static) {
  2129. init_grammer_rules();
  2130. gravity_parser_t *parser = mem_alloc(NULL, sizeof(gravity_parser_t));
  2131. if (!parser) return NULL;
  2132. gravity_lexer_t *lexer = gravity_lexer_create(source, len, fileid, is_static);
  2133. if (!lexer) goto abort_init;
  2134. parser->lexer = mem_alloc(NULL, sizeof(lexer_r));
  2135. marray_init(*parser->lexer);
  2136. marray_push(gravity_lexer_t*, *parser->lexer, lexer);
  2137. parser->statements = gnode_array_create();
  2138. if (!parser->statements) goto abort_init;
  2139. parser->declarations = gnode_array_create();
  2140. if (!parser->declarations) goto abort_init;
  2141. marray_init(parser->vdecl);
  2142. parser->last_error_lineno = UINT32_MAX;
  2143. return parser;
  2144. abort_init:
  2145. gravity_parser_free(parser);
  2146. return NULL;
  2147. }
  2148. gnode_t *gravity_parser_run (gravity_parser_t *parser, gravity_delegate_t *delegate) {
  2149. parser->delegate = delegate;
  2150. gravity_lexer_setdelegate(CURRENT_LEXER, delegate);
  2151. // check if some user code needs to be prepended
  2152. if ((delegate) && (delegate->precode_callback))
  2153. parser_appendcode(delegate->precode_callback(delegate->xdata), parser);
  2154. // if there are syntax errors then just returns
  2155. if (parser_run(parser) > 0) {
  2156. parser_cleanup (parser);
  2157. return NULL;
  2158. }
  2159. // if there are some open declarations then there should be an error somewhere
  2160. if (marray_size(*parser->declarations) > 0) return NULL;
  2161. // return ast
  2162. return gnode_block_stat_create(NODE_LIST_STAT, NO_TOKEN, parser->statements, NULL, 0);
  2163. }
  2164. void gravity_parser_free (gravity_parser_t *parser) {
  2165. // free memory for stack of lexers
  2166. if (parser->lexer) {
  2167. size_t _len = marray_size(*parser->lexer);
  2168. for (size_t i=0; i<_len; ++i) {
  2169. gravity_lexer_t *lexer = (gravity_lexer_t *)marray_get(*parser->lexer, i);
  2170. gravity_lexer_free(lexer);
  2171. }
  2172. marray_destroy(*parser->lexer);
  2173. mem_free(parser->lexer);
  2174. }
  2175. // parser->declarations is used to keep track of nodes hierarchy and it contains pointers to
  2176. // parser->statements nodes so there is no need to free it using node_array_free because nodes
  2177. // are freed when AST (parser->statements) is freed
  2178. if (parser->declarations) {
  2179. marray_destroy(*parser->declarations);
  2180. mem_free(parser->declarations);
  2181. }
  2182. // parser->statements is returned from gravity_parser_run
  2183. // and must be deallocated using gnode_free
  2184. marray_destroy(parser->vdecl);
  2185. mem_free(parser);
  2186. }