parser.inc 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814
  1. //#include "introspect"
  2. #include <a_samp>
  3. // Tokeniser. Read text and convert it to tokens for simple processing.
  4. #if !defined TODO
  5. #define TODO:%9\32;%0\10;%1 { new TODO; print("TODO: \"%0\""); }
  6. #endif
  7. #include "introspect"
  8. #if defined INTROSPECT_LAMBDA
  9. #tryinclude "..\YSI_Coding\y_inline"
  10. #tryinclude "YSI_Coding\y_inline"
  11. #tryinclude "../YSI_Coding/y_inline"
  12. #tryinclude "YSI_Coding/y_inline"
  13. #if !defined YSI_MAX_INLINE_STRING
  14. #error YSI 4.0 is required. Get it here: github.com/Y-Less/YSI-Includes/tree/YSI.tl
  15. #endif
  16. #endif
  17. enum e_TOKEN_OP
  18. {
  19. e_TOKEN_OP_NONE,
  20. e_TOKEN_OP_ASSIGN, // =
  21. e_TOKEN_OP_EQUALS, // ==
  22. e_TOKEN_OP_LTE, // <=
  23. e_TOKEN_OP_GTE, // >=
  24. e_TOKEN_OP_LESS, // <
  25. e_TOKEN_OP_GREATER, // >
  26. e_TOKEN_OP_NOT, // !
  27. e_TOKEN_OP_NEQ, // !=
  28. e_TOKEN_OP_INV, // ~
  29. e_TOKEN_OP_INV_ASS, // ~=
  30. e_TOKEN_OP_ADD, // +
  31. e_TOKEN_OP_ADD_ASS, // +=
  32. e_TOKEN_OP_SUB, // - (INFIX)
  33. e_TOKEN_OP_NEG, // - (PREFIX)
  34. e_TOKEN_OP_SUB_ASS, // -=
  35. e_TOKEN_OP_MUL, // *
  36. e_TOKEN_OP_MUL_ASS, // *=
  37. e_TOKEN_OP_DIV, // /
  38. e_TOKEN_OP_DIV_ASS, // /=
  39. e_TOKEN_OP_MOD, // %
  40. e_TOKEN_OP_MOD_ASS, // %=
  41. e_TOKEN_OP_XOR, // ^
  42. e_TOKEN_OP_XOR_ASS, // ^=
  43. e_TOKEN_OP_LAND, // & (INFIX)
  44. e_TOKEN_OP_REF, // & (PREFIX)
  45. e_TOKEN_OP_LAND_ASS, // &=
  46. e_TOKEN_OP_LOR, // |
  47. e_TOKEN_OP_LOR_ASS, // |=
  48. e_TOKEN_OP_RSHIFT, // >>
  49. e_TOKEN_OP_RSHIFT_ASS, // >>=
  50. e_TOKEN_OP_SHIFT, // >>>
  51. e_TOKEN_OP_SHIFT_ASS, // >>>=
  52. e_TOKEN_OP_LSHIFT, // <<
  53. e_TOKEN_OP_LSHIFT_ASS, // <<=
  54. e_TOKEN_OP_AND, // &&
  55. e_TOKEN_OP_OR, // ||
  56. e_TOKEN_OP_OP_BRACKET, // (
  57. e_TOKEN_OP_CL_BRACKET, // )
  58. e_TOKEN_OP_OP_BRACE, // {
  59. e_TOKEN_OP_CL_BRACE, // }
  60. e_TOKEN_OP_OP_SQUARE, // [
  61. e_TOKEN_OP_CL_SQUARE, // ]
  62. e_TOKEN_OP_PRE_INC, // ++ (PREFIX)
  63. e_TOKEN_OP_POST_INC, // ++ (SUFFIX)
  64. e_TOKEN_OP_PRE_DEC, // -- (PREFIX)
  65. e_TOKEN_OP_POST_DEC, // -- (SUFFIX)
  66. e_TOKEN_OP_ELIPSIS, // ...
  67. e_TOKEN_OP_CONCAT, // ..
  68. e_TOKEN_OP_HASH, // #
  69. e_TOKEN_OP_PAAMAYIM, // ::
  70. e_TOKEN_OP_DQUOTE, // "
  71. e_TOKEN_OP_QUOTE, // '
  72. e_TOKEN_OP_SEMICOLON, // ;
  73. e_TOKEN_OP_COMMA, // ,
  74. e_TOKEN_OP_POINT, // .
  75. e_TOKEN_OP_COLON, // :
  76. e_TOKEN_OP_QUESTION, // ?
  77. }
  78. enum e_TOKEN_TYPE
  79. {
  80. e_TOKEN_TYPE_NONE,
  81. e_TOKEN_TYPE_STRING,
  82. e_TOKEN_TYPE_SYMBOL, // Unknown symbol type.
  83. // These two are distinct for simplicity.
  84. e_TOKEN_TYPE_NATIVE,
  85. e_TOKEN_TYPE_FUNC,
  86. e_TOKEN_TYPE_FFUNC,
  87. // This makes the code quite context-aware.
  88. e_TOKEN_TYPE_VAR, // Regular variable.
  89. e_TOKEN_TYPE_FVAR, // Float variable.
  90. e_TOKEN_TYPE_FLOAT,
  91. e_TOKEN_TYPE_BOOL,
  92. e_TOKEN_TYPE_INT,
  93. e_TOKEN_TYPE_APPLY,
  94. e_TOKEN_TYPE_INDEX,
  95. //e_TOKEN_TYPE_MD, // This is used when we have a multi-dimensional array.
  96. e_TOKEN_TYPE_OP,
  97. // Special types for unresolved arrays.
  98. e_TOKEN_TYPE_ARRAY,
  99. e_TOKEN_TYPE_FARRAY,
  100. }
  101. #define TOKEN_TYPE_MASK (e_TOKEN_TYPE:0x3F)
  102. #define TOKEN_TYPE_SHIFT (e_TOKEN_TYPE:6)
  103. enum E_TOKEN
  104. {
  105. e_TOKEN_TYPE:E_TOKEN_TYPE,
  106. E_TOKEN_INT_VAL = 1,
  107. Float:E_TOKEN_FLOAT_VAL = 1,
  108. bool:E_TOKEN_BOOL_VAL = 1,
  109. e_TOKEN_OP:E_TOKEN_OP = 1,
  110. E_TOKEN_SYM_PTR = 1,
  111. E_TOKEN_STRING_IDX = 1,
  112. E_TOKEN_NATIVE_IDX = 1,
  113. E_TOKEN_FUNC_PTR = 1,
  114. E_TOKEN_LEFT,
  115. E_TOKEN_RIGHT,
  116. //_E_TOKEN_TEMP_STRING[32],
  117. }
  118. #define COMPARE_PARSER_TOKEN(%0,{%1,%2}) (((%0[E_TOKEN_TYPE]) == (%1)) && ((%0[E_TOKEN_INT_VAL]) == (%2)))
  119. #define MAKE_PARSER_TOKEN(%0,%1,%2,%3) {%0, %1, Float:%2, bool:%3}
  120. #define EMPTY_PARSER_TOKEN MAKE_PARSER_TOKEN(e_TOKEN_TYPE_NONE, 0, -1, -1)
  121. #define MAKE_TOKEN(%0,%1,%2) %0[E_TOKEN_TYPE]=%1,%0[E_TOKEN_INT_VAL]=%2,%0[E_TOKEN_LEFT]=%0[E_TOKEN_RIGHT]=-1
  122. enum E_OPERATOR_DATA
  123. {
  124. E_OPERATOR_DATA_NAME[7],
  125. E_OPERATOR_DATA_PRECEDENCE, // -1 = unary only.
  126. }
  127. static stock const
  128. ISI_gscOpData[][E_OPERATOR_DATA] =
  129. {
  130. // 3 is a special precedence that makes "=" right-associative.
  131. {"<none>", 0}, // e_TOKEN_OP_NONE
  132. {"=", 4}, // e_TOKEN_OP_ASSIGN
  133. {"==", 12}, // e_TOKEN_OP_EQUALS
  134. {"<=", 14}, // e_TOKEN_OP_LTE
  135. {">=", 14}, // e_TOKEN_OP_GTE
  136. {"<", 14}, // e_TOKEN_OP_LESS
  137. {">", 14}, // e_TOKEN_OP_GREATER
  138. {"!", -1}, // e_TOKEN_OP_NOT
  139. {"!=", 12}, // e_TOKEN_OP_NEQ
  140. // There is no binary "~".
  141. {"~", -1}, // e_TOKEN_OP_INV
  142. {"~=", 4}, // e_TOKEN_OP_INV_ASS
  143. {"+", 22}, // e_TOKEN_OP_ADD
  144. {"+=", 4}, // e_TOKEN_OP_ADD_ASS
  145. // This is the precedence for the binary operator, the unary
  146. // operators all have the same precedence and are handled specially.
  147. {"-", 22}, // e_TOKEN_OP_SUB
  148. {"-", 22}, // e_TOKEN_OP_NEG
  149. {"-=", 4}, // e_TOKEN_OP_SUB_ASS
  150. {"*", 24}, // e_TOKEN_OP_MUL
  151. {"*=", 4}, // e_TOKEN_OP_MUL_ASS
  152. {"/", 24}, // e_TOKEN_OP_DIV
  153. {"/=", 4}, // e_TOKEN_OP_DIV_ASS
  154. {"%", 24}, // e_TOKEN_OP_MOD
  155. {"%=", 4}, // e_TOKEN_OP_MOD_ASS
  156. {"^", 17}, // e_TOKEN_OP_XOR
  157. {"^=", 4}, // e_TOKEN_OP_XOR_ASS
  158. {"&", 18}, // e_TOKEN_OP_LAND
  159. {"&", 18}, // e_TOKEN_OP_REF
  160. {"&=", 4}, // e_TOKEN_OP_LAND_ASS
  161. {"|", 16}, // e_TOKEN_OP_LOR
  162. {"|=", 4}, // e_TOKEN_OP_LOR_ASS
  163. {">>", 20}, // e_TOKEN_OP_RSHIFT
  164. {">>=", 4}, // e_TOKEN_OP_RSHIFT_ASS
  165. {">>>", 20}, // e_TOKEN_OP_SHIFT
  166. {">>>=", 4}, // e_TOKEN_OP_SHIFT_ASS
  167. {"<<", 20}, // e_TOKEN_OP_LSHIFT
  168. {"<<=", 4}, // e_TOKEN_OP_LSHIFT_ASS
  169. {"&&", 10}, // e_TOKEN_OP_AND
  170. {"||", 9}, // e_TOKEN_OP_OR
  171. {"(", 0}, // e_TOKEN_OP_OP_BRACKET
  172. {")", 0}, // e_TOKEN_OP_CL_BRACKET
  173. {"{", 0}, // e_TOKEN_OP_OP_BRACE
  174. {"}", 0}, // e_TOKEN_OP_CL_BRACE
  175. {"[", 0}, // e_TOKEN_OP_OP_SQUARE
  176. {"]", 0}, // e_TOKEN_OP_CL_SQUARE
  177. {"++", -1}, // e_TOKEN_OP_PRE_INC
  178. {"++", -1}, // e_TOKEN_OP_POST_INC
  179. {"--", -1}, // e_TOKEN_OP_PRE_DEC
  180. {"--", -1}, // e_TOKEN_OP_POST_DEC
  181. {"...", 8}, // e_TOKEN_OP_ELIPSIS
  182. {"..", 26}, // e_TOKEN_OP_CONCAT
  183. {"#", -1}, // e_TOKEN_OP_HASH
  184. {"::", 0}, // e_TOKEN_OP_PAAMAYIM
  185. {"\"", 0}, // e_TOKEN_OP_DQUOTE
  186. {"'", 0}, // e_TOKEN_OP_QUOTE
  187. {";", 2}, // e_TOKEN_OP_SEMICOLON
  188. {",", 2}, // e_TOKEN_OP_COMMA
  189. {".", 0}, // e_TOKEN_OP_POINT
  190. // Here "colon" binds slightly tighter than "question mark" so that
  191. // we don't need extra code to deal with ternary operators, instead
  192. // we just give "?" a condition and a (true, false) pair. I might
  193. // have to change this in the future if I do JIT execution.
  194. {":", 7}, // e_TOKEN_OP_COLON
  195. {"?", 6} // e_TOKEN_OP_QUESTION
  196. };
  197. static stock
  198. ISI_gFloatTagIndex = -1,
  199. ISI_gInputPtr,
  200. ISI_gParsePos,
  201. ISI_gsStringEnd;
  202. stock
  203. ISI_gInputLine[512],
  204. ISI_gsStringTable[32] = {-1, ...},
  205. ISI_gParseTree[512][E_TOKEN];
  206. #if defined INTROSPECT_PLAYER_DATA
  207. static stock
  208. ISI_gCurrentPlayer = -1,
  209. ISI_gPlayerInts[MAX_PLAYERS][12], // a - l
  210. ISI_gPlayerStrM[MAX_PLAYERS][144], // m
  211. ISI_gPlayerStrN[MAX_PLAYERS][144], // n
  212. ISI_gPlayerFlts[MAX_PLAYERS][12]; // o - z
  213. #endif
  214. static stock
  215. ISI_gNoPlayerInts[12], // a - l
  216. ISI_gNoPlayerStrM[144], // m
  217. ISI_gNoPlayerStrN[144], // n
  218. ISI_gNoPlayerFlts[12]; // o - z
  219. stock Parser_SetPlayer(pid)
  220. {
  221. #if defined INTROSPECT_PLAYER_DATA
  222. if ((ISI_gCurrentPlayer = pid) == -1)
  223. {
  224. state Parser_Error_state : Parser_Error_print;
  225. }
  226. else
  227. {
  228. state Parser_Error_state : Parser_Error_player;
  229. }
  230. #else
  231. #pragma unused pid
  232. #endif
  233. }
  234. static stock Parser_GetLocalName(ptr)
  235. {
  236. #if defined INTROSPECT_PLAYER_DATA
  237. if (IsPlayerConnected(ISI_gCurrentPlayer))
  238. {
  239. new
  240. sInts = -1,
  241. sStrM,
  242. sStrN,
  243. sFlts;
  244. sInts = ref(ISI_gPlayerInts[ISI_gCurrentPlayer]),
  245. sStrM = ref(ISI_gPlayerStrM[ISI_gCurrentPlayer]),
  246. sStrN = ref(ISI_gPlayerStrN[ISI_gCurrentPlayer]),
  247. sFlts = ref(ISI_gPlayerFlts[ISI_gCurrentPlayer]);
  248. if (sInts <= ptr < sInts + 12 * 4)
  249. {
  250. return 'a' + (ptr - sInts) / 4;
  251. }
  252. else if (sStrM <= ptr < sStrM + 144 * 4)
  253. {
  254. return 'm';
  255. }
  256. else if (sStrN <= ptr < sStrN + 144 * 4)
  257. {
  258. return 'n';
  259. }
  260. else if (sFlts <= ptr < sFlts + 12 * 4)
  261. {
  262. return 'o' + (ptr - sFlts) / 4;
  263. }
  264. }
  265. else
  266. #endif
  267. {
  268. static
  269. sInts = -1,
  270. sStrM,
  271. sStrN,
  272. sFlts;
  273. if (sInts == -1)
  274. {
  275. sInts = ref(ISI_gNoPlayerInts),
  276. sStrM = ref(ISI_gNoPlayerStrM),
  277. sStrN = ref(ISI_gNoPlayerStrN),
  278. sFlts = ref(ISI_gNoPlayerFlts);
  279. }
  280. if (sInts <= ptr < sInts + 12 * 4)
  281. {
  282. return 'a' + (ptr - sInts) / 4;
  283. }
  284. else if (sStrM <= ptr < sStrM + 144 * 4)
  285. {
  286. return 'm';
  287. }
  288. else if (sStrN <= ptr < sStrN + 144 * 4)
  289. {
  290. return 'n';
  291. }
  292. else if (sFlts <= ptr < sFlts + 12 * 4)
  293. {
  294. return 'o' + (ptr - sFlts) / 4;
  295. }
  296. }
  297. return '-';
  298. }
  299. forward _@_ParserFuncs();
  300. public _@_ParserFuncs()
  301. {
  302. printf("");
  303. format("", 0, "");
  304. }
  305. stock _Parser_Msg(const str[], ...) <Parser_Error_state : Parser_Error_player>
  306. {
  307. static
  308. dest[144],
  309. sPar,
  310. sRet,
  311. sFrm;
  312. // Save the header.
  313. #emit LOAD.S.pri 0
  314. #emit STOR.pri sFrm
  315. #emit LOAD.S.pri 4
  316. #emit STOR.pri sRet
  317. #emit LOAD.S.pri 8
  318. #emit STOR.pri sPar
  319. // Push the size.
  320. #emit CONST.alt 144
  321. #emit STOR.S.alt 8
  322. // Push the destination.
  323. #emit CONST.alt dest
  324. #emit STOR.S.alt 4
  325. // Update the parameter count.
  326. #emit ADD.C 8
  327. #emit STOR.S.pri 0
  328. // Call the function.
  329. #emit SYSREQ.C format
  330. // Restore the header.
  331. #emit LOAD.pri sFrm
  332. #emit STOR.S.pri 0
  333. #emit LOAD.pri sRet
  334. #emit STOR.S.pri 4
  335. #emit LOAD.pri sPar
  336. #emit STOR.S.pri 8
  337. return SendClientMessage(ISI_gCurrentPlayer, (str[7] == 'E') ? 0xCD2626FF : 0xFFD700FF, dest);
  338. }
  339. stock _Parser_Msg(const str[], {Float,_}:...) <Parser_Error_state : Parser_Error_print>
  340. {
  341. #pragma unused str
  342. #emit STACK 8
  343. #emit SYSREQ.C printf
  344. #emit STACK 0xFFFFFFF8
  345. #emit RETN
  346. return 0;
  347. }
  348. #if defined INTROSPECT_PLAYER_DATA
  349. #define Parser_Error(%0) _Parser_Msg("PARSER ERROR : " %0)
  350. #define Parser_Warning(%0) _Parser_Msg("PARSER WARNING: " %0)
  351. #else
  352. #define Parser_Error(%0) printf("PARSER ERROR : " %0)
  353. #define Parser_Warning(%0) printf("PARSER WARNING: " %0)
  354. #endif
  355. /******************************************************************************\
  356. |******************************************************************************|
  357. |******************************************************************************|
  358. |******************************************************************************|
  359. |**** ****|
  360. |**** HELPER FUNCTIONS ****|
  361. |**** ****|
  362. |******************************************************************************|
  363. |******************************************************************************|
  364. |******************************************************************************|
  365. \******************************************************************************/
  366. /******************************************************************************\
  367. Parser_PrintOp
  368. Print an operator (or rather return it) given an identifier.
  369. \******************************************************************************/
  370. static stock Parser_PrintOp(e_TOKEN_OP:op)
  371. {
  372. new
  373. none[7];
  374. if (e_TOKEN_OP_NONE <= op < e_TOKEN_OP)
  375. {
  376. strcat(none, ISI_gscOpData[op][E_OPERATOR_DATA_NAME], 7);
  377. }
  378. else
  379. {
  380. none = "<none>";
  381. }
  382. return none;
  383. }
  384. static stock Parser_Print(token[E_TOKEN], ret[], len = sizeof (ret))
  385. {
  386. switch (token[E_TOKEN_TYPE] & TOKEN_TYPE_MASK)
  387. {
  388. case e_TOKEN_TYPE_NONE: ret[0] = '\0';
  389. case e_TOKEN_TYPE_STRING: format(ret, len, "STRING: %s", ISI_gInputLine[ISI_gsStringTable[token[E_TOKEN_STRING_IDX]]]);
  390. case e_TOKEN_TYPE_NATIVE:
  391. {
  392. new name[32];
  393. GetNativeNameFromIndex(token[E_TOKEN_NATIVE_IDX], name);
  394. format(ret, len, "NATIVE: %s", name);
  395. }
  396. case e_TOKEN_TYPE_SYMBOL:
  397. format(ret, len, "SYMBOL: %s", ISI_gInputLine[ISI_gsStringTable[token[E_TOKEN_STRING_IDX]]]);
  398. case e_TOKEN_TYPE_FUNC, e_TOKEN_TYPE_FFUNC:
  399. format(ret, len, "FUNCTION: %s", GetFunctionFromAddress(token[E_TOKEN_FUNC_PTR]));
  400. case e_TOKEN_TYPE_VAR, e_TOKEN_TYPE_FVAR, e_TOKEN_TYPE_ARRAY, e_TOKEN_TYPE_FARRAY:
  401. {
  402. new
  403. ch = Parser_GetLocalName(token[E_TOKEN_SYM_PTR]);
  404. if (ch == '-') format(ret, len, "VARIABLE: %s", GetVariableFromAddress(token[E_TOKEN_SYM_PTR]));
  405. else format(ret, len, "LOCAL: %c", ch);
  406. }
  407. case e_TOKEN_TYPE_FLOAT: format(ret, len, "FLOAT: %.2f", token[E_TOKEN_FLOAT_VAL]);
  408. case e_TOKEN_TYPE_INT: format(ret, len, "NUMBER: %d", token[E_TOKEN_INT_VAL]);
  409. case e_TOKEN_TYPE_BOOL: format(ret, len, "BOOLEAN: %s", (token[E_TOKEN_BOOL_VAL]) ? ("true") : ("false"));
  410. case e_TOKEN_TYPE_OP: format(ret, len, "OPERATOR: %s", Parser_PrintOp(token[E_TOKEN_OP]));
  411. case e_TOKEN_TYPE_APPLY: ret[0] = '\0', strcat(ret, "APPLY", len);
  412. case e_TOKEN_TYPE_INDEX: ret[0] = '\0', strcat(ret, "INDEX", len);
  413. default: ret[0] = '\0', strcat(ret, "<unknown>", len);
  414. }
  415. }
  416. static stock PrettyPrint(token[E_TOKEN])
  417. {
  418. new str[32];
  419. Parser_Print(token, str);
  420. print(str);
  421. }
  422. static stock Parser_PeekChar()
  423. {
  424. return ISI_gInputLine[ISI_gInputPtr];
  425. }
  426. static stock Parser_PeekToken()
  427. {
  428. // Find out what the next token is, then backtrack to the start of it.
  429. new
  430. ret[E_TOKEN] = EMPTY_PARSER_TOKEN,
  431. ptr = ISI_gInputPtr;
  432. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_NONE,
  433. Parser_SkipWhitespace();
  434. // We don't actually NEED the next token most of the time, just the type,
  435. // which can be determined from the first character. This solves a tiny and
  436. // (possibly) rare issue when strings from "peek" would overwrite the true
  437. // input.
  438. switch (Parser_PeekChar())
  439. {
  440. case '\0': {}
  441. case '0' .. '9': ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_INT;
  442. case 'a' .. 'z', 'A' .. 'Z', '_', '@': ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_SYMBOL;
  443. case '"': ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_STRING;
  444. case '\'': ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_INT;//'
  445. default: Parser_GetOp(ret);
  446. }
  447. return
  448. ISI_gInputPtr = ptr,
  449. ret;
  450. }
  451. #define Parser_IsWhitespace((%0)) ('\0' <= (%0) <= ' ')
  452. static stock Parser_SkipWhitespace()
  453. {
  454. while ('\0' < ISI_gInputLine[ISI_gInputPtr] <= ' ') ++ISI_gInputPtr;
  455. }
  456. /******************************************************************************\
  457. |******************************************************************************|
  458. |******************************************************************************|
  459. |******************************************************************************|
  460. |**** ****|
  461. |**** TOKENISER ****|
  462. |**** ****|
  463. |******************************************************************************|
  464. |******************************************************************************|
  465. |******************************************************************************|
  466. \******************************************************************************/
  467. #define PARSER_DO_OP_1(%9,%0) else if (p0 == %0) ret[E_TOKEN_OP] = (%9), len = 1;
  468. #define PARSER_DO_OP_2(%9,%0,%1) else if (p0 == %0 && p1 == %1) ret[E_TOKEN_OP] = (%9), len = 2;
  469. #define PARSER_DO_OP_3(%9,%0,%1,%2) else if (p0 == %0 && p1 == %1 && p2 == %2) ret[E_TOKEN_OP] = (%9), len = 3;
  470. #define PARSER_DO_OP_4(%9,%0,%1,%2,%3) else if (p0 == %0 && p1 == %1 && p2 == %2 && p3 == %3) ret[E_TOKEN_OP] = (%9), len = 4;
  471. static stock Parser_GetOp(ret[E_TOKEN])
  472. {
  473. // Should really use a "trie" here, but don't - too complex for now.
  474. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_OP;
  475. new
  476. len,
  477. p0, p1, p2, p3;
  478. // Very special if - uses short-circuiting to always fail eventually...
  479. if ((p0 = ISI_gInputLine[ISI_gInputPtr + 0]) &&
  480. (p1 = ISI_gInputLine[ISI_gInputPtr + 1]) &&
  481. (p2 = ISI_gInputLine[ISI_gInputPtr + 2]) &&
  482. (p3 = ISI_gInputLine[ISI_gInputPtr + 3]) && len) {}
  483. PARSER_DO_OP_4(e_TOKEN_OP_SHIFT_ASS, '>', '>', '>', '=')
  484. PARSER_DO_OP_3(e_TOKEN_OP_RSHIFT_ASS, '>', '>', '=')
  485. PARSER_DO_OP_3(e_TOKEN_OP_SHIFT, '>', '>', '>')
  486. PARSER_DO_OP_3(e_TOKEN_OP_LSHIFT_ASS, '<', '<', '=')
  487. PARSER_DO_OP_3(e_TOKEN_OP_ELIPSIS, '.', '.', '.')
  488. PARSER_DO_OP_2(e_TOKEN_OP_EQUALS, '=', '=')
  489. PARSER_DO_OP_2(e_TOKEN_OP_LTE, '<', '=')
  490. PARSER_DO_OP_2(e_TOKEN_OP_GTE, '>', '=')
  491. PARSER_DO_OP_2(e_TOKEN_OP_NEQ, '!', '=')
  492. PARSER_DO_OP_2(e_TOKEN_OP_INV_ASS, '~', '=')
  493. PARSER_DO_OP_2(e_TOKEN_OP_ADD_ASS, '+', '=')
  494. PARSER_DO_OP_2(e_TOKEN_OP_SUB_ASS, '-', '=')
  495. PARSER_DO_OP_2(e_TOKEN_OP_MUL_ASS, '*', '=')
  496. PARSER_DO_OP_2(e_TOKEN_OP_DIV_ASS, '/', '=')
  497. PARSER_DO_OP_2(e_TOKEN_OP_MOD_ASS, '%', '=')
  498. PARSER_DO_OP_2(e_TOKEN_OP_XOR_ASS, '^', '=')
  499. PARSER_DO_OP_2(e_TOKEN_OP_LAND_ASS, '&', '=')
  500. PARSER_DO_OP_2(e_TOKEN_OP_LOR_ASS, '|', '=')
  501. PARSER_DO_OP_2(e_TOKEN_OP_RSHIFT, '>', '>')
  502. PARSER_DO_OP_2(e_TOKEN_OP_LSHIFT, '<', '<')
  503. PARSER_DO_OP_2(e_TOKEN_OP_AND, '&', '&')
  504. PARSER_DO_OP_2(e_TOKEN_OP_OR, '|', '|')
  505. PARSER_DO_OP_2(e_TOKEN_OP_PAAMAYIM, ':', ':')
  506. PARSER_DO_OP_2(e_TOKEN_OP_PRE_INC, '+', '+')
  507. PARSER_DO_OP_2(e_TOKEN_OP_PRE_DEC, '-', '-')
  508. PARSER_DO_OP_2(e_TOKEN_OP_CONCAT, '.', '.')
  509. PARSER_DO_OP_1(e_TOKEN_OP_ASSIGN, '=')
  510. PARSER_DO_OP_1(e_TOKEN_OP_LESS, '<')
  511. PARSER_DO_OP_1(e_TOKEN_OP_GREATER, '>')
  512. PARSER_DO_OP_1(e_TOKEN_OP_NOT, '!')
  513. PARSER_DO_OP_1(e_TOKEN_OP_INV, '~')
  514. PARSER_DO_OP_1(e_TOKEN_OP_ADD, '+')
  515. PARSER_DO_OP_1(e_TOKEN_OP_SUB, '-')
  516. PARSER_DO_OP_1(e_TOKEN_OP_MUL, '*')
  517. PARSER_DO_OP_1(e_TOKEN_OP_DIV, '/')
  518. PARSER_DO_OP_1(e_TOKEN_OP_MOD, '%')
  519. PARSER_DO_OP_1(e_TOKEN_OP_XOR, '^')
  520. PARSER_DO_OP_1(e_TOKEN_OP_LAND, '&')
  521. PARSER_DO_OP_1(e_TOKEN_OP_LOR, '|')
  522. PARSER_DO_OP_1(e_TOKEN_OP_OP_BRACKET, '(')
  523. PARSER_DO_OP_1(e_TOKEN_OP_CL_BRACKET, ')')
  524. PARSER_DO_OP_1(e_TOKEN_OP_OP_BRACE, '{')
  525. PARSER_DO_OP_1(e_TOKEN_OP_CL_BRACE, '}')
  526. PARSER_DO_OP_1(e_TOKEN_OP_OP_SQUARE, '[')
  527. PARSER_DO_OP_1(e_TOKEN_OP_CL_SQUARE, ']')
  528. PARSER_DO_OP_1(e_TOKEN_OP_HASH, '#')
  529. PARSER_DO_OP_1(e_TOKEN_OP_DQUOTE, '"')
  530. PARSER_DO_OP_1(e_TOKEN_OP_QUOTE, '\'')//'
  531. PARSER_DO_OP_1(e_TOKEN_OP_COMMA, ',')
  532. PARSER_DO_OP_1(e_TOKEN_OP_POINT, '.')
  533. PARSER_DO_OP_1(e_TOKEN_OP_QUESTION, '?')
  534. PARSER_DO_OP_1(e_TOKEN_OP_COLON, ':')
  535. PARSER_DO_OP_1(e_TOKEN_OP_SEMICOLON, ';')
  536. if (len)
  537. {
  538. // Found an op.
  539. ISI_gInputPtr += len;
  540. }
  541. else
  542. {
  543. Parser_Error("Unexpected input at (%d).", ISI_gInputPtr);
  544. // Skip one character and try again.
  545. ++ISI_gInputPtr;
  546. }
  547. return ret;
  548. }
  549. #undef PARSER_DO_OP_1
  550. #undef PARSER_DO_OP_2
  551. #undef PARSER_DO_OP_3
  552. #undef PARSER_DO_OP_4
  553. static stock Parser_GetNextToken(ret[E_TOKEN])
  554. {
  555. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_NONE,
  556. Parser_SkipWhitespace();
  557. switch (Parser_PeekChar())
  558. {
  559. case '\0': return 0;
  560. case '0' .. '9': Parser_GetNumber(ret);
  561. case 'a' .. 'z', 'A' .. 'Z', '_', '@':
  562. {
  563. Parser_GetSymbol(ret);
  564. }
  565. case '"': Parser_GetString(ret);
  566. case '\'': Parser_GetChar(ret);//'
  567. default: Parser_GetOp(ret);
  568. }
  569. return 1;
  570. }
  571. static stock Parser_GetHex(ch)
  572. {
  573. switch (ch)
  574. {
  575. case '0' .. '9': return ch - '0';
  576. case 'a' .. 'f': return ch - 'a' + 10;
  577. case 'A' .. 'F': return ch - 'A' + 10;
  578. }
  579. return -1;
  580. }
  581. /******************************************************************************\
  582. Parser_DoHex
  583. Given an input string we KNOW starts with a hex number, return that number.
  584. \******************************************************************************/
  585. static stock Parser_DoHex(ret[E_TOKEN])
  586. {
  587. new
  588. ptr = ISI_gInputPtr + 2,
  589. cur,
  590. num = Parser_GetHex(ISI_gInputLine[ptr]);
  591. if (num == -1) Parser_Error("Invalid HEX number.");
  592. while ((cur = Parser_GetHex(ISI_gInputLine[++ptr])) != -1)
  593. {
  594. num = (num << 4) | cur;
  595. }
  596. return
  597. ret[E_TOKEN_INT_VAL] = num,
  598. ISI_gInputPtr = ptr,
  599. 1;
  600. }
  601. static stock Parser_DoDecimal(ret[E_TOKEN])
  602. {
  603. new
  604. ptr = ISI_gInputPtr,
  605. cur,
  606. num = ISI_gInputLine[ptr] - '0';
  607. if (0 <= num <= 9)
  608. {
  609. while (0 <= (cur = ISI_gInputLine[++ptr] - '0') <= 9)
  610. {
  611. num = num * 10 + cur;
  612. }
  613. return
  614. ret[E_TOKEN_INT_VAL] = num,
  615. ISI_gInputPtr = ptr,
  616. 1;
  617. }
  618. else return Parser_Error("Invalid HEX number.");
  619. }
  620. static stock Parser_GetBinary(ch)
  621. {
  622. switch (ch)
  623. {
  624. case '0': return 0;
  625. case '1': return 1;
  626. }
  627. return -1;
  628. }
  629. static stock Parser_DoBinary(ret[E_TOKEN])
  630. {
  631. new
  632. ptr = ISI_gInputPtr + 2,
  633. cur,
  634. num = Parser_GetBinary(ISI_gInputLine[ptr]);
  635. if (num == -1) Parser_Error("Invalid Binary number.");
  636. while ((cur = Parser_GetBinary(ISI_gInputLine[++ptr])) != -1)
  637. {
  638. num = (num << 1) | cur;
  639. }
  640. return
  641. ret[E_TOKEN_INT_VAL] = num,
  642. ISI_gInputPtr = ptr,
  643. 1;
  644. }
  645. static stock Parser_GetOctal(ch)
  646. {
  647. switch (ch)
  648. {
  649. case '0' .. '7': return ch - '0';
  650. }
  651. return -1;
  652. }
  653. static stock Parser_DoOctal(ret[E_TOKEN])
  654. {
  655. new
  656. ptr = ISI_gInputPtr + 1,
  657. cur,
  658. num = Parser_GetOctal(ISI_gInputLine[ptr]);
  659. if (num == -1) Parser_Error("Invalid Octal number.");
  660. while ((cur = Parser_GetOctal(ISI_gInputLine[++ptr])) != -1)
  661. {
  662. num = (num << 3) | cur;
  663. }
  664. return
  665. ret[E_TOKEN_INT_VAL] = num,
  666. ISI_gInputPtr = ptr,
  667. 1;
  668. }
  669. /******************************************************************************\
  670. Parser_Pow10
  671. Very quickly raise some number by a given exponent (i.e. n *= 10^e).
  672. \******************************************************************************/
  673. static stock Float:Parser_Pow10(Float:n, e)
  674. {
  675. static const
  676. Float:scPow[] = {1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0};
  677. while (e > 0)
  678. {
  679. n *= scPow[e % sizeof (scPow)],
  680. e -= sizeof (scPow);
  681. }
  682. return n;
  683. }
  684. static stock Parser_DoFloat(ret[E_TOKEN])
  685. {
  686. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_FLOAT;
  687. new
  688. part = 0,
  689. ndp = 0,
  690. dp = 0,
  691. parts[3],
  692. ptr = ISI_gInputPtr - 1,
  693. ch;
  694. for ( ; ; )
  695. {
  696. switch ((ch = ISI_gInputLine[++ptr]))
  697. {
  698. case '0' .. '9': parts[part] = parts[part] * 10 + (ch - '0'), ++dp;
  699. case '.':
  700. {
  701. if (part == 0) part = 1, dp = 0;
  702. else break;
  703. }
  704. case 'e', 'E':
  705. {
  706. if (part == 2) break;
  707. else part = 2, ndp = dp;
  708. }
  709. default: break;
  710. }
  711. }
  712. if (ndp) dp = ndp;
  713. // At this point we have 3 integers - the whole part, the fractional part,
  714. // and the exponent:
  715. //
  716. // 4.6e6 == 4600000 == 4, 6, 6
  717. //
  718. return
  719. ret[E_TOKEN_FLOAT_VAL] = Parser_Pow10(float(parts[0]) + float(parts[1]) / Parser_Pow10(1.0, dp), parts[2]),
  720. ISI_gInputPtr = ptr,
  721. 1;
  722. }
  723. /******************************************************************************\
  724. Parser_GetNumber
  725. Parse an unknown number, this could be: hex, octal, binary, decimal, or a
  726. float (including exponents). Loop through assuming its decimal, and if we
  727. find concrete evidence to the contrary then reparse it as that type instead.
  728. \******************************************************************************/
  729. static stock Parser_GetNumber(ret[E_TOKEN])
  730. {
  731. new
  732. num = 0,
  733. ch,
  734. ptr = ISI_gInputPtr;
  735. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_INT;
  736. if (ISI_gInputLine[ptr] == '0')
  737. {
  738. // Hex, binary, or octal (or 0).
  739. switch ((ch = ISI_gInputLine[++ptr]))
  740. {
  741. case 'x', 'X': return Parser_DoHex(ret); // Hex
  742. case 'b', 'B': return Parser_DoBinary(ret); // Binary
  743. case 'e', 'E', '.': return Parser_DoFloat(ret); // Float
  744. case '0' .. '9':
  745. {
  746. new
  747. bool:oct = ('0' <= ch <= '7');
  748. num = ch - '0';
  749. for ( ; ; )
  750. {
  751. switch ((ch = ISI_gInputLine[++ptr]))
  752. {
  753. case '0' .. '7': num = num * 10 + (ch - '0'), oct &= true;
  754. case 'e', 'E', '.': return Parser_DoFloat(ret); // Float
  755. case '8', '9': num = num * 10 + (ch - '0'), oct = false;
  756. default: break;
  757. }
  758. }
  759. if (oct) return Parser_DoOctal(ret);
  760. }
  761. }
  762. }
  763. else
  764. {
  765. // Decimal or float.
  766. // Lookahead.
  767. num = ISI_gInputLine[ptr] - '0';
  768. for ( ; ; )
  769. {
  770. switch ((ch = ISI_gInputLine[++ptr]))
  771. {
  772. case '0' .. '9': num = num * 10 + (ch - '0');
  773. case 'e', 'E', '.': return Parser_DoFloat(ret);
  774. default: break;
  775. }
  776. }
  777. }
  778. return
  779. ret[E_TOKEN_INT_VAL] = num,
  780. // Decimal (default).
  781. ISI_gInputPtr = ptr,
  782. 1;
  783. }
  784. static stock Parser_GetString(ret[E_TOKEN])
  785. {
  786. new
  787. stringSlot;
  788. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_STRING,
  789. ++ISI_gInputPtr;
  790. if ((stringSlot = Parser_ReserveString()) == -1) return Parser_Error("String table full.");
  791. while (ISI_gInputLine[ISI_gInputPtr] != '\"')
  792. {
  793. // Copy the string to (possibly) earlier in the input string.
  794. if (ISI_gInputLine[ISI_gInputPtr]) ISI_gInputLine[ISI_gsStringEnd++] = Parser_DoChar();
  795. else return Parser_Error("Unclosed string literal.");
  796. }
  797. return
  798. ISI_gInputLine[ISI_gsStringEnd++] = '\0',
  799. ret[E_TOKEN_STRING_IDX] = stringSlot,
  800. // Decimal (default).
  801. ++ISI_gInputPtr,
  802. 1;
  803. }
  804. static stock Parser_IsSymbolCharacter(ch)
  805. {
  806. return ('0' <= ch <= '9') || ('a' <= ch <= 'z') || ('A' <= ch <= 'Z') || ch == '_' || ch == '@';
  807. }
  808. static stock Parser_GetSymbol(ret[E_TOKEN])
  809. {
  810. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_NONE;
  811. // Find the end of the symbol (already have the first character).
  812. new
  813. ptr = ISI_gInputPtr + 1;
  814. while (Parser_IsSymbolCharacter(ISI_gInputLine[ptr])) ++ptr;
  815. // Store the next character so we can blank it and get the symbol.
  816. new
  817. tmp = ISI_gInputLine[ptr]; // So we can restore the value later.
  818. ISI_gInputLine[ptr] = '\0';
  819. // Booleans.
  820. if (!strcmp(ISI_gInputLine[ISI_gInputPtr], "false"))
  821. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_BOOL,
  822. ret[E_TOKEN_BOOL_VAL] = false;
  823. else if (!strcmp(ISI_gInputLine[ISI_gInputPtr], "true"))
  824. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_BOOL,
  825. ret[E_TOKEN_BOOL_VAL] = true;
  826. else
  827. {
  828. if (ISI_gFloatTagIndex == -1)
  829. {
  830. ISI_gFloatTagIndex = GetTagIdx("Float");
  831. }
  832. if (ptr - ISI_gInputPtr == 1)
  833. {
  834. #if defined INTROSPECT_PLAYER_DATA
  835. if (IsPlayerConnected(ISI_gCurrentPlayer))
  836. {
  837. new
  838. ch = ISI_gInputLine[ISI_gInputPtr];
  839. if ('a' <= ch <= 'l')
  840. {
  841. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_VAR,
  842. ret[E_TOKEN_SYM_PTR] = ref(ISI_gPlayerInts[ISI_gCurrentPlayer][ch - 'a']);
  843. goto Parser_GetSymbol_return;
  844. }
  845. else if (ch == 'm')
  846. {
  847. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_ARRAY | (e_TOKEN_TYPE:1 << TOKEN_TYPE_SHIFT),
  848. ret[E_TOKEN_SYM_PTR] = ref(ISI_gPlayerStrM[ISI_gCurrentPlayer][0]);
  849. goto Parser_GetSymbol_return;
  850. }
  851. else if (ch == 'n')
  852. {
  853. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_ARRAY | (e_TOKEN_TYPE:1 << TOKEN_TYPE_SHIFT),
  854. ret[E_TOKEN_SYM_PTR] = ref(ISI_gPlayerStrN[ISI_gCurrentPlayer][0]);
  855. goto Parser_GetSymbol_return;
  856. }
  857. else if ('o' <= ch <= 'z')
  858. {
  859. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_FVAR,
  860. ret[E_TOKEN_SYM_PTR] = ref(ISI_gPlayerFlts[ISI_gCurrentPlayer][ch - 'o']);
  861. goto Parser_GetSymbol_return;
  862. }
  863. else if (ch == '@')
  864. {
  865. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_INT,
  866. ret[E_TOKEN_INT_VAL] = ISI_gCurrentPlayer;
  867. goto Parser_GetSymbol_return;
  868. }
  869. }
  870. else
  871. #endif
  872. {
  873. // No player, use default locals.
  874. new
  875. ch = ISI_gInputLine[ISI_gInputPtr];
  876. if ('a' <= ch <= 'l')
  877. {
  878. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_VAR,
  879. ret[E_TOKEN_SYM_PTR] = ref(ISI_gNoPlayerInts[ch - 'a']);
  880. goto Parser_GetSymbol_return;
  881. }
  882. else if (ch == 'm')
  883. {
  884. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_ARRAY | (e_TOKEN_TYPE:1 << TOKEN_TYPE_SHIFT),
  885. ret[E_TOKEN_SYM_PTR] = ref(ISI_gNoPlayerStrM[0]);
  886. goto Parser_GetSymbol_return;
  887. }
  888. else if (ch == 'n')
  889. {
  890. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_ARRAY | (e_TOKEN_TYPE:1 << TOKEN_TYPE_SHIFT),
  891. ret[E_TOKEN_SYM_PTR] = ref(ISI_gNoPlayerStrN[0]);
  892. goto Parser_GetSymbol_return;
  893. }
  894. else if ('o' <= ch <= 'z')
  895. {
  896. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_FVAR,
  897. ret[E_TOKEN_SYM_PTR] = ref(ISI_gNoPlayerFlts[ch - 'o']);
  898. goto Parser_GetSymbol_return;
  899. }
  900. // '@' is undefined for no players.
  901. }
  902. }
  903. {
  904. // See if this symbol is an array/variable.
  905. new
  906. info[E_VARIABLE];
  907. if (GetVariableInfo(ISI_gInputLine[ISI_gInputPtr], info))
  908. {
  909. // Preserve the tag.
  910. // Preserve the dimension information.
  911. if (info[Tag] == ISI_gFloatTagIndex) // switch (info[Dimensions])
  912. {
  913. if (info[Dimensions]) ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_FARRAY | (e_TOKEN_TYPE:info[Dimensions] << TOKEN_TYPE_SHIFT);
  914. else ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_FVAR;
  915. }
  916. else
  917. {
  918. if (info[Dimensions]) ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_ARRAY | (e_TOKEN_TYPE:info[Dimensions] << TOKEN_TYPE_SHIFT);
  919. else ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_VAR;
  920. }
  921. // Convert to a pointer.
  922. ret[E_TOKEN_SYM_PTR] = info[Address];
  923. goto Parser_GetSymbol_return;
  924. }
  925. }
  926. {
  927. // See if this symbol is a normal function.
  928. new
  929. info[E_FUNCTION];
  930. if (GetFunctionInfo(ISI_gInputLine[ISI_gInputPtr], info))
  931. {
  932. if (info[Tag] == ISI_gFloatTagIndex) ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_FFUNC;
  933. else ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_FUNC;
  934. ret[E_TOKEN_FUNC_PTR] = info[Address];
  935. goto Parser_GetSymbol_return;
  936. }
  937. }
  938. #if defined INTROSPECT_NATIVES
  939. {
  940. // See if this symbol is a native function.
  941. new
  942. info = GetNativeIndexFromName(ISI_gInputLine[ISI_gInputPtr]);
  943. if (info != -1)
  944. {
  945. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_NATIVE,
  946. ret[E_TOKEN_NATIVE_IDX] = info;
  947. goto Parser_GetSymbol_return;
  948. }
  949. }
  950. #endif
  951. // Unknown symbol.
  952. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_SYMBOL,
  953. ret[E_TOKEN_STRING_IDX] = Parser_AddString(ISI_gInputPtr);
  954. Parser_Error("Unknown symbol: %s", ISI_gInputLine[ISI_gsStringTable[ret[E_TOKEN_STRING_IDX]]]);
  955. }
  956. Parser_GetSymbol_return:
  957. return
  958. ISI_gInputLine[ptr] = tmp,
  959. ISI_gInputPtr = ptr,
  960. 1;
  961. }
  962. /******************************************************************************\
  963. Parser_GetChar
  964. Gets a number by decoding a single character enclosed in ''s. This includes
  965. various escape sequences, decimals, and hex numbers.
  966. \******************************************************************************/
  967. static stock Parser_DoChar()
  968. {
  969. //ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_INT;
  970. new
  971. ch,
  972. ret[E_TOKEN];
  973. switch ((ch = ISI_gInputLine[ISI_gInputPtr++]))
  974. {
  975. case '\\':
  976. {
  977. switch (ISI_gInputLine[ISI_gInputPtr++])
  978. {
  979. case '\0': return Parser_Error("Invalid escape sequence.");
  980. case 'n': return '\n';
  981. case '\\': return '\\';
  982. case '\'': return '\'';
  983. case 't': return '\t';
  984. case '"': return '\"';
  985. case 'a': return '\a';
  986. case 'b': return '\b';
  987. case 'v': return '\v';
  988. case 'r': return '\r';
  989. case '0' .. '9':
  990. {
  991. --ISI_gInputPtr,
  992. Parser_DoDecimal(ret);
  993. if (ISI_gInputLine[ISI_gInputPtr] == ';') ++ISI_gInputPtr;
  994. }
  995. case 'x', 'X':
  996. {
  997. ISI_gInputPtr -= 2,
  998. Parser_DoHex(ret);
  999. if (ISI_gInputLine[ISI_gInputPtr] == ';') ++ISI_gInputPtr;
  1000. }
  1001. }
  1002. }
  1003. default: return ch;
  1004. }
  1005. return ret[E_TOKEN_INT_VAL];
  1006. }
  1007. static stock Parser_GetChar(ret[E_TOKEN])
  1008. {
  1009. ++ISI_gInputPtr,
  1010. ret[E_TOKEN_TYPE] = e_TOKEN_TYPE_INT,
  1011. ret[E_TOKEN_INT_VAL] = Parser_DoChar();
  1012. if (ISI_gInputLine[ISI_gInputPtr] != '\'') return Parser_Error("Unclosed character literal.");//'
  1013. return
  1014. ++ISI_gInputPtr,
  1015. 1;
  1016. }
  1017. /******************************************************************************\
  1018. |******************************************************************************|
  1019. |******************************************************************************|
  1020. |******************************************************************************|
  1021. |**** ****|
  1022. |**** PARSER ****|
  1023. |**** ****|
  1024. |******************************************************************************|
  1025. |******************************************************************************|
  1026. |******************************************************************************|
  1027. \******************************************************************************/
  1028. static stock Parser_GetLeft(prec)
  1029. {
  1030. new
  1031. token[E_TOKEN] = EMPTY_PARSER_TOKEN,
  1032. pos = ISI_gParsePos;
  1033. if (pos >= sizeof (ISI_gParseTree)) return Parser_Error("Parse Tree full.");
  1034. Parser_GetNextToken(token);
  1035. switch (token[E_TOKEN_TYPE] & TOKEN_TYPE_MASK)
  1036. {
  1037. case e_TOKEN_TYPE_OP:
  1038. {
  1039. switch (token[E_TOKEN_OP])
  1040. {
  1041. case e_TOKEN_OP_OP_BRACKET:
  1042. {
  1043. new
  1044. t2[E_TOKEN];
  1045. t2 = Parser_PeekToken();
  1046. if (t2[E_TOKEN_TYPE] == e_TOKEN_TYPE_OP && t2[E_TOKEN_OP] == e_TOKEN_OP_CL_BRACKET)
  1047. {
  1048. return
  1049. Parser_GetNextToken(t2),
  1050. 0;
  1051. }
  1052. // Start of a new bracketed set.
  1053. pos = Parser_BuildTree(0);
  1054. Parser_GetNextToken(token);
  1055. if (token[E_TOKEN_TYPE] != e_TOKEN_TYPE_OP || token[E_TOKEN_OP] != e_TOKEN_OP_CL_BRACKET)
  1056. {
  1057. new
  1058. pp[32];
  1059. Parser_Print(token, pp);
  1060. return Parser_Error("Expected token \")\", but found: %s", pp);
  1061. }
  1062. }
  1063. case e_TOKEN_OP_OP_BRACE:
  1064. {
  1065. // Start of a new bracketed set.
  1066. pos = Parser_BuildTree(0);
  1067. Parser_GetNextToken(token);
  1068. if (token[E_TOKEN_TYPE] != e_TOKEN_TYPE_OP || token[E_TOKEN_OP] != e_TOKEN_OP_CL_BRACE)
  1069. {
  1070. new
  1071. pp[32];
  1072. Parser_Print(token, pp);
  1073. return Parser_Error("Expected token \")\", but found: %s", pp);
  1074. }
  1075. }
  1076. case e_TOKEN_OP_OP_SQUARE:
  1077. {
  1078. // Start of a new bracketed set.
  1079. pos = Parser_BuildTree(0);
  1080. Parser_GetNextToken(token);
  1081. if (token[E_TOKEN_TYPE] != e_TOKEN_TYPE_OP || token[E_TOKEN_OP] != e_TOKEN_OP_CL_SQUARE)
  1082. {
  1083. new
  1084. pp[32];
  1085. Parser_Print(token, pp);
  1086. return Parser_Error("Expected token \")\", but found: %s", pp);
  1087. }
  1088. }
  1089. case e_TOKEN_OP_SUB: // Prefix, not infix, "-".
  1090. {
  1091. ++ISI_gParsePos,
  1092. token[E_TOKEN_OP] = e_TOKEN_OP_NEG,
  1093. token[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1094. ISI_gParseTree[pos] = token;
  1095. }
  1096. case e_TOKEN_OP_LAND: // Prefix, not infix, "&".
  1097. {
  1098. ++ISI_gParsePos,
  1099. token[E_TOKEN_OP] = e_TOKEN_OP_REF,
  1100. token[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1101. ISI_gParseTree[pos] = token;
  1102. }
  1103. case e_TOKEN_OP_NOT,
  1104. e_TOKEN_OP_INV,
  1105. e_TOKEN_OP_ADD,
  1106. e_TOKEN_OP_PRE_INC,
  1107. e_TOKEN_OP_PRE_DEC,
  1108. e_TOKEN_OP_HASH:
  1109. {
  1110. ++ISI_gParsePos,
  1111. token[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1112. ISI_gParseTree[pos] = token;
  1113. }
  1114. default: return Parser_Error("Expected value, found %s", Parser_PrintOp(token[E_TOKEN_OP]));
  1115. }
  1116. }
  1117. case e_TOKEN_TYPE_ARRAY, e_TOKEN_TYPE_FARRAY:
  1118. {
  1119. // Check for postfix operators.
  1120. new
  1121. t2[E_TOKEN];
  1122. ISI_gParseTree[ISI_gParsePos++] = token;
  1123. for ( ; ; )
  1124. {
  1125. t2 = Parser_PeekToken();
  1126. if (t2[E_TOKEN_TYPE] == e_TOKEN_TYPE_OP)
  1127. {
  1128. switch (t2[E_TOKEN_OP])
  1129. {
  1130. case e_TOKEN_OP_PRE_INC:
  1131. {
  1132. return
  1133. t2[E_TOKEN_OP] = e_TOKEN_OP_POST_INC,
  1134. t2[E_TOKEN_LEFT] = pos,
  1135. t2[E_TOKEN_RIGHT] = -1,
  1136. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2,
  1137. Parser_GetNextToken(t2),
  1138. pos;
  1139. }
  1140. case e_TOKEN_OP_PRE_DEC:
  1141. {
  1142. return
  1143. t2[E_TOKEN_OP] = e_TOKEN_OP_POST_DEC,
  1144. t2[E_TOKEN_LEFT] = pos,
  1145. t2[E_TOKEN_RIGHT] = -1,
  1146. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2,
  1147. Parser_GetNextToken(t2),
  1148. pos;
  1149. }
  1150. case e_TOKEN_OP_OP_BRACKET: return Parser_Error("Not a function.");
  1151. case e_TOKEN_OP_OP_SQUARE:
  1152. {
  1153. t2[E_TOKEN_TYPE] = e_TOKEN_TYPE_INDEX,
  1154. t2[E_TOKEN_LEFT] = pos,
  1155. t2[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1156. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2;
  1157. }
  1158. default: return pos;
  1159. }
  1160. }
  1161. else return pos;
  1162. }
  1163. }
  1164. case e_TOKEN_TYPE_NATIVE, e_TOKEN_TYPE_FUNC, e_TOKEN_TYPE_FFUNC:
  1165. {
  1166. // Check for postfix operators.
  1167. new
  1168. bool:once = false,
  1169. t2[E_TOKEN];
  1170. ISI_gParseTree[ISI_gParsePos++] = token;
  1171. for ( ; ; )
  1172. {
  1173. t2 = Parser_PeekToken();
  1174. if (t2[E_TOKEN_TYPE] == e_TOKEN_TYPE_OP)
  1175. {
  1176. switch (t2[E_TOKEN_OP])
  1177. {
  1178. case e_TOKEN_OP_PRE_INC: return Parser_Error("Cannot increment functions.");
  1179. case e_TOKEN_OP_PRE_DEC: return Parser_Error("Cannot decrement functions.");
  1180. case e_TOKEN_OP_OP_BRACKET:
  1181. {
  1182. if (once) return Parser_Error("Invalid syntax.");
  1183. once = true,
  1184. t2[E_TOKEN_TYPE] = e_TOKEN_TYPE_APPLY,
  1185. t2[E_TOKEN_LEFT] = pos,
  1186. t2[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1187. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2;
  1188. }
  1189. case e_TOKEN_OP_OP_SQUARE:
  1190. {
  1191. t2[E_TOKEN_TYPE] = e_TOKEN_TYPE_INDEX,
  1192. t2[E_TOKEN_LEFT] = pos,
  1193. t2[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1194. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2;
  1195. }
  1196. default: return pos;
  1197. }
  1198. }
  1199. else return pos;
  1200. }
  1201. }
  1202. case e_TOKEN_TYPE_VAR, e_TOKEN_TYPE_FVAR:
  1203. {
  1204. // Check for postfix operators.
  1205. new
  1206. t2[E_TOKEN];
  1207. ISI_gParseTree[ISI_gParsePos++] = token;
  1208. t2 = Parser_PeekToken();
  1209. if (t2[E_TOKEN_TYPE] == e_TOKEN_TYPE_OP)
  1210. {
  1211. switch (t2[E_TOKEN_OP])
  1212. {
  1213. case e_TOKEN_OP_PRE_INC:
  1214. {
  1215. return
  1216. t2[E_TOKEN_OP] = e_TOKEN_OP_POST_INC,
  1217. t2[E_TOKEN_LEFT] = pos,
  1218. t2[E_TOKEN_RIGHT] = -1,
  1219. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2,
  1220. Parser_GetNextToken(t2),
  1221. pos;
  1222. }
  1223. case e_TOKEN_OP_PRE_DEC:
  1224. {
  1225. return
  1226. t2[E_TOKEN_OP] = e_TOKEN_OP_POST_DEC,
  1227. t2[E_TOKEN_LEFT] = pos,
  1228. t2[E_TOKEN_RIGHT] = -1,
  1229. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2,
  1230. Parser_GetNextToken(t2),
  1231. pos;
  1232. }
  1233. case e_TOKEN_OP_OP_BRACKET: return Parser_Error("Not a function.");
  1234. case e_TOKEN_OP_OP_SQUARE: return Parser_Error("Not an array.");
  1235. default: return pos;
  1236. }
  1237. }
  1238. return pos;
  1239. }
  1240. case e_TOKEN_TYPE_SYMBOL:
  1241. {
  1242. // Check for postfix operators.
  1243. new
  1244. bool:once = false,
  1245. t2[E_TOKEN];
  1246. ISI_gParseTree[ISI_gParsePos++] = token;
  1247. for ( ; ; )
  1248. {
  1249. t2 = Parser_PeekToken();
  1250. if (t2[E_TOKEN_TYPE] == e_TOKEN_TYPE_OP)
  1251. {
  1252. switch (t2[E_TOKEN_OP])
  1253. {
  1254. case e_TOKEN_OP_PRE_INC:
  1255. {
  1256. return
  1257. t2[E_TOKEN_OP] = e_TOKEN_OP_POST_INC,
  1258. t2[E_TOKEN_LEFT] = pos,
  1259. t2[E_TOKEN_RIGHT] = -1,
  1260. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2,
  1261. Parser_GetNextToken(t2),
  1262. pos;
  1263. }
  1264. case e_TOKEN_OP_PRE_DEC:
  1265. {
  1266. return
  1267. t2[E_TOKEN_OP] = e_TOKEN_OP_POST_DEC,
  1268. t2[E_TOKEN_LEFT] = pos,
  1269. t2[E_TOKEN_RIGHT] = -1,
  1270. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2,
  1271. Parser_GetNextToken(t2),
  1272. pos;
  1273. }
  1274. case e_TOKEN_OP_OP_BRACKET:
  1275. {
  1276. if (once) return Parser_Error("Invalid syntax.");
  1277. once = true,
  1278. t2[E_TOKEN_TYPE] = e_TOKEN_TYPE_APPLY,
  1279. t2[E_TOKEN_LEFT] = pos,
  1280. t2[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1281. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2;
  1282. }
  1283. case e_TOKEN_OP_OP_SQUARE:
  1284. {
  1285. t2[E_TOKEN_TYPE] = e_TOKEN_TYPE_INDEX,
  1286. t2[E_TOKEN_LEFT] = pos,
  1287. t2[E_TOKEN_RIGHT] = Parser_GetLeft(prec),
  1288. ISI_gParseTree[(pos = ISI_gParsePos++)] = t2;
  1289. }
  1290. default: return pos;
  1291. }
  1292. }
  1293. else return pos;
  1294. }
  1295. }
  1296. default:
  1297. {
  1298. ISI_gParseTree[ISI_gParsePos++] = token;
  1299. }
  1300. }
  1301. return pos;
  1302. }
  1303. stock Parser_BuildTree(prec = cellmin)
  1304. {
  1305. new
  1306. left = Parser_GetLeft(prec),
  1307. token[E_TOKEN];
  1308. for ( ; ; )
  1309. {
  1310. new
  1311. p2 = prec;
  1312. token = Parser_PeekToken();
  1313. switch (token[E_TOKEN_TYPE])
  1314. {
  1315. case e_TOKEN_TYPE_NONE: break; // Done.
  1316. case e_TOKEN_TYPE_OP:
  1317. {
  1318. if ((p2 = ISI_gscOpData[token[E_TOKEN_OP]][E_OPERATOR_DATA_PRECEDENCE]) <= prec) return left;
  1319. }
  1320. default: return Parser_Error("Unexpected token, expected operator.");
  1321. }
  1322. new
  1323. ret = ISI_gParsePos++;
  1324. Parser_GetNextToken(token); // We only peeked, so pop.
  1325. token[E_TOKEN_LEFT] = left;
  1326. token[E_TOKEN_RIGHT] = Parser_BuildTree((p2 == 4) ? (p2 - 1) : p2),
  1327. ISI_gParseTree[ret] = token,
  1328. left = ret;
  1329. }
  1330. return left;
  1331. }
  1332. stock Parser_SetInput(line[], size = sizeof (line))
  1333. {
  1334. IntrospectInit();
  1335. if (size > sizeof (ISI_gInputLine)) return Parser_Error("Insufficient line space.");
  1336. static
  1337. blank[sizeof (ISI_gsStringTable)] = {-1, ...},
  1338. sNoToken[E_TOKEN] = EMPTY_PARSER_TOKEN;
  1339. return
  1340. ISI_gParseTree[0] = sNoToken, // Static "none" token.
  1341. ISI_gsStringEnd = 0,
  1342. ISI_gsStringTable = blank,
  1343. // Pad with one space, so we can store the first symbol correctly.
  1344. ISI_gInputLine[0] = ' ',
  1345. ISI_gInputLine[1] = '\0',
  1346. strcat(ISI_gInputLine, line),
  1347. ISI_gParsePos = 1,
  1348. ISI_gInputPtr = 1,
  1349. 1;
  1350. }
  1351. stock Parser_GetToken(n)
  1352. {
  1353. new
  1354. fail[E_TOKEN] = EMPTY_PARSER_TOKEN;
  1355. if (0 <= n < sizeof (ISI_gParseTree)) return ISI_gParseTree[n];
  1356. return fail;
  1357. }
  1358. /******************************************************************************\
  1359. |******************************************************************************|
  1360. |******************************************************************************|
  1361. |******************************************************************************|
  1362. |**** ****|
  1363. |**** TESTS ****|
  1364. |**** ****|
  1365. |******************************************************************************|
  1366. |******************************************************************************|
  1367. |******************************************************************************|
  1368. \******************************************************************************/
  1369. stock Parser_PrintExpr(str[], size, tree[][E_TOKEN], entry)
  1370. {
  1371. str[0] = '\0',
  1372. _Parser_PrintExpr(str, size, tree, entry);
  1373. }
  1374. stock RenderToken(str[], token[E_TOKEN], size = sizeof (str))
  1375. {
  1376. str[0] = '\0',
  1377. _Parser_RenderToken(str, size, token);
  1378. }
  1379. static stock _Parser_RenderToken(str[], size, token[E_TOKEN])
  1380. {
  1381. switch (token[E_TOKEN_TYPE] & TOKEN_TYPE_MASK)
  1382. {
  1383. case e_TOKEN_TYPE_STRING: format(str, size, "\"%s\"", ISI_gInputLine[ISI_gsStringTable[token[E_TOKEN_STRING_IDX]]]);
  1384. case e_TOKEN_TYPE_FLOAT: format(str, size, "%.2f", token[E_TOKEN_FLOAT_VAL]);
  1385. case e_TOKEN_TYPE_ARRAY: ReadAmxMemoryArray(token[E_TOKEN_SYM_PTR], str, size);
  1386. case e_TOKEN_TYPE_FVAR: format(str, size, "%.2f", Float:ReadAmxMemory(token[E_TOKEN_SYM_PTR]));
  1387. case e_TOKEN_TYPE_VAR: format(str, size, "%d", ReadAmxMemory(token[E_TOKEN_SYM_PTR]));
  1388. case e_TOKEN_TYPE_INT: valstr(str, token[E_TOKEN_INT_VAL]);
  1389. case e_TOKEN_TYPE_BOOL: strcat(str, (token[E_TOKEN_BOOL_VAL]) ? ("true") : ("false"), size);
  1390. }
  1391. }
  1392. static stock _Parser_PrintToken(str[], size, token[E_TOKEN], bool:bracket)
  1393. {
  1394. switch (token[E_TOKEN_TYPE] & TOKEN_TYPE_MASK)
  1395. {
  1396. case e_TOKEN_TYPE_STRING: format(str, size, "%s\"%s\"", str, ISI_gInputLine[ISI_gsStringTable[token[E_TOKEN_STRING_IDX]]]);
  1397. case e_TOKEN_TYPE_FLOAT: format(str, size, "%s%.2f", str, token[E_TOKEN_FLOAT_VAL]);
  1398. case e_TOKEN_TYPE_NATIVE:
  1399. {
  1400. new name[32];
  1401. GetNativeNameFromIndex(token[E_TOKEN_NATIVE_IDX], name);
  1402. strcat(str, name, size);
  1403. }
  1404. case e_TOKEN_TYPE_FUNC, e_TOKEN_TYPE_FFUNC:
  1405. strcat(str, GetFunctionFromAddress(token[E_TOKEN_FUNC_PTR]), size);
  1406. case e_TOKEN_TYPE_VAR, e_TOKEN_TYPE_FVAR, e_TOKEN_TYPE_ARRAY, e_TOKEN_TYPE_FARRAY:
  1407. {
  1408. new
  1409. ch = Parser_GetLocalName(token[E_TOKEN_SYM_PTR]);
  1410. if (ch == '-') strcat(str, GetVariableFromAddress(token[E_TOKEN_SYM_PTR]), size);
  1411. else format(str, size, "%s%c", str, ch);
  1412. }
  1413. case e_TOKEN_TYPE_INT: format(str, size, "%s%d", str, token[E_TOKEN_INT_VAL]);
  1414. case e_TOKEN_TYPE_BOOL: strcat(str, (token[E_TOKEN_BOOL_VAL]) ? ("true") : ("false"), size);
  1415. case e_TOKEN_TYPE_OP:
  1416. if (bracket) format(str, size, "%s(%s)", str, Parser_PrintOp(token[E_TOKEN_OP]));
  1417. else format(str, size, "%s%s", str, Parser_PrintOp(token[E_TOKEN_OP]));
  1418. case e_TOKEN_TYPE_APPLY: strcat(str, "()", size);
  1419. case e_TOKEN_TYPE_INDEX: strcat(str, "[]", size);
  1420. case e_TOKEN_TYPE_SYMBOL: format(str, size, "%s<<<%s>>>", str, ISI_gInputLine[ISI_gsStringTable[token[E_TOKEN_STRING_IDX]]]);
  1421. }
  1422. }
  1423. static stock _Parser_PrintExpr(str[], size, tree[][E_TOKEN], entry)
  1424. {
  1425. new
  1426. bool:bracket = false;
  1427. switch (tree[entry][E_TOKEN_TYPE])
  1428. {
  1429. case e_TOKEN_TYPE_INDEX:
  1430. {
  1431. _Parser_PrintExpr(str, size, tree, tree[entry][E_TOKEN_LEFT]);
  1432. strcat(str, "[", size);
  1433. _Parser_PrintExpr(str, size, tree, tree[entry][E_TOKEN_RIGHT]);
  1434. strcat(str, "]", size);
  1435. return;
  1436. }
  1437. case e_TOKEN_TYPE_APPLY:
  1438. {
  1439. _Parser_PrintExpr(str, size, tree, tree[entry][E_TOKEN_LEFT]);
  1440. strcat(str, "(", size);
  1441. _Parser_PrintExpr(str, size, tree, tree[entry][E_TOKEN_RIGHT]);
  1442. strcat(str, ")", size);
  1443. return;
  1444. }
  1445. case e_TOKEN_TYPE_OP: bracket = tree[entry][E_TOKEN_OP] != e_TOKEN_OP_COMMA;
  1446. }
  1447. if (bracket) strcat(str, "(", size);
  1448. if (tree[entry][E_TOKEN_LEFT] != -1) _Parser_PrintExpr(str, size, tree, tree[entry][E_TOKEN_LEFT]);
  1449. _Parser_PrintToken(str, size, tree[entry], false);
  1450. if (tree[entry][E_TOKEN_RIGHT] != -1) _Parser_PrintExpr(str, size, tree, tree[entry][E_TOKEN_RIGHT]);
  1451. if (bracket) strcat(str, ")", size);
  1452. }
  1453. stock Parser_PrintTree(str[], size, tree[][E_TOKEN], entry)
  1454. {
  1455. str[0] = '\0',
  1456. _Parser_PrintTree(str, size, tree, entry, 0);
  1457. }
  1458. static stock _Parser_PrintTree(str[], size, tree[][E_TOKEN], entry, indent)
  1459. {
  1460. static const
  1461. sIndents[] = "| | | | | | | | | | | | | | | |- ";
  1462. strcat(str, sIndents[(sizeof (sIndents) - 1) - indent], size);
  1463. _Parser_PrintToken(str, size, tree[entry], true);
  1464. strcat(str, "\n", size);
  1465. if (tree[entry][E_TOKEN_LEFT] != -1) _Parser_PrintTree(str, size, tree, tree[entry][E_TOKEN_LEFT], indent + 3);
  1466. if (tree[entry][E_TOKEN_RIGHT] != -1) _Parser_PrintTree(str, size, tree, tree[entry][E_TOKEN_RIGHT], indent + 3);
  1467. }
  1468. #if defined INTROSPECT_PARSER_TEST
  1469. // "P"arser "T"est "N"umber.
  1470. #define PTN(%1) ISI_gInputLine=#%1,ISI_gInputPtr=0,Parser_GetNextToken(ret),printf("%s: \"%s\"",(ret[E_TOKEN_TYPE]==e_TOKEN_TYPE_INT&&ret[E_TOKEN_INT_VAL]==%1)?("PASS"):("FAIL"),ISI_gInputLine)
  1471. // "P"arser "T"est "F"loat.
  1472. #define PTF(%1) ISI_gInputLine=#%1,ISI_gInputPtr=0,Parser_GetNextToken(ret),printf("%s: \"%s\"",(ret[E_TOKEN_TYPE]==e_TOKEN_TYPE_FLOAT&&ret[E_TOKEN_FLOAT_VAL]==%1)?("PASS"):("FAIL"),ISI_gInputLine)
  1473. // "P"arser "T"est "O"ctal (no native PAWN representation).
  1474. #define PTO(%0,%1) ISI_gInputLine=#%0,ISI_gInputPtr=0,Parser_GetNextToken(ret),printf("%s: \"%s\"",(ret[E_TOKEN_TYPE]==e_TOKEN_TYPE_INT&&ret[E_TOKEN_INT_VAL]==%1)?("PASS"):("FAIL"),ISI_gInputLine)
  1475. #define TEST_OP(%1) ISI_gInputLine=#%1,ISI_gInputPtr=0,Parser_GetNextToken(ret),printf("%s: \"%s\"",(ret[E_TOKEN_TYPE]==e_TOKEN_TYPE_OP&&!strcmp(Parser_PrintOp(ret[E_TOKEN_OP]),#%1))?("PASS"):("FAIL"),ISI_gInputLine)
  1476. main()
  1477. {
  1478. IntrospectInit();
  1479. print("\n-------------------------");
  1480. print(" Introspect parser tests");
  1481. print("-------------------------\n");
  1482. new
  1483. ret[E_TOKEN];
  1484. // Test numbers.
  1485. PTN(70);
  1486. PTN(0800);
  1487. PTN(0x45);
  1488. PTN(0b11);
  1489. PTN(0b01010101);
  1490. PTN(2345);
  1491. PTF(5.5);
  1492. PTF(9.5e1);
  1493. PTN(77);
  1494. PTF(66.123);
  1495. PTF(0.1);
  1496. PTO(0500, 320);
  1497. PTO(01234, 668);
  1498. // These are a little awkward, because we are simulating run-time input.
  1499. PTN('f');
  1500. PTO('\\n', '\n');
  1501. PTN('7');
  1502. PTN('@');
  1503. PTN('_');
  1504. PTO("'\\x45;'", '\x45;');
  1505. PTO('\\01', '\01');
  1506. PTO("'\\x11;'", '\x11;');
  1507. // Especially these two...
  1508. PTO('\\\\', '\\');
  1509. PTO('\\\'', '\'');
  1510. TEST_OP("=");
  1511. TEST_OP("==");
  1512. TEST_OP("<=");
  1513. TEST_OP(">=");
  1514. TEST_OP("<");
  1515. TEST_OP(">");
  1516. TEST_OP("!");
  1517. TEST_OP("!=");
  1518. TEST_OP("~");
  1519. TEST_OP("~=");
  1520. TEST_OP("+");
  1521. TEST_OP("+=");
  1522. TEST_OP("-");
  1523. TEST_OP("-=");
  1524. TEST_OP("*");
  1525. TEST_OP("*=");
  1526. TEST_OP("/");
  1527. TEST_OP("/=");
  1528. TEST_OP("%");
  1529. TEST_OP("%=");
  1530. TEST_OP("^");
  1531. TEST_OP("^=");
  1532. TEST_OP("&");
  1533. TEST_OP("&=");
  1534. TEST_OP("|");
  1535. TEST_OP("|=");
  1536. TEST_OP(">>");
  1537. TEST_OP(">>=");
  1538. TEST_OP(">>>");
  1539. TEST_OP(">>>=");
  1540. TEST_OP("<<");
  1541. TEST_OP("<<=");
  1542. TEST_OP("&&");
  1543. TEST_OP("||");
  1544. TEST_OP("(");
  1545. TEST_OP(")");
  1546. TEST_OP("{");
  1547. TEST_OP("}");
  1548. TEST_OP("[");
  1549. TEST_OP("]");
  1550. TEST_OP("++");
  1551. TEST_OP("--");
  1552. TEST_OP("...");
  1553. TEST_OP("..");
  1554. TEST_OP("#");
  1555. TEST_OP("::");
  1556. #if defined INTROSPECT_PLAYER_DATA
  1557. ISI_gCurrentPlayer = 45;
  1558. #endif
  1559. //ISI_gInputLine = "34 0x55 7.7 \"Hello \\\"there\\\"\" 'a' MyFuncSymbol",
  1560. Parser_SetInput(" -someVar + 5 * ((44) + 5) / func(a, b, c) * arr[5][6][xx[5]] - someVar++ - ++someVar - someVar-- - --someVar");
  1561. new
  1562. pos = Parser_BuildTree(cellmin),
  1563. str[32],
  1564. output[2048];
  1565. //print(Parser_PrintTree(ISI_gParseTree, pos));
  1566. Parser_PrintTree(output, sizeof (output), ISI_gParseTree, pos);
  1567. print(output);
  1568. Parser_PrintExpr(output, sizeof (output), ISI_gParseTree, pos);
  1569. print(output);
  1570. while (pos != ISI_gParsePos)
  1571. {
  1572. Parser_Print(ISI_gParseTree[pos], str);
  1573. print(str);
  1574. ++pos;
  1575. }
  1576. //new str[32];
  1577. while (Parser_GetNextToken(ret))
  1578. {
  1579. Parser_Print(ret, str);
  1580. print(str);
  1581. }
  1582. TEST_OP("\"");
  1583. TEST_OP("\'");//'
  1584. Parser_SetInput(" 70 5.5 0800 0100 0x345 0b11 0.888 0.888e3");
  1585. //new
  1586. // ret[E_TOKEN];
  1587. printf("%d", e_TOKEN_TYPE_INT);
  1588. Parser_GetNextToken(ret);
  1589. printf("T = %d %d", ret[E_TOKEN_TYPE], ret[E_TOKEN_INT_VAL]);
  1590. Parser_GetNextToken(ret);
  1591. printf("T = %d %.1f", ret[E_TOKEN_TYPE], ret[E_TOKEN_FLOAT_VAL]);
  1592. Parser_GetNextToken(ret);
  1593. printf("T = %d %04d", ret[E_TOKEN_TYPE], ret[E_TOKEN_INT_VAL]);
  1594. Parser_GetNextToken(ret);
  1595. printf("T = %d %04x", ret[E_TOKEN_TYPE], ret[E_TOKEN_INT_VAL]);
  1596. Parser_GetNextToken(ret);
  1597. printf("T = %d 0x%x", ret[E_TOKEN_TYPE], ret[E_TOKEN_INT_VAL]);
  1598. Parser_GetNextToken(ret);
  1599. printf("T = %d 0b%b", ret[E_TOKEN_TYPE], ret[E_TOKEN_INT_VAL]);
  1600. Parser_GetNextToken(ret);
  1601. printf("T = %d %f", ret[E_TOKEN_TYPE], ret[E_TOKEN_FLOAT_VAL]);
  1602. Parser_GetNextToken(ret);
  1603. printf("T = %d %f", ret[E_TOKEN_TYPE], ret[E_TOKEN_FLOAT_VAL]);
  1604. // BUG: Using "(a, b)" as the FIRST parameter doesn't work. Others do.
  1605. Parser_SetInput("Parser_FakeOne((Parser_FakeThree, 77), Parser_FakeTwo(), (7, 57))");
  1606. pos = Parser_BuildTree(cellmin);
  1607. //print(Parser_PrintTree(ISI_gParseTree, pos));
  1608. Parser_PrintTree(output, sizeof (output), ISI_gParseTree, pos);
  1609. print(output);
  1610. Parser_SetInput("f = g = h + 55");
  1611. pos = Parser_BuildTree(cellmin);
  1612. //print(Parser_PrintTree(ISI_gParseTree, pos));
  1613. Parser_PrintTree(output, sizeof (output), ISI_gParseTree, pos);
  1614. print(output);
  1615. Parser_SetInput("Parser_FakeThree");
  1616. pos = Parser_BuildTree(cellmin);
  1617. //print(Parser_PrintTree(ISI_gParseTree, pos));
  1618. Parser_PrintTree(output, sizeof (output), ISI_gParseTree, pos);
  1619. print(output);
  1620. Parser_SetInput("Parser_FakeTwo(one)");
  1621. pos = Parser_BuildTree(cellmin);
  1622. //print(Parser_PrintTree(ISI_gParseTree, pos));
  1623. Parser_PrintTree(output, sizeof (output), ISI_gParseTree, pos);
  1624. print(output);
  1625. Parser_FakeOne();
  1626. Parser_FakeTwo();
  1627. }
  1628. // Variables we later get the address of.
  1629. stock Parser_FakeThree;
  1630. stock Parser_FakeTwo()
  1631. {
  1632. }
  1633. stock Parser_FakeOne()
  1634. {
  1635. printf("%d", Parser_FakeThree);
  1636. }
  1637. #endif
  1638. /******************************************************************************\
  1639. |******************************************************************************|
  1640. |******************************************************************************|
  1641. |******************************************************************************|
  1642. |**** ****|
  1643. |**** STRINGS ****|
  1644. |**** ****|
  1645. |******************************************************************************|
  1646. |******************************************************************************|
  1647. |******************************************************************************|
  1648. \******************************************************************************/
  1649. stock Parser_AddString(start)
  1650. {
  1651. new
  1652. i = 0;
  1653. for ( ; i != sizeof (ISI_gsStringTable); ++i)
  1654. {
  1655. if (ISI_gsStringTable[i] == -1) break;
  1656. }
  1657. if (i == sizeof (ISI_gsStringTable)) return -1;
  1658. ISI_gsStringTable[i] = ISI_gsStringEnd;
  1659. while ((ISI_gInputLine[ISI_gsStringEnd++] = ISI_gInputLine[start++])) {}
  1660. return i;
  1661. }
  1662. stock Parser_ReserveString()
  1663. {
  1664. new
  1665. i = 0;
  1666. for ( ; i != sizeof (ISI_gsStringTable); ++i)
  1667. {
  1668. if (ISI_gsStringTable[i] == -1) break;
  1669. }
  1670. if (i == sizeof (ISI_gsStringTable)) return -1;
  1671. ISI_gsStringTable[i] = ISI_gsStringEnd;
  1672. return i;
  1673. }
  1674. stock Parser_RemoveString(idx)
  1675. {
  1676. if (idx == -1) return;
  1677. new
  1678. rem = ISI_gsStringTable[idx];
  1679. if (rem == -1) return;
  1680. for ( ; ; )
  1681. {
  1682. new
  1683. top = cellmax,
  1684. found = -1;
  1685. // Find the next highest slot string.
  1686. for (new i = 0; i != sizeof (ISI_gsStringTable); ++i)
  1687. {
  1688. if (rem < ISI_gsStringTable[i] < top)
  1689. {
  1690. top = ISI_gsStringTable[i],
  1691. found = i;
  1692. }
  1693. }
  1694. if (found == -1) break;
  1695. ISI_gsStringTable[found] = rem;
  1696. // There must be a faster way than this... Given that the ranges may be
  1697. // overlapping.
  1698. while ((ISI_gInputLine[rem++] = ISI_gInputLine[top++])) {}
  1699. }
  1700. ISI_gsStringTable[idx] = -1;
  1701. }
  1702. stock Parser_InsertString(str[])
  1703. {
  1704. new
  1705. i = 0;
  1706. for ( ; i != sizeof (ISI_gsStringTable); ++i)
  1707. {
  1708. if (ISI_gsStringTable[i] == -1) break;
  1709. }
  1710. if (i == sizeof (ISI_gsStringTable)) return -1;
  1711. ISI_gsStringTable[i] = ISI_gsStringEnd;
  1712. new
  1713. idx = 0;
  1714. while ((ISI_gInputLine[ISI_gsStringEnd++] = str[idx++])) {}
  1715. return i;
  1716. }