From 4812d47285f6d0ce94273f7a5f418ee5cd075639 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 14 May 2020 10:40:30 -0500 Subject: [PATCH] Added hash table iteration --- bh.h | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++---- onyx | Bin 41536 -> 42168 bytes onyx.c | 33 ++++++++++------------------ onyxlex.c | 38 ++++++++++++++++++++++++++++++++ onyxlex.h | 3 +++ 5 files changed, 111 insertions(+), 26 deletions(-) diff --git a/bh.h b/bh.h index 22c808a9..da236743 100644 --- a/bh.h +++ b/bh.h @@ -242,11 +242,12 @@ void bh__arr_deleten(void **arr, i32 elemsize, i32 index, i32 numelems); #define BH__HASH_STORED_KEY_SIZE 64 typedef struct bh__hash_entry { char key[BH__HASH_STORED_KEY_SIZE]; - // Value follows + i32 value; // NOTE: Not actually an i32, just used as a placeholder for offset } bh__hash_entry; #define BH__HASH_MODULUS 1021 -#define BH__HASH_KEYSIZE 16 +#define BH__HASH_KEYSIZE 64 +#ifdef BH_DEFINE u64 bh__hash_function(const char* str, i32 len) { u64 hash = 5381; i32 c, l = 0; @@ -258,6 +259,13 @@ u64 bh__hash_function(const char* str, i32 len) { return hash % BH__HASH_MODULUS; } +#endif + +typedef struct bh_hash_iterator { + ptr *tab, *endtab, arr; + i32 elemsize, arridx; + bh__hash_entry* entry; +} bh_hash_iterator; #define bh_hash(T) T* @@ -277,12 +285,18 @@ u64 bh__hash_function(const char* str, i32 len) { #define bh_hash_delete(T, tab, key) (bh__hash_delete((ptr *) tab, sizeof(T), key)) #endif +#define bh_hash_iter_setup(T, tab) (assert(sizeof(T) == sizeof(*(tab))), bh__hash_iter_setup((ptr *) tab, sizeof(T))) +#define bh_hash_iter_key(it) (it.entry->key) +#define bh_hash_iter_value(T, it) (assert(sizeof(T) == it.elemsize), *(T *)&(it.entry->value)) + b32 bh__hash_init(ptr **table); b32 bh__hash_free(ptr **table); ptr bh__hash_put(ptr *table, i32 elemsize, char *key); b32 bh__hash_has(ptr *table, i32 elemsize, char *key); ptr bh__hash_get(ptr *table, i32 elemsize, char *key); void bh__hash_delete(ptr *table, i32 elemsize, char *key); +bh_hash_iterator bh__hash_iter_setup(ptr *table, i32 elemsize); +b32 bh_hash_iter_next(bh_hash_iterator* it); #endif @@ -662,6 +676,8 @@ b32 bh__arr_grow(void** arr, i32 elemsize, i32 cap) { if (cap == 0 && elemsize == 0) return 1; arrptr = (bh__arr *) malloc(sizeof(*arrptr) + elemsize * cap); + if (arrptr == NULL) return 0; + arrptr->capacity = cap; arrptr->length = 0; @@ -793,7 +809,7 @@ b32 bh__hash_free(ptr **table) { ptr bh__hash_put(ptr *table, i32 elemsize, char *key) { u64 index = bh__hash_function(key, 0); - elemsize += sizeof(bh__hash_entry); + elemsize += BH__HASH_STORED_KEY_SIZE; ptr arrptr = table[index]; i32 len = bh_arr_length(arrptr); @@ -821,9 +837,9 @@ b32 bh__hash_has(ptr *table, i32 elemsize, char *key) { u64 index = bh__hash_function(key, 0); ptr arrptr = table[index]; - i32 len = bh_arr_length(arrptr); if (arrptr == NULL) return 0; + i32 len = bh_arr_length(arrptr); i32 stride = elemsize + BH__HASH_STORED_KEY_SIZE; while (len--) { @@ -874,6 +890,45 @@ void bh__hash_delete(ptr *table, i32 elemsize, char *key) { bh__arr_deleten((void **) &arrptr, elemsize, i, 1); } +bh_hash_iterator bh__hash_iter_setup(ptr *table, i32 elemsize) { + bh_hash_iterator it = { + .tab = table, + .endtab = table + BH__HASH_MODULUS, + .arr = NULL, + .elemsize = elemsize, + .entry = NULL + }; + return it; +} + +b32 bh_hash_iter_next(bh_hash_iterator* it) { + if (it->tab == NULL) return 0; + + if (it->entry != NULL) { + it->arridx++; + if (it->arridx >= bh_arr_length(it->arr)) { + it->tab++; + goto step_to_next; + } + + it->entry = (bh__hash_entry *)((char *)(it->entry) + BH__HASH_STORED_KEY_SIZE + it->elemsize); + return 1; + } + +step_to_next: + // Set forward to find next valid + while (*it->tab == NULL && it->tab != it->endtab) { + it->tab++; + } + + if (it->tab == it->endtab) return 0; + + it->arr = *it->tab; + it->entry = it->arr; + it->arridx = 0; + return 1; +} + #endif // ifndef BH_NO_HASHTABLE #endif // ifdef BH_DEFINE diff --git a/onyx b/onyx index e6cb94a24b220508298f7e54c473440ad335c933..8f837e0e1b922cc10e8a170268a9541a09eda703 100755 GIT binary patch literal 42168 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 W*O7q7tN+3Gcm?{L&Ul%M%Krtf)v7`O literal 41536 zcmeHw3wTu3wf{ad$>flbnS}5N2r@yQQj&mxprA=$a3To_AyKH{5R%EG$TTfd+o>B=bSzJJO!(4n#R;+XV)<*r8os7MQQEbQPZsR8qca zDK8F7e<|xzsp4A;KGO3ay;3A$iL7rVzjRCeRVu4zS#`Br7B9@ItDIL?+YsC_Z^x3w z^A<16Y-!9~!0jgaM0>-UGF}t4w-m+kV^Jm;;r(}?Sad1>;;x^qJM)|EuN-N<_?_3T zCff1%M>4owqGB$B;7i|WQ=x&<@aro8jTsJRj{@e70Z#%f7X9uK;B!WRliji8+<2 zdj$CE5#YCv0KaJj_)CDh@y~iK1|XK6%SV7`i~zrF1bF=j@Uvbyt z)2u+0sXwK%bhdx3n`2dfWQf-a3eUx?DHv#BK3_|qyke`bqGqeFs=T(2HT%o!>KZFp zOQ5;V-@xix{Qj-1-d|tQw3F2T=F-9yb&U=F(()~JB(u7{u|dl83DTH^@C9`p8~@KPQ!3FYC7|N3 zprL+e$3M&i_(#`QI=_l;7{_QDAlTU2+GOg%_sDW^Qtc?>{Q=5!sc}{LKgA{BUO9d$ zc#oWC^kO$BP;gatTi}%og`C+I_;v};w!qsZe2E2qRKjyC@JA)wYk|KY;l&nsSi;v^ z;MyXg=Vl9hqJ-C2;Mo%1WPz`e@EsQTW(nVKf!`+Khb-_fOL&I`eoVp-Ti{Pg_)!b| zRSCb}0zWU|4_n{~G|=EWZh=pc@NNryp@g5ZzzZb2#{&0Dc&`P1n}qjS;9rvPehd6Q z2|sUvcS-o51^&E*Gs`%0PQrBy{E~#HSm0x>7XC@Mz_TUXZGn3ve6|ICtAuA;;4Koq z!~zdVc#Z}BO$ql};6IY^VhjAFgs->2PfPe_3;bOPud%=rmIyyIS>PEGzQY1vCgHtB zZq7(+1RBlM)n|eyDj?E+6MVD@e%=HhYl07&;Nwj2{Zb!Vi;g$J*Gu{Yz-atb*Jcx( z);;Q~F~QYZj&MyTxOu(1!vr_4_x79MRJXbgnc!+{C0vIIj)B{_4x8Y#CQ{c?6C4A- zaoul%I}Ipf51Zg}=;zquCU}a8zS{&(HNj7r;O6y8j|rY;qW8AGrF+}rlUKNz_h5Ix zHq_&7eM*1QpcqHCGkX`ER)>Q_~D&^YS}XrcfSm^YWWirY0Il;pNw;?4&Z|B(x!gR)l#@(0eW*1#kS8~u& z_`1y79zUOazI4zVIvbdXCfEfUYJ%iVLw!}5uBivO{7p}i*CS698+yqbI@$j_c+(s540>Dl46?nuK+)G$_F^bSkQRf~18z#o24!C1+_DV& zq}b3CGMnz5^Mp6l)7q_hD|#duk)w7la?q;@Qb;~d@fwalPL@3TBx&B}NeOj(+s8gl zAT-Xx95}fx&bEnTVOJCEIt;ryDgmA`o2X#I{O)iw>geDWwijzWj|##|VnHR$?Tt{9 zhT!HJcED&dj7xJp!j>fl$3>yra#FlYp9tP#qH#Ue4UfK$_(kX-j7-7=wd>$UG|ov+ z4>wGy8uIjdPkQ>u4N{mJ=D=0b6z)~h!{k+1?>Qf%hTv#O=L5h|bSou-^v`k~d>kWz z0(sFk1isRB@cU+Pd$Em^z;BQQOoRh^R-N?xKw|^1paw%w#DD)3Ps`Sk?l;U`Yf?#? zOXGr}r7}0T$MsXs4^XNKd46DE|H(Gw=+gDERLqhp_Wv)bSk=1c2h4SFG6vZHJ^y%l z(D#aA#M|0$L%jD5{1Q`(w>{WHdi{r;nzw!2%IQeZ?M8htG<2}rb#RH9hNd#m%#t)` z|0ZZAm}%k!O`@cET++OUY0apMra;Jf^9oVdHzdvP%rrDDg63ICvs2Ri*i1uHA85WW zY04zcm(4WD6U`ST&3sAIY^I?p6*LW!CRx&~HPg^E44So)X5g>F_G~i^O}(JWmNZXG z8kd=dren~gN}6v;nm@r_!#^}dgXZEiBxs90lIB-2XnrecHb|NW%`_=O&c92VMUtk? zOhYRy)YTzrQYFo2%rvyx0!@RYd3#XUo^Ph1l^19VB+avuX11AzR@0!lQqtTjX%fsd zw6X?`E@?g|Y0e>L4FAw78#L!Kkib8iB+b)inhApDDM_ zq%_r&D_!lQc`sH0TdRGf&clBu%=R24f1*BuN^-qj^Upff@T2r zQC+!`<|Q-DOhI!}(oB&wKQYtH5;XTpn!mm)Z2t<;w0U|ld3s{Rbt+s`6W`UgOB07E^kg+cQ$%?((r z%!VNY-?JO$E}P~$_&bdo$rqO}wwsJqV*dxMbRGP$Q9<-V<>5gV zvQQcKKcKMd;2okO=x2%0aAQZfz9amZj&OBHxUwT$-VwgFBYaCoczs8>tRq~~5iaTo z7j%U4JHo3v!Yew$IUV8U9pP&_!dG{M7j}f_cZ4%L!gD*qvpd2wI>OUB!c#lKlRLr_ zJHq2T!f74hl#Xz6M>w$~oX`=D>j-O5q3|$l?Gg8*XzR7&ezUC%cdfZ8DAO(2dF0(l zL0ULi>Ah++zvBzU_b>bN(2%%e3=JOgT-v|q(&oJm{N1&8H2&u7O~&6(?@KV>V2WEv zMV`e;mc}BXy%gZ@neueoWKXVgTLovoxvw=|4(`bQ9ld2K-`bP26vl^t>5)X3b^}7=o5iI z$SedoNT$3mH}1T%ap#S#1HJ_Bq3J69PZ%gDWKVkfsR}RwPWPsTy(9}w3l&t;Qd3fG zy@s!HAP_Mh>;|-(1m67i&``*8y3KRii<{h&{Xa#SDmdxs zz+BCDQozi`Z4+^s4|%{UDzr)=2;*=MiLH=aLh*ed5K<3ELe)HuY@bx58^U5s8m?6lSCRXePY`blZ;3$(2);l zhO@E_XJO|JEW+ZYScZMRRm2YrKiU78H@OQ9|MW)t@BRDW)iAAeRZENwWiXBrt@HQRGb#fiJOLc>&$m#LUC0l8)Fp+ot_JygDBAmJl z`lI2rzj?J6DDDx1@lfC7)e&3f8w0WvM%5_0PIQ!5-Oru-7r5P#n`%i0J++AMmulM$F2Dx`yvTrw?zqUqB;3fi&uo-6z_d z6xBT8u^@+U(J1Z3#EM4a4Fy<=fojDNPeUUnoE`wri=p91xKYNi{#cA2t)_=KIh8=6 z6q0Qc(kFy82q7=iZgIeW(sK!(V&S={1w0I%K+|i_g?{60A5HoQL6;EKu1B;(wpPz2 zt*uOs7+#&KnDe+dbP64-`Gg=RM*ter4LWxN;oBGe3b**wgI-0~j#wldMHC`Nkb>%& zpJVmK`rkemA;nM@3Z6OXxrp&{2y+*o9@{);S_id&8-JP;S_f@`E5p}r*kwCyo6f6xeEIE3Qt0Y>I$bKlSe3>GC*|*wR<0Z1Uhlu zxuyL};Peo0P2q<&EQ5E-=@26WA1rze$4DD!xf8q?8R2OOA;O&dGunqa%7AAE&Q5bTAQPMk$si)S6DSRe^BprdB7%(cak2uWDvgvw4qVmBlnw>)Yv zt#^7+Q9BI`#PGtS)F!B`nLJGPE%o#SFGr5Z+RD126J-7x6r0X)bXi5~p zQ$YV-qH!B`Txfe7*z-zTZ`&SP3@=lQ;Vh6xLLju~Ef~;8b7ZKnmk(RCN&=8-zCwr= z4}H)YP?ce6*}A7!RMZ>OEk>{ocg1<$jfBtJDK_bm(+l*z8o8pH`WT;_qu1}dUpJ}D zrT=}&kV*mgm=ryF1koA8M3XyWh$lJJOuP*Z#bq1*KQb` zL3GV9(Qz+$&X9AFXCe>7{sZ&6gOy}}v1 zaY){`@GwCtbRI+EGdxB(v7t{6^f_e>s5Xoj?Q{dgZSY`QUKCIEFBTf2TcAsFl9T=8 zg&X=%6IvxY#5VVt+9ZWHDWBFb^Fu!yurLkxAmnDtEeQ8iDEMNC20mJ}(4*`iT+_pX zDXn{6goF6K#lRoI+U9xD^$;{ZjLjA<`UVm$9xk58&>1R@BX5d&2L25kN@i<6=*f$o z^KA@++#V^lP0*Zg%ZUSY?^aHb6BqKl6&}~R=PkB30ppO?jXO(B8w_9+ul4loeqE^Y z7F21Mi%;Rkr~kk;5~Ec>tbkO-Wp6>jupGe%bzU+fEG(lsA7C&ohRWb@ns>Nc5_vBe z_?%FhLoJ5&xe7gfVpB%g)VC)O^C`U6H%!$@AE#>H2&y9FW2vf?6zWjlL9ag9pYVI$ z^yp(y8S}0YkgC~-#Uw%?%A}CzjGDdL%FeXmwSabyTy8undL1IPcn~&*Y+MOh$m5aF z#$fr2#_b&L^2JJJ=)a_1Z9$rs7OHvaYk)`T*e}{3RCqdug%nABdum$uoMwCdWHK!( z@kYXF?YTKUsQ3(A&U;HDrWgXh<9evrd^6HHU`B!XbY15b_)ahsxhC z^1RalhFxlY1A*TCu!-t8f~K1$8>ELR^bj_OAEg)99;2Oiip|?-*rdU&z3iwQ18)@J zdYIm(aX}i!nSQ;E;Q>Q9o-dV1iXq?{KJEt5#vr7yv$cD*P$ETJsK@(wpACaC5<6}$ zXnP9d8!h?N?vfZtEgOfR!g}6yu#yH~zKIyUZhHS!Q+#d??RgMW=h5MQJIcpL++;|}qYm>#is1}OH|O4zA9^{rEEn%`%~&&$ zzp6El(sj9^5A#Fs70jWxoOJKwAKLqW-is;@z8!GS|4;RPRYB-)1)=v=hW?y8H1@Q& z^-0aU^uK~{(mQpxY|7o3yD9h9T;G!&kqR$7iFP4*@~t}!!ChLk+Ox)2x}n(PD_gUA zP0`J3%plL2mA-YQC7#?uGjv5!VWDSDsTs7|v*G5V5>8yUA||G6ohKH9XMJ%|Nlb?P zRWa!cV#`@oR1%APWl=0>iKn!zB+5{wKg4+QZ-|L1E-6|OOV|wsMR~aeW=u)`4c<~; zZb?be&1P_cXH^VnQ8D~qoLl0Fs&qv`(K^p?FelC{$z2iUOF=vgY!I*ZL^(J@Zb5K{ z+%-28#E?D=ylz9GuehLWo!LTy73QxQ4qR878`V6V*;BH@5=8`FwXPs{o!2TgFD8_S z?K-qqF4{9nX_B;}sGumysRUf-Da?M6-Bpgx%&Em>jKlofhP@}mNEMNt_# zE54lxRs@)TM^j^SfCcfDOl=kO<5L<|)!6K>t;Q!Wjm`MdCJ=0HV3m#dKBlpPRo69c zDX(Mmu4BvQvDs`6yN&H(x3EoY89qgv%jU5wSr(hYHnMB3Vb`#0*{9fYwwdk4w}-c~ znanqxrcuV+qmmQxCovgHRMs}o-^O5o68dC^v3v21r3wFb;veO2mnr4dzc%E*BFo=E zx(eR~`77OlMmK%z97p;z(q5$fNC%N-U{5C9&X@=35~M+->yaKqx&!GYq=%6fVjt-^($|spBAxOE z_>l&YrsGE9eWXi}?!lJodZg2_`?>?^Z;>8G`WF~fcb&mxx~9Ynew=}p)Y z*@5(jNDm`*{RR9;KZCRv>D@>Nk^UZOdIIcu2mDC4AzhEuaRK~Dn~@$ydKBq#q(8-? zqZjEGyxuX0^lM1d@l5L4_rQ;|7wLMW_hAjO1L=R_6`{jOn{Y3B9BCg?d;rTYdb^1( zZC44?cBE*RjZV-zw1gCb)7w7}|7K`tE)mEpHa&a|Jkf7{VQ46YR*24&RnGJqT}j*Z z{p|Wl*Is$m^l2o5_*dee7jmJBaS`uE{JRk`#aA@B&XhZBE0P_ypFkradpGcBfWMr$ z6n+Co^SX}!{2K6M=~Xm^x4WD~LGn-F-%Hp4$Uc<-VZ$g zv{lIuMDUYgw}zb=@`WMa7r`$BJ|6gNGk$9XzY+Lxz*FBc_*)|Q-N4TSzQ~NX-N*^Z zz9YbI1b%H4zQDkr0KOgguSVfJ4g6`~?btNC#*7a}>c0g16yVpJ@wRma|77&#GT?8I z!tXKg%YgqW@OMPvKWE@K0zU;~!gr(a-!|~Ofxid%hobP`H}FS*zY1eTPZa(a2L1%_ zuLJ*l6#h8_e;W8NVQjfM3SVO2F9H87@DE4fA29HfF&1sW7&Og{-^9^8{+0oM3-G)@ zsradi;5Pza1^huXziq!Ee>d>I06x=XPNO^BKQ-)_W}Qu8E^Z!A^$Y+ z2QYSyq~9gr?*hIgioej{pB%^7Uj}>y#^SOle6fMw2>fB-Z;ir>4o>mC z8~B%iza1>osD4Ws`xaq+zUE&+cx@YkF1yCV3> zm)kj8FSfo;O~jzzuVwn2K)!Wep++jx{vchr#o$*z?zQN`lAT}O z5-)Zy@eRL(C&@HjrsHI)65O)#E2qfKQ?+K_FAY@tSyN4c}VK~BX!=9I^Rg0XQa+AQs)(^^NG}XMC$w@b>5IV zUr3!Nq|Ogg=LMii#d-j6!pN1f-R&hJs@^{DfC)OkGW{2g`PjyhjQou{MD z&r#>)sPl2uc{u9)8+G1|I^RZ}XQR%qxnaeMYuvNTwgejjLHE^}3p2Cl%@6X@{Jry+ zWM(hSoIgjv@!&%paU(j%B$sHhx12FsPSUrdqX~M4>|4)U`?zEefl~BJUE7V!=*NJV ziVh#EBAcea0hG;_up2{!EiPdqC3?bGN;Jm+$HmhyXpf7>8EL@9?*cGR-wLUqIFCX+ z|=mgs58udp~Y9c4tLIjik0BGVzP<(d0 zqZCQf1E7dcAZ=LEFHwoe>!bY*l`@}_bRW?q5>0v%PIqAONiQPrW}`?@{OBb7O)h{> z6XLD~Jl?qz^v)mR4|5&{PID&0BAasy0CuMic%1VbCwvNdhjSCEO>ka-0Nr^z=tnt8 zvqa|$fG0VBjK8CuSAjm+NqcZkCw(vMa^8=>Db7y(O?57V{4vfF{7rLC$KSC|9hBpo zS&%>8>A~L#&c%?K?##g7iO#zqbCNR=`OBR2Olq<-1N2jzry%We=hethb#4Tg+qoN% z4ChSHPjeO`e}$9YNty0^9)D*zZvy2^XDcXYIo|@!Z0Ebk&vE7!V$?dqtuTB*iIu(Sj1~8?52Y zeM3ywmw_KkM-OU0C3EbZM?o}8&j0icE?p-LqNfDW{rggD(VW`TqWJJWHesS%BXn~P zCA3cv9N$O1grXG8=@Ah=%Wz0r}LW)qubsG=X0` zatG*zhw{low$An71~tKLoy8ODY6B=y^VvGRY1FVYujloAN_mCO3`)}f+?k{ z5)Wc8M~)?5PZYP2OLZ1UG}`VtKse__D%!i7Dssb6=K3v>yRHWvDk2)~_VvJyE(1J8 zJMbX#!ee(_h5Dr@KYyDLPej_G&lCM}sH$tr+2PHR{^k z&~S6=F5*el?nR*{bq>`zS|f#BSLG(RvqQol|-`(nA)iVLZ z2wrPQy^#v(+5?c*n!1U|CTm?N97>%*0%mAUAnQmyM}>JBIs0(x+f>Npg`=q#sgT7B z_ose9g=}7UIMqhJT%g?rp5v)clWtdW-MUlXpu!^Uan$n^8*_^M{PocnQF(g8Q8F^Q zmbCg7Wm)nl67y{`S5Kx_1rqKfYpIho0OsIppfnmFNbRwC$PkoTlS5xn&@?vgcChQ; zrOL0@2(Fh>Jvk!(Bl37I&yV_$2tQACj;e%*^+P=S0I2m4&mM!aqb89eX&3NkK6uBo zgqcW2*&%<_Wds?`moSNrFCd>xOPIt23J8`=OBj*YQ)mez@+rx*gh@;!n)GB^!Xzfq zc;IGnBq(uoF61~POPECGL(sy-moP5AgmLjDjB5)7*j;=H<2r|Yyo)bkTzm=R;!7A8 zU&6Tf62`@sFfP7?aq%ULi!WhZQ^4zT-H*R1F200u@gJN~F200u@g#ZxcEalq}q}10+&uNg9rk9 z=aGHs^UxP;Q|<%a-r2El;(WxB?Q$9-v09l#Z$#Oq(nxOad~n~SstRVCK?593)b~jWM@Ur_RAjL2$7bZ9o2>d+}? z?;PAa@oMxc+bD`mt{ty4RR}$_ZxR*`wy`7@x}pNoY|3P?YX55UW((=Rmg;Cn=>43_ z%V7|(l*h_rY6U!oA`QH@&eEw>f>#uar#=H+4Qzq?JYm0X+sk=tP#+C54xI+@DaYYO z?M~YRS)#gc7`6Th)S}iqqiel0x>i+`wW^}5wcV&SV=k$@*G6?G$lC5PYTF1kL~Vis zODJLEURm2pVZ}ZvZ}YT@@+PKz&US_HfV-3IXywx3AC|Fz$~$b=0sWgyQ4N14jjVR$ z8%AwAlx;%%&WO5oVK zISs~qMrvP!n+-ZzOUvc8r_f3X7k?y=R6BCNQG2eeT{8iaDb8Jfrseq{yvY zFz#wld$FqBy@u*uD@ARDGUrjBb~RV#wND8asXml>709WZ5XzvS=(ly&u#7nJewK~m zdYj~^lXYoFuEa1um9Jg0Y_xc>cOKv8UP2+8ZIk_X8ak7wJ_&~)2uK-;BI{@Mi>`n(}D zT?$<<#7yK2w$9D&KN0^VS%lHAkl)5~H?5KKt{1vO$*CX~N{*HCYNjp{4AdhaZ|V+m z;#fn=jGsdVErrW-4U^Ys$V-Wqmm=Fy%1epJdw`lT!A67Pt5*ueB3!OIG%3N}l@&*=tk&V;TQW27aJX17t`6 zbaO(NcBI%4@PQ^;b^X*Qs7Aqnun_VtaenxZWzY+l+Pl2`%p4&nqEM$H?_DKN2zW0d z;5Jh5&%9hC1w<73qaonWO2E{a6qka*Q0TlN?}|6cz&A7+gwmwEGNBg?T;s$TQiaw0 z8=4rmHwtlYNdDrfuM2j%SD-PUyYCH+_$b7AbM#AM8r8WUU#3QWnOC`Xwy5g~qsrI8 zDuVE3X@XbO`LYy~BVzJp?HqWhUy7i7S);B)v*pz7Wbw-yNwRm|zfWk<%kk7F_EYt* zNNLp5h%w{e$dDeclz8)uG5&%WD$$NqWp5qxA4)FHH=*qx8r+bEf_W z)!8FeIxbauL85Ee^y>-#oJMi~;w<5dxrR#~F=~HK)?ULKYw_z)MDBE>yrh#QxpjCsf~<{65rhcvodq`8`pd=E)^UiT837Jn#10KMui()Ix^ zeqg4MD{FzTZZgC_ptKe89+2|T3yzS0d%1uvDIn9(?>VEmG9*87E5^t4SDg{1`>^Try-BgxOk^Vcb>4<{RkP@E)A@7^V+^BYpY>XZlZu{ z)sm#>NXuLW(U;?Od%{wlCKiWI+a*&zM{TR5kl5{RtT3z1KjQOx!X(jq>xkl@0^auBSq{kLb zEQO%g^HkoTt++zS>@h^&V~F0M^b(>~akCJ;L5g0_rc_Zh6=`3QK7PoMHDt&tidM5I zTFs(pHP=Se^pFQuX>Vr;ncp=;uTE1QSQV|NDoQn1MbvzfhW_PRwUl*-A?s@-YdjgT zT&X#gR&OYZ9$oCtAU&>&=(U>Ai?p+DA>?*L){BO$MM^IrOBK=kJ|IQr@}aI>3gGWT zLx^@{+*lRTbCm$GQkyF+fq*LN57W7Tby5I-*_sQu!4NQA2>=Im&~X~|jGs*f87}_% zHd5`#z2KPoA}KYF8%%@vG`UA-)08Fh$cj;xc?*YY|@ z`Z>~vuXK~OJV0?fBcwT%G&a4JLOG6)$u)3=EYwUcH}aKi!c!C@7f4R0lq35woH9UiKz%`qVH3(o@?o*DyfpxPusw25wQ zlTi_Gh&D-_i8x3yH_Yhhwn&a{3+Hg>yOi@&qT4A|av~t8*~Tb+;b_%LV^u4SOM`PM zXvSwip9!%%DH|z0x{)SE45CJw6y0W*skWIM?f)r81@W^cM#aG8k`PLhys5G_S#(GI zN!Sdt7)vlslbT4*D`bnKJ`3UWSVCmj%rJ1KNRhaiBjDh_U)a!T8BIx=_JK1Qe>KD` z!#^!6*wUO;+fY##tn@Q;AqziT=Uco`{)%07LojPgEq)%1H8$+rQRm;0Spfko*npqj zs?5Y-$yl{N(AX64Rp5h008rzW8l<=s2QOe3)~244*-zm{v0A@7*mK<~Q6Ha+d1`2RS)wKXfYwO(P!qYm5j z39Z46XIl>p*I9?h3O0QD?1pUzha=B8?A!Dkg_KN(J$VG1yMnD7^{&6Gg??2qMjc!M z`*-$bF8>EE`_g3@wz+AxNeJFGaTLyH5n3M`&Lc!H4|4qCTvl~O#c-0VV|Iq30- z*xBT75uuMhQ0cD{QEzk!yR}Q8kD%JxMuUfELDsUf#fM#!I`k!h8`fjgByB&ZX`Q@P zs;JHAPdxoepg%fxpyQGp8?qx5c1}j{1i+s~YIB^yUpxJYGvNB_Y<;!fn*A(wJI(Q^ zqxz;FZpiLx<@A{ZL+8ujI0^(Cuh+5Rs*4v|TlKqZF7)eZ0NbfvyMB_>-RQWZvlF$hEfDeGO;2!f0mm_v9z55ocOBKA(|;y`KiHsuTHm0PI+`Qk zQ0cJ^^WQlO($)H>A4U2sQfs*@c%gdRax!>Mn*7_QTQ|9II1si)nD!< z@vYg9p3}4RY3to@oaK-Q9Y;^xjhsVxh!apO#L;jY zzszw!KNoC0vGXh}5{>?->&~1#@ugOM`Li$U=b*m6`rNUt`qFIu zrqx5Q+IQ-i%V!~^&fVRmFQ2dXKb`&2YW?O{^*OWRZ1z9w%6#SaZHo@muK z>LThoP`QoAC8-hTux(B|0m*01>0Q;fnQ7nBm!G%@gy!Icr-+8@OGO8ciizX11zu6e zMm~Y;OHhqXbeL?wp%bBFz2hrgyxlf9&e-rkSi{6sizj|a%A2cMDSfqGitfFpydJxk zrc*j%pCX~ouNZz91)VN1?7#v=j&lSo$90H<6D&s|eB5ai;^+!BTvV7d=6|CRlZ#MIBi$^>Nf~vAotK%-Hz47y;QPPyobaYBqeM2CtBCFEBEsK0@ z7W3aewj*)|27axy+RgvOaD3!U3hqs=9k-kROsZLfvf(GkDBW?23vSx012wF+g?@fD z*wBKrCU6QvMNN5>vFZQ|d9+1DGlL_Bit2n0@}5~CB`n5i7)mh@9VCO^M$ZaF?0sBC z`~Z`>@}2(X7RJ4SAB>HPR3(<55>pX`P*WHyWQ@~g5HWPdhtKD4*jC%z7-hwX2enX` z#Xb>59&MsV53>@)H0)g#XQ$kq);p;8AC>L_FzXEp_EBHP8%i^|Cy#Z&iMQ$5&Xi(&M|i1gEP+gGz43 zEd+i$xX$mR-yFuUf_AE86v@5-e$uzdx4<_aKk-WknfQnlo~Ui8_LVo`P?Abt1#M6f zRZICcKj%~x-t6_PS>f^Jd2YyGW8%X}CBbI6tsF;`)CP7M%6M>=P>C;p%}u!l`74Ru zhsWx$0l$CT*y5{i#ElbG!+*@!x1}71x={D>)i(H=%NweJ#MviXaoUT&o_9h+B~FUp zS*Bk+j%W`X>PcH4KPiRz5YDP4v7bwOaI{=RbfD){`tT%ZII9U%+tA|2uPT=Zdh91T5L)}0g-1hEU651qx@e|Ayf;*qH&@CCr&k(OHI@FBiso8` zCqO#`n5xMp@;2f_*@VGk&B|Pyj#X4vT3lAjN$A(7eN7Y|O^q$;T%5=voaFO1u5NDR zcJqR8WdoB=gOX4l&WpB+wl!fLB_ax1eC2gbHRYJD7?v3R9ft6h8bs?>!xkChoT~+9 zlh@$?7Lw+}0|mgi?lR^PUCdWiS6U5036m*l?&ZYo!zH{h4Qd847@ zU?}6ZiCCjf4x_1|m0&(Z(4Tdj4xSesO*NE|$GZ`an`j%P6EMyLe$pVpFC6a|A z!EcJUK(=%&0;738{aIk>VFXkD8j2;n2h1mCX4xP{ zi}7J-3w~O?!4OO#tQd_>Nj+{0elI@QBwEDBr*rN^U}Ui3z$qU?XN3X{{vA?{#S5Vb zqHsR_Ss-E&eJg;icPqwgu=X;H|#gUgK}5;O;X` zDchT=kuZ|d7-NXR*oqN_l;D+;78C_E_Hy2aM%L08Y)1Q0un`*#5R}SrH#M&TB*p3A zEfvyo62h|90EvlaP0<>UsW+&8>Z_F_iK(8*=+2`E4a8>|##aGi86Fu+`7m2q9w^7@ zV*YJLrMzq97ULkih$0+@g9lgA_T9%^cI^8t!A_s`vSWLuG$!260x{un#&>#VS$2H2 z*Bz7I!PIwr(ew#Secu)h*O~e*E*d_Ht;e$+>t$z&#&>#VoSh{Z-z!GLN3-*IqGG-5 z^gauol2|W0fGIKIE~dVJH1pW;V(sRIW{Ak!St@H%4~0x7FGD5}&r-A6&|W!~_M#%e_gml@60W{`;pA)@HhA4^c)vI#4j=axbNXS`vKvQ$XTs01^sJKgS|9swA3@F+B)#?B!mmlV^)2Lk zB;5Me)Q=?G`qJd%96sEx7bU&*4TIN4px3y)PG)@(#tk^Ni*+2HH-dlYWqtQ>b=X=d z-}*{pIpC?b3C#LkG=0h!%m1H~a;&dieVyc(<~4*FzrH8wt#5t&M8d7_Xg(|9eOC#7 zzm)Tegj?Tde3Qc^ktv~%*C=kSZysO9#t%?G?9g~9byu&iD(Z>=bN6qhZWgWAm z9P9f%xg+#1`nZDRTl?3R5$Lx``PR=MZj*59D`WK2t)!>*CERaGxb@Y#A9A?KVKV!S zq_@6y^s=UpzO?M*aLH^++>+k+7$qqB+nKz*Y^mys%SZX&z*=m>nMh3!ZPbRbc-$1(;U*GjP4}04SA%a6sasZ`Z&gWdp~pwhMX(hV zT|p)Dt=zCC7pHAUV{o5~^QV12>^b{9*nZ^_yemtXPdvNw6|Gve&Qt0u&CSEcEC}(y zx&m7iL2fF{^ZRphZYaplTj5)fxgc{9>Bd!)`%C$yg}#WBOAA+!i%aQt+@Orw(lhRk zq5klVN-`WS^TphTQ%JS-(-aJ}MC%r{|HgcNe(xKp(X_)60n%n0ZsO^FAGiC_@_e)v ziM_>&nytPnoPZs{E>t^dkzG5S?d{(hp)mVOZCP;J_%<@?=U$At#ltsxq9qB-jQwTN zO1y2cfl_NxJ7QeSZ3%=w_5{c@L`D_gsH=*u&F8DGZ)^}02sNdw+OULxmPQ|TI4jZ0 z_5S*brkxS~`3s3&Zi`sAwz0v2O%d#5(xzn829Tu=z7b>!M(Rw49>(TYeL0;n9;w^x zbH0%i+3gaWnkqo##+KC5`WOJL!{z#XTUuJA)0(&j(e?7J^N8h<=;j+W$~?7AE^8LM zq;O$<k%OP&Hb0rbK%~a{s9{L8dGszR_ZQ#F zHl9rzZr~PS<56)M+xbzuY(8Jbj&d3$%j>Wu9Br!DvW$iq^_ZT4o9$pMvt?&Jb~2F$ znnhZpa(Ec)Z*F3l4cIu(%+1T67bvfmCA_GYxg}UzS2?e?l4Vk<22b2rX64QX$P+2X zH;&nc2dcGr>S-?cfNS>Gl@o)^HPr=JChu~Y$YxeIq8OlU+)SGPK-9=b)=WP}F+Ts* zR6>X<3087&`A)&1@~EM_zP187(WYc3Iuy&qv|Ep<6fpmmARguMCuo3+Vr@fJqso_W z*+Scx5RUTf7vCjDKf@r4+x2D)55trKMRH-~mL}CT4Q9$Mj{KG5u2EW=5RjC^| z^Mz$`)HNR^Gr!t5Rq6C7YTEmWzE+}$86Sf3dVP_|<-`O064h#8(U5-a@`ol3U? zPiLa3vfBSuX^!N#>My};7c%5i#jo~>RjSTuQ}tWzKOp(@q(F71w`0D46-x{CRlTYmX+N4s6u)|2kRw0i=?2bxDSnl{ z38b0d*v~2!T>EAHN`_lyWO^Pc$x`*J`|15_1%c92k~6o;$n;&LR7JK0uK3lyjzTMS zRQi$RS9p~^AnV_(05Vm43QV8rSz&}rDiIVPS{{*DX(x`ruhWACTu&*-h~luiW{trA z%O=5)VToUB{qzYh!L0s!d%NJDm@F%niQ+e>s_&U8^@F0+EuXi!QKYSV6*p@9r18OG jA|Q;N>f{MKt^!vShuNPBcr5data, - .curr = fc->data, - .end = fc->data + fc->length - 1, - .line_number = 1, - .line_start = fc->data, - }; - - bh_arr(OnyxToken) token_arr = NULL; - bh_arr_grow(token_arr, 512); - - OnyxToken tk; - do { - tk = onyx_get_token(&tknizer); - bh_arr_push(token_arr, tk); - } while (tk.type != TOKEN_TYPE_END_STREAM); - - return token_arr; -} - int main(int argc, char *argv[]) { bh_file source_file; bh_file_error err = bh_file_open(&source_file, argv[1]); @@ -38,7 +17,9 @@ int main(int argc, char *argv[]) { bh_file_contents fc = bh_file_read_contents(&source_file); bh_file_close(&source_file); - bh_arr(OnyxToken) token_arr = parse_tokens(&fc); + bh_hash(u16) symbol_count; + bh_hash_init(symbol_count); + bh_arr(OnyxToken) token_arr = onyx_parse_tokens(&fc, symbol_count); printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr)); @@ -46,6 +27,14 @@ int main(int argc, char *argv[]) { printf("%s\n", onyx_get_token_type_name(*it)); } + bh_hash_iterator it = bh_hash_iter_setup(u16, symbol_count); + while (bh_hash_iter_next(&it)) { + const char* sym = bh_hash_iter_key(it); + u16 count = bh_hash_iter_value(u16, it); + + printf("%s was seen %d times.\n", sym, count); + } + bh_file_contents_delete(&fc); bh_arr_free(token_arr); diff --git a/onyxlex.c b/onyxlex.c index 4e69467d..fb552d13 100644 --- a/onyxlex.c +++ b/onyxlex.c @@ -236,3 +236,41 @@ OnyxToken onyx_get_token(OnyxTokenizer* tokenizer) { token_parsed: return tk; } + +bh_arr(OnyxToken) onyx_parse_tokens(bh_file_contents *fc, bh_hash(u16) symcount) { + OnyxTokenizer tknizer = { + .start = fc->data, + .curr = fc->data, + .end = fc->data + fc->length - 1, + .line_number = 1, + .line_start = fc->data, + .symbol_count = symcount, + }; + + bh_arr(OnyxToken) token_arr = NULL; + bh_arr_grow(token_arr, 512); + + OnyxToken tk; + do { + tk = onyx_get_token(&tknizer); + + if (tk.type == TOKEN_TYPE_SYMBOL) { + u16 val = 0; + + char tmp = tk.token[tk.length]; + tk.token[tk.length] = '\0'; + + if (bh_hash_has(u16, tknizer.symbol_count, tk.token)) { + val = bh_hash_get(u16, tknizer.symbol_count, tk.token); + } + + bh_hash_put(u16, tknizer.symbol_count, tk.token, val + 1); + + tk.token[tk.length] = tmp; + } + + bh_arr_push(token_arr, tk); + } while (tk.type != TOKEN_TYPE_END_STREAM); + + return token_arr; +} \ No newline at end of file diff --git a/onyxlex.h b/onyxlex.h index b77320a7..fe6b729d 100644 --- a/onyxlex.h +++ b/onyxlex.h @@ -9,6 +9,8 @@ typedef struct OnyxTokenizer { // TODO: Fix the line number and column count char* line_start; u64 line_number; + + bh_hash(u16) symbol_count; } OnyxTokenizer; typedef enum OnyxTokenType { @@ -73,5 +75,6 @@ typedef struct OnyxToken { const char* onyx_get_token_type_name(OnyxToken tkn); OnyxToken onyx_get_token(OnyxTokenizer* tokenizer); +bh_arr(OnyxToken) onyx_parse_tokens(bh_file_contents *fc, bh_hash(u16) symcount); #endif \ No newline at end of file -- 2.25.1