From dc63dabb606009a090dc53e5722209a11e7b83e2 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sun, 17 May 2020 22:28:28 -0500 Subject: [PATCH] Getting ready to start the initial parser --- Makefile | 1 + bh.h | 72 +++++++++++++++++++++++- docs/parse_grammar | 2 +- onyx | Bin 50624 -> 54120 bytes onyx.c | 1 + onyxlex.c | 6 +- onyxlex.h | 1 + onyxparser.c | 21 +++++++ onyxparser.h | 134 +++++++++++++++++++++++++++++++++++++++++++-- progs/minimal.onyx | 3 + progs/mvp.onyx | 11 +++- 11 files changed, 238 insertions(+), 14 deletions(-) create mode 100644 progs/minimal.onyx diff --git a/Makefile b/Makefile index 187b707f..a3c6d82e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ OBJ_FILES=\ onyxlex.o \ + onyxparser.o \ onyx.o CC=gcc diff --git a/bh.h b/bh.h index 10f503e7..89746593 100644 --- a/bh.h +++ b/bh.h @@ -114,7 +114,15 @@ i64 chars_match(char* ptr1, char* ptr2); #define bh_clamp(v, a, b) (bh_min((b), bh_max((a), (v)))) #define bh_abs(x) ((x) < 0 ? -(x) : (x)) + + + + +//------------------------------------------------------------------------------------- +// Helpful macros +//------------------------------------------------------------------------------------- #define bh_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm)) +#define BH_BIT(x) (1 << (x)) @@ -192,10 +200,16 @@ BH_ALLOCATOR_PROC(bh_arena_allocator_proc); +// SCRATCH ALLOCATOR +typedef struct bh_scratch { + bh_allocator backing; + ptr memory, end, curr; +} bh_scratch; - - - +void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size); +void bh_scratch_free(bh_scratch* scratch); +bh_allocator bh_scratch_allocator(bh_scratch* scratch); +BH_ALLOCATOR_PROC(bh_scratch_allocator_proc); @@ -736,6 +750,58 @@ BH_ALLOCATOR_PROC(bh_arena_allocator_proc) { +// SCRATCH ALLOCATOR IMPLEMENTATION +void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size) { + ptr memory = bh_alloc(backing, scratch_size); + + scratch->backing = backing; + scratch->memory = memory; + scratch->curr = memory; + scratch->end = memory + scratch_size; +} + +void bh_scratch_free(bh_scratch* scratch) { + bh_free(scratch->backing, scratch->memory); + + scratch->memory = NULL; + scratch->curr = NULL; + scratch->end = NULL; +} + +bh_allocator bh_scratch_allocator(bh_scratch* scratch) { + return (bh_allocator) { + .proc = bh_scratch_allocator_proc, + .data = scratch, + }; +} + +BH_ALLOCATOR_PROC(bh_scratch_allocator_proc) { + bh_scratch* scratch = (bh_scratch*) data; + ptr retval = NULL; + + switch (action) { + case bh_allocator_action_alloc: { + if (size > scratch->end - scratch->memory) { + return NULL; + } + + retval = scratch->curr; + scratch->curr += size; + + if (scratch->curr >= scratch->end) { + scratch->curr = scratch->memory; + retval = scratch->curr; + } + } break; + + case bh_allocator_action_free: + case bh_allocator_action_resize: + // Do nothing + break; + } + + return retval; +} //------------------------------------------------------------------------------------- diff --git a/docs/parse_grammar b/docs/parse_grammar index d4642989..821b5120 100644 --- a/docs/parse_grammar +++ b/docs/parse_grammar @@ -27,7 +27,7 @@ TOP_LEVEL_VALUE FUNCTION_DECLARATION = proc FUNCTION_TYPE BLOCK -FUNCTION_TYPE = :: ( FUNCTION_PARAMS ) -> TOKEN_TYPE_SYMBOL +FUNCTION_TYPE = ( FUNCTION_PARAMS ) -> TOKEN_TYPE_SYMBOL -- This may be too weird... BLOCK = { STATEMENTS | --- diff --git a/onyx b/onyx index b8911011cf089071f0bbd84ada557389a703a101..40a17c46c671440e0ad8fe44d735b485029ac837 100755 GIT binary patch literal 54120 zcmeIb3w)KuwKx1c`<5pck_dZ4xXI=oZb?8yK)_tsup0KcG8cFfkMiZoe0egT3eQWyRH*7lb)&xuSwDNY6gaw6NVIg7 zpAFYgyk{9F2ZW0xKNYHcHy|I$`S)J3d9_utyutKxT9&6mSzRr+p?>|mxw#EBvl{9f zBim+en?G;Xytz58O*wP8-o&41m#?g3k*K{TE5>_~CK%xt-mqxg`rlU_I{KAJ?r%38 zI9Im#=2W5`g+JA99FZ&tzTmxfWg18gyp91hbRbw8HV8a*5cvCm`|)SLS^-GJfAk>m zy@SAu2Z7HW1YS4@eET5qgM+~L35&QdQrDdRIhsgpMXF6wF!VLv@A`l_A^TLcMbian#_Nm)*5bUtlr!#!shK- zDAXFRs@@c;uG!wM7}#} ziPz?)Ewx%R%B|6wMYd3g1SZK){^qKB2pcyyHA?m&L7I?|x-|Wx&?(~rLNM0=h?^la zF1UC|P~+HrUH4)5b89D%i(vP1+NHfB)86{}AvEH=Ez^-v^~qG`?~$fU%>$}EyRQ)N zY&qU5_-+X|*7=!0!ByICgV*FsJ~sGP3D2{^J0yI*4Sqnv^KJ0M5+1a{UzYH48@x}# z*Vy2CfyUQ58+@dM*V*8C65ecsFO%?XHuyRT-))0`M#A^m;9r*TP8yV+u&;? zJkJLIw1m&M!S9yvd>eefga>W#?@4&M4gS1@ud%`3l<;*n_ zHXD4dgzvV&%Ow0!8~l`nciZ5nCH#~PepbTI+u(nYaAUn+qf52>A0^yxga28==iA^P zNO-vo{#OaFv%xP(_--3q3$Pg4{WiEu!VlWuhJ>HA!P6xCv<;pq;ip1=E{J?$mnf2d zPg~$=7I?1(o^FAkx4=hO;1@0Mkrue}3*3N_pQ^6;l0FFlT>%m1Ti^~0JZOPCE%0&+ zoXSww8VlUI4p?V_Q`zdOv%r;25U$w*#{_9!+br-D6RK&uE$~zee4ho5iPyY3E$|Ez zs%iII;A&1M^Z^T8PQ9G#Q48Gaza6x|hgtX^vcPHWp{{NV+^2vDPg>x^E$|)-9A2P# z1>4>=g6;0Fl>4>d-tMrYzbDvs+;~pwzxr62U+bTI9KRXk@)4tS9pyWBx*yl%!;~hI zIM>7J?^Bvg;aoST{|}|f1kN4g^h1;;lRkHV(_g1FnZmhFPJfBgWCG`QbNcg?rlvpF z%;~!*O-+7o9jEW0G&S|Pa!$8Unwt1rKBqrLX=>VYd7NHPY3e%X{G7g-($vJ~GC949 z(&?1eIDI{(sj1JMzYM_SLP}E;pF7Rzg_NeIJ=eqOIh3X*J=e|Y>6E6XJa^E{zo8Rp zzGnZiIQsJK!RT*;ZD-DxSCn+P@5t4(V8;+A2a7+#LZsjK;Yz=DA!8iIq+rM5zuw^2 zDuW&FKO+n-xEPF{4Ua_Ay$Bj=x*@mqpWcv@F>Vj@zwJ3{wOAVYpQ3ynSAU<`OuLNy z!DlZ!gVFQBXM3*;>dyyXz8ua1!!F4%jTjEbZ};NQf{zx-4Yn=bhzyVn@}vdZ7k>(= z-XYLfZxBDvyVrtFCvkR@VDCQ%mZ%Sr-*#>TC@2Oi%nL?$^ai7m)4^!vsc7kI!S+CJ zust8fS$QfL{bewEqW1!{9gGGp2HSRA)OOwhiqq|tuSGKjX*oy($X$+f z?C}1CKxmvjrBHIa%W)fHQLkpy>weU$vj*VF*+hjZ%TJ^WjxajRV~icG}wesAh;exkQrQXEb_S%fgYAtF^WQMCjzIa zZjzB7GNS&nAXXJ+x2OtL3Y<^GJq_G>RG5msr&v%Gb2Iji#qgj&K`5NS(=+yZtl*Av z2a`bC;6&qznFDfeI1%`+uARFTB`EMeOnvcMGVAfNMFg%#q+S(m)**6Z#*YHuMU6H@ z1K(BHf0$sxM5YfcH&>S1`;RVnL)(t;Y8iXKhJow9p*BG_sMDg~1>1TZu%%Py{(`YR z*b(WW0-vIJBiP~Fl7j%|eCp%={=MB9d#kN9G0Xubi>B1zLJX~tV= zXwCu67)jG0X~^X?<)L{9G#}4G0C|Fv=GTCmG&I+M<}FDxNzy!Hr2$W(>6SE_r1=*s z4b5SoIUs4?`bgCMPAd(~d!T8PG>0V3Emj(u>p-(!(%dU)7FubB2$~{E(=2I5T4~Y+ z%@j#fB55u{Z)V*kja$-WOPbfMG#HXdo->%)NQW*-^Q4uA=2OrdlQgIQD(e0fD-F%D zpgACEj!K%am4@bB(Cm~n_e+}9RvL1rKy$042}_zeRvL1xK(kQNluMc`tTg0ifhJ4R z%#<{=BX8=5TyW5QI0FIdZb+J+TWQEG1I=ra=FCM=_wQP1$Ylr3_a#lYr0KBIkoyjr zPD!(0(ll6UXb&1Rjgn@Yq*-C587*i^Bu#~+nQo;SD`=)mnmkF9Y^AwU&=`^?P15wD zZ<_iUCurW84jA;)`xjC76IL3(p!tcUIWB1)vC@neG~bjo2PDm2E6oH!^I1uAr=+3d z3satnf+i$s)<~KnE6pT9vslv1l{6EqG?N9*Xi1YPX>=>i6hZUXX`=4$ekkgG8e^a- z&s0J4x}-TNX?|>_$rdy}lr#@Znr{#dJR?j;!Z)}Nog0Jcp6?L-iNHYwT3>mvEpSly z9sf-($)~y4$X6{B3d!?4JX04$?)`V*_h5`~g--~YgET3?0{}`p_bcHcP#qRc$k@A< zrvDQGcEb>MQw=O^|Eu0qUn`VxC{7u-M$!O-i`Z7%t@j!K4TW0eM-}fNEwt_E#w^?< z6haQzKgd@+O^yrndm8$MWs>d=@f_S5?^g+X`3gES*~{06@eX6r>V`pDYXJ1uk-|d}! zw{-Tc>FlfQ>|52@SJv5A(%Dzs*|)5-uc)&xzq4;~XWzokzH2)B=63eY?(ECy?3>Zq zm)+SnxwCIVXWzKazA>GBBRl(sclHhI?91%z8`9aA(%F~P+2`u))6ue}_oD)EeQ2$N zmbrmE`qM~aMO2W9G$W@*Pdz0Xr{l#3v+6)%=-SfTZPQ_Mj7loEc9C0-zU zS{C{q75Yb7PPRuN9Jq9p_qG>ib_Dh4^_jE|jP?YdJ?)?xK6~03>`3!~3QDSkv8ncv z&1JUFX=)!(wO!OR_U5oM!MOdlUbNL1)m9h&glc{EI5p8N1-F{3#60Wj7e%4n;br~@ zH5wM6?U7Sx^V4h(SdbQD$PJ@Lo>{?5N!${Q&s zYrvG!qJ@~0JI%5l27ikpu%{4>oPjA`bi5lw6+qRhxriytK#=*z!nBzrkP+&~7v&C);Jh08$&Mc`(bb~2p*W1jG$Oa7Sg?F5 z6XgcQfCXPg!$xWLEmFF+chMVE$Be#S5lym# z?=iLhpYu|K0XiS*Q*g*48irQ6HzkGvNcCsxkt7vHLF%qCsY=AuDJ6?gH>NtD7Sdr9 zc!t<1(f+oo+IF1M!c!m*>WZyAXijnI;kq8CT0TSLc7IQ&Re2q5QYWKLb>`E6NL`m2 z0mByrJy{Yh?N;sI9yo(>HvAdrsk ziF`k*j5;GuTb{i2X~wez9D9Bzh)Ro%x-c(lAEE?S?BhW?)M*x=umz}$0^UUhkwKoP zlA*hKjedo&3ut}89d^&+VFRfZgej;!Ib8WwE z2=kNilDOgNeb<5nR)mquor&!is#YHyl?&|bcDNl1HViNfJVf^awtI+*)f{5mtLZr(Vx-KM~iLKol!{B*-Jpkx*D?LY=r#l4)-z=T<__}B9t@r%|xUCtotS+l8+sd zzEOx!S$$U^Qb;I+B0zNtu}>X-5~^X@xu(69XZriOrF(@Q+OcxoE?pa1MW8Rye1el4 z5=qtp#uklS;E9?WnI>#;^uzj$*I~ZWp><|r-9w!`E%(sW0WH1pJ2{lM?Kr80Q$ceQ zrNfvq*^M(5SPqVm2|M4G5zo3j!)cKk^uXj4hUX4)xGBTShsiWhSPKHK--19-gj`x8 zYp?8vOc+If28vJpmc=>WH&$V3;vtI2NuWQLXpC!zgtUi%J+GuC*9GgCMQR;06Xa$M z@}fK5MFma^SLYNhTcL{f0Dx4oU$7SEc4!S!J={O`7f3Cq5~{^C)`6_x^2yWvnEkg;udJxvN16WJ{S_p|Me;E|fz@@ewm$dCkK$5KJC1%@`B4N|y zR#LNLkVK|((i416%c4+tx`h0}C0lg{WWVBXWq;nD9gdJ#*OAOrz$;W)nh|6=SyY~J zPYN7#%##^lyd2&q-5Rr6<){`q4r(PQ(}SqrA@WDS^&oO1PN&VNvnoBNxo(o;X08N` zo9sL?nLDDnsiXD~gdB2@r*A8GpW?-4JNr8*gPp?4_st5OLa}5Zssi1X6$F)fBTuwk zxAPcXpC@y}2=KQH2KuB~^L3~>3XawM0BZRtYJSje&+U~5dDBLy@OhkRAc>)!bQC!N z9U<3=-tUmcX>SMdFSD9UF|yb_j?*AVW0;#MAc-Gvj=XKLnoKr2F(YSz8JgO#IH~2N zFM>+1G=99z=apLAny3f-pxMfk(bD5fqqNaOV>R7Y5!ptYu#wER9mlmu3Nt#Fgg($7 zIG*vZAiN*V1qo;}aYBzh;&tnjdmV1FXFXcVgC58!> z0oz`p%>(D#^SuiK-8;7sDdN$Pn(c0PHA*{{ZEl{##Jk-5HM6g#ggK$Rh$S{H{H^9RpwmEk@j8eGXoE_uX?C1xFFkHf?=YzX+Q;RF zS|Wxh+KlRjf}(|)ERITX^I$y(#T_RHiyMLGe(HFCd{atq>s7UYn>{}-)`rp2w*&|5 zaM&N>O9nZEKZ{l#fLDEbWAjHmw;%*h0PFXLY;&jhPq33kkd z|3x!IN_!<*7iI#W{xa`~{k*qB$VVm22)q?#UmeR?u{|yXq|Jx<)K9TCj8^tUOJ8c+ z@sgIYXDE6jL^&l*u2}dLDL9zW0|HLC-xcES8xH1wisZFV;5gftNbQI0h|b1{Gp0fwzKC!YN++Ki|6*?6E$% zo!L=sNo}vO+E5yl^BR=X6Vn(2cl5MZzNCKy%xiIKyYUUttU@laE+e(!NTKcce7QL# z6$d*)UB!6-hO6jpkO(VmIdmPq$U7K3-MsTI^(|@x>gODY?kq=w>jlU_06Qapny0f9 zfp?)bjr~jT)!HlHC1Kl+If5r#J%nn*DD~ML?_P3h+Rit5EVYP<=H)>I9zL^K0`^ck z*j!R<+Fd=gbK@U~dG@zXUM!#Joe1}!EpQ3tT;g)DFH3AhXF)aMCW@(Iw>V*^Ha8&> z^k8$Z=&RT(qT#YF@LE0!LStc!r5cl{Q7RaJ5P1kkU`a4=x%-H2-R{zbQx@Pz&!Y@1@SW-<^9o0EO8^xA>;qc0xA18o$QlW5R@Gvx}m@aOpBPl_R`K#?&+^^$3DJ7GAUP#9o;ci%K^Xf0uju?1$LrD=@ zN6c00h%-Q&0}zH%Q|sV$(o}O^FRS^Y5CX$_-a&&G!&=)8jwTo6j54texH}> z#q+~O*p#$IvqI%)fs@h5aSRQI2HO20vq2ts$E+V&!ryQ6Vp>6u*aY8%TjR`$z-d^z z)|Vwrilz`@PPDh*w)ricrkgPKTDYqmvKrUjuX6347ZkLc0nt0KRZpuF>Pr*gl&Uk< z02!XR1rvv+n~+sjTQ0w&l`ml)W?9sHoWQs5ffZ+>X-`9=BJS?xp)=5nsR2U)GW=QnrH@H^hGL%yy1JPXaQI+`6cf%O0rqz95*{0}cZe+ujM#lM zL}uPdq$w2|g{otlSy{r5y%)uF_R(<(mmg!GAVMfvLZ*OXCm8pT{!}F5V6qDqn7IWu zD#XAr!*!vF8O0$HXZz6B#b}|I1rw?%s1&E!`ygfX=>}d+{cs%ut6iSrlWT&ah6WAu z9XPxe3zDlbxJUQi30&LL^s9xh3byaH(zd&QILQyqUHu6TAYd-sxqH9&GPZ5WfX>~7 z-`=&ND<9xhPzTn29i^St_03Pof#y=Nv?V981IwcJ(gUdHqjEt|g*7xxW;Z~))oid^ zjIiE5H}6{vM8zfwI(Z92LLuI<9xx+D(ZIewawGPYwAcAXxGsxAXg3oFUm4Gw!kh}F z1orhe`}>=-`kOQRn~naw-XhpOX5PHgXm3gMH_WuqRZ(6p%} zgoZ(30O4~?bwV!3k)VDOyYBlk?y990A!VTt2I(Zfg9JX&yB9m4Tn(IypR%5dzx8t> zs_n(0c)@MAJ=a-qQ^AeJ(bvfcN;)RzjOAP3XHmGiAo@vh^uv;Abl12MeD)J(?=_Tp z?;ped*}qcvtCvJSDv5r$H2NO}{oc2NZO`e!1#d_GfJz&;+(tzd++GlRt}}Lj{QJ+r z0*D_!{XoyUIJAng6@itZinZl|Q02-ME6Z+LX$1vVE)A`&SQRKJwL*)^N=pMPE3BXu zfwec4tzzQJqJ)^r)qzAA0&B|4Rwc|(yeuJoNn$?B%2p*JUs{$3x++jnxhk%rN`9~j z6faMRDqmGrl!)2#lCr{r5-Vm^@$z6rs9@EqvYV{nlEAVA(6Vyqzr0{oAg<7&lCsr- zfnX*sTvbpMr%ORR0BjPk2*fEkMs7oJhJuyLOA>G&0A9VeG*n(vx!PJof|VAp90*)p zQ4rTWoH?+n$YwEPyE5XzRk8ckS$CXTBIaVjb+DT~uH0aph~ zixVQq&I|0t25zVc=e<*N#A98g+CammsFz(Q!!&a(*3KcLnHrR9NDs|!{xwNV$A z#Ti>kaYbNNK?!x!;&{#qv$C=@u&OxDc8kg?(SPwUe55+8)oyEUY6)u*JgQ#5L94|> z?%IZ?mRda4P9dI%4@X)WwVEb8q~27mZER>-U)7+^TB0qQrDbc=w9jZev|F^>v_*J3 z$qa3lHeJinCTqFct=htc+CuGGZKk$ZTc_>B3rTL*rf8u_TBLDPW7F0~ZA(*qjkdn2 zsX>d(*CKeVJ#y6?Ei!MeRzF{>N3tHtdL%a>+<>r^esJBgG*DQ%{5JpOX8&Tpcnm*# zazo8De^uB&xpg6;bns)Ni+fI=$Y=WPc@$rI+CF=7^WWwtUlahkfsFjgLsGQ$bvbn` zhE~v0+gRl4zmxc*_{%b+xcYk&@!!exy9ldVTAITx{_%_bD=SM%v}Jg|L2Zpc+~lV> z68JYD1$9AH6?J$~02S|_Oz2IujjjG{DK0X!Hdj^G`e6z&^t2Rha;typ7$+3(z{WXA>MhizkeU%r(fvrKZx)=!Zip# zdJ%O*_{2}~a23K=5E@uZ7oO_x&qjC=y8-10i?Nx~jPNmpoe2K};X#C}e%0UKgV6m} zfB$)ea}j1@$M7bEd330TupHqN2%8a}LD-3K47OemBHV(o2jO9a=Mj4T9r>|BDMy%x z@Ii#-2>*gGj4=7v{r&eMd=23f2+7k$G$Kl><2=7670pSl2df~KeMSIRg_z=Phgw*EbFFlDx%Do6v;lVwD zupZ%S2#+JYfN%mpmWAN8`qQ8HJq@f@&y{1h9j_9@L!JC}m^vq@HS=VQzZZ&pm*NwV%`c;!A z5SsEY#a}k~LKWskd2hwv^ppMl?AR8hXWs278sc&M5E2RAcLIML_$w)w!mnjCm%Sh0 zW5743S@6zHX+%Nt9mU^JEY|7l*UW$YJ-l zCjL0^Ss3#YwXYv}&H!HwJiY73TD~*^)*+3bp8*YSK#tLrauJNDadk8BKegf=&zmv? zfzQJDN+&jE8IF5Qd>!yn;G=Q)Jtlr1@b3Z7&v2{0P#!D)QQ&_M`~tM4$=^Ab&75?2 z5_k>c^o}_G+f4qwz~2UZA{|kF!=-6o0DiFYvw?2|ez3kA1b!^$gS~O(?>5V?1O6`H z@o-&C{`y$`_5t4s{8TG`eGLC7@LvV~xE1gCvC01=@YiC#;jvBWZ$m79FYwENUlo^M zG%(j6^UyZnkHz7iHu+}*KMM0#WgK2K5ap*Gx-#HzkHd?>jPUe?dk65h#Nlr=`R@b% zkVV;+tC4SY86_X5Axn%_}j z${z&&-+=!p4*!9PrziTqg?awrIQ#=9ejo5NFz+w6;)VILe2)Sj1imuP{>x+b5Bv`J z2S2jrcYNRE-wV7KenOEIZyCc4_yN}d|DqM|_=%Z68~EP<|6m+`KjZy?1%Y1=ed<2@$TWK77O*sw%Ujx5oOPn4)ZR(*1 z_`~p9z89DOF*E;p;8(zpc{vXMl8MiRL0kf!?xr+lbi8Nc^MHR9{?DCp_^l?s9Qa)L zL!;y58_x1&BTqB%)8QxS7?Vx@B^}OtTy1XWd7&#}y%c}@L94-cswF^Sdgd1$h3Q#e za0b%-9j?Ok?0ek7^t`)0!SwlUNu}xeE$Q(KQ-`A4g6CB|J1<$%^FbefmQE)CAXX|71GukUBL_y4iSM? zkuM@6W!it6pJStCnp|_bMu|XE@0q2wBwY&s!R7uYO5ZP?Z!AOk3d#tUWqfr@JhnCY znlA;E+nQRIg!BG{j8j0{9(4Ibeh!t7e_G~O`frE;YeAWAS)%$nV`*zj)b=CWH)%$ZFk@?j7an<{9-;waY%22)ER=v+wy}wqy zuU5UE_HNz?!5UkJ>V31%%d~o*ta^W}dS9%1KdgEmta|^esMX-V>V2?^LYI-#w9vO) z4#Wwk-UqAtBlUBF|3T7Inl2aqD35v{tb)_=E7l^-lAFP7Y_(geK0Yb*cSsKTPUcC>N^CC^-FVUw-dIhI(nBeMtunNAs zsA!=-yK;S`F&yz@M1`bCO zy}QieO3DVY!$_J)f$o{WIJX1M=XAO8mU!UY4dCTkO_+OV+tuYlfsPJ}x($!fh7dWY z0iQ&1*A-}M=cz(OjWyuon&5Z@agRY;=E-YeFz!hleGzQkb8aH&DuQ0a(J0dHYbl!2 zgWRV)AJ9>3Y9Yo!&xZuoQvVMM@O(@>jMNX1({qX9nW;Gh|AgXMsX1WoxlD0?>RgEC z;T`+zv`#=gnofwkv=OL?N9V-+v`-Pn!HN8|-xFIGCxU6;g#aEmC(6@0p<$1Q6Km3v zDPicHAXt}1N1mP({XQh>(vnG*G@S%)PCG)FOiqN;j-ytdp?WPa+tPXoGhCmG#O|~r zDs+TijKp1Oe*Ai}^!?!0mi7$g8KXaj#J;qXl$fkHgP=3*ZK~%i{WD11pLT{4Ih;6< z)<=n4PCT0S9wqWPaWL(#l$fJ`5qS=!{Q-97xr$}$PQyl?=DAw`KFT?+4Vg|Nd_Cm> zR3*!EfGU}K1NxokL5garIVAf-R9z#rkreR=)ix6f2?6FYP9c@vh943;qYx2-Qfo5w zn1T+|GS{O@#u^gqI-TG~gyQ)kPDjU{0*-r(&x1))A4rl{Lae0EQSr%9l%BMYqjWZw z6y@k2h|wsLDgDog&I0`vTG9jr$@dUyG(lkA8&MW|z?Favr8_^8hf;G4rJFyJy@eE| zn?I7Xh|^HI2PAnUcY_PWX*3h8CxS6m01U-l4qEb9YL8*`E{7!7wTLE1j{@iY2tS&4 z8l=^|i>Xx2MKsAB_XFYDf}iBCynfyZ_s@1$%Ak^7Ab$A;gg46pd;4Uw|0in6Qg_PC%2*?fZH%LtH zm#9GRbBL#UXMi%z`!ujay!7x(x_2Mo8Qv&W(pvz^E4*~{JJkCXlEd3fg?oPmtj}wJ z|8VbPfRFIL4h~t~b>KGAI}0?UyhVVF_HM!N81GTQ$9n07U{`wk02$}400+O9UaU0U z8^P}c?@s`k=zRluCwVu4^JMSMpr7J>1=y+HARyV^$AF#Y^`gY--bv`rGraUtubG;Q z^pjHHK_X=YXtGm^?m&<_8g)roN($3b={F@nt#73Mh2qOd<(a9h^5vxRtkm5oC57Wq zKQT%P&c<&#^+|edBzN?g+Nk%D)?Ir6Np||z`N0QuT?7{TpM5BDsGQ9Bo&uos{RACD zrmp{)jM3S3dgs^;)ku+q&aP8CM}33n-Xo)NcJ1CZie6x+e?-}wT^Dy=8Q!GnpHP*Y zT?co;>M80m$i_$i2~qtv0zAa$&NL>IJb>;W0v(O{gb650oSD__MDFOyA4jjY)c^Qz zS2Dfk@1ZmSNYh6 z`Y=*tC62D(7-}iKn5@XrwN%vi`UdcHbk%9vYRKi%euc_PH)S4tyS)J3KotKKw?w~Z zB?Mr%MDL&|xh1V6lXOcc&Tfh0)Eq?FEpbk8+=sZw*oB&CGLKT3%A6r z>68#|iCgD{a7)|{P6)Te?c#)ROWbZw2)D%T;e>EY+=fnFRk$VY6#Z@_gj?cH(@9|A zmbf!HA>0!8P`wfu;g-0E>ywZWZi#z@PItZBmFCBetRJbMXG3=uVx5PbJUk3u= zmbho>n~)H0i93fA!Yy&6W+; zP$k(daX&~=;g+}`qUs8_#Qg}>mfVsuz&yrDq|(VE$hFEKdmt#aCPT^hVW`zDabL$i z5xXVsd=V$N#9hE~3^rhr^ebd#x5V=~DxTdE&pwWlTjGgwl-!b}Q6y9PZx9^|>xWx1 z6al*>Nuvp3cT32>7&ZfWhHXGMOmb1wnDZDYy^o>)tJhJG>=`JH40i>++ri z#O?hAzaH;x_)YTu4!?%C2*1hR--0H^`#gSAy`A_?^Ns*~h~}bFjHS!KKji^HvW#Vu z&@EE0Bk*!6R!f}?SI`Jvi?}QG8|WxTG1cGjeUbQI&v1QQrtdIiSs{{FX8P_UY>7yY z&GaoLY^g|&$<$m_n6Z*Pk8~<^xBAhY+}0{SZK7Ur(%l z^i(mdoCJa{wQMRz&i~Rd{UljeKS|crPm*=@lVn}}Bw1HKN!Ha*l6CcyWL^Cv z#jSpl&ITm2+iRzFFW)lbqtVD*z^S^XqgRzFFJS3gE<^<%_VKSpfzlRWt9Cpp3D z$79e`JaicDfY+~>g|0J0iAXq`W55@299(6X{>0%(NzY8zHZW^sf_B?>y`;h}DC>|8@X; zUjRVYQf?Z88CieoTf}V`HgxpE*D|+X6Z#0tl=>qxp2ef0ev}0Br_R6#DdO3hix}xo z6YG>ch-T_Pew}!J6{D5jO?;$;&r($k%|%4|F-@sB&)^WUE3~s*P0HXP}keu2mLhF-sdf)iS-@!kY zq*L^}iF5~cwRB$=NFBa<#9h9hgR|lL6NJdnMo|WRmR?DjTVv(q>OZ2)Rmi6KGN`V; zp8@O8MiG&ImHs85M?FV~t9cJ%^hzi>Q@=+45Qs4wP^tO)bBJnb%ZO-!PCl)njUqCA zp-wM!A4z-ZQrJcMRCu4huK=t0KH%~;LqL>AM0&nXJ6of90jwA5bx82~RWH(6rMv*v zm+I7hVganH1@I`!q%YI2A_lww)?4&%n+#g548l5@y;uP2BH`6WQ6@d2hl#-=2(?r{ zs=tlIm`%0YVHzCQ(w-)vpJ4|1Vx#1bpy5^3b=oM(r~g?0A@P_FmHYLVb-E>POt@;j zroX~*E$x@YLnMr}9%|iJr9^ZayG(e~0>tb!eI@c|p-YeFT6tUKSq5l=}u_uuK z;yC?vJqkLZty8kHtEmm&U__>tPWitMnkx&T{7X)46y?<4)Yk##wXV*|-|+G3+{deP zALwCKygK*s>fFbxb04qHeY`sNJpvlT$E$N6ug-nEI`{GF+{dePAFs}RygK*s>fFbx zb04qHeY`sN@#@_7E6D2e@#@^it8*W(&V9T(_wnl7SA-Hr`*?NkDYIQyeu8>@v zlfu;MoHun6tj=lhQ>$}|qw9;+`OC=cF^HR&ygJcQQs;C5;A7v>$G)SFeMcYrjz0Ds zee65>*mv}?@91OS(Z{}{k9|iUiI(bP-_d9B9aERi0Ds{-rY=i{A+Yb5x}1s?zGG_e zR){Hl$JAo(*5k-`Oue4r@EymI@0hwmB(KaIN4{ffiAavk97n!mYN<#n-!XONeh{To zf#dKeeaF;tFB1MKFn&iWZR7p>V*KFZyCW&w{~8F!kD{T137lPT?Hs>~lVo_#uAZF} zj?uuCM&lA~5=^9rp&UbK7|ilP)iz!Zq!Gi$I%*RkUM_KwsR6eI1=fw}_jz1)p0ai1g& z-Q=b%183KxyJqa7p=OPnOxDr0ZbmANNjJM`EWu{OG~P40g>yT)N@i>&ac`H&ifQ$l z9+HW2ZRQM8S`la6wNME4vMJlQP1%ZMZG%FzBFSK>kgP~bc1TLLG+wf0QnETB*>ahA z&8%uj_7uuUc6Kilg$iM>mlU^Z>7NIjNO&wy(~?M}nRk-VbGW5{Mk{Pw-xC28x&q1& z3Y`-#^qhF1=h%e4N(x;k)OocOdYuq@z7kqUxWJTf<_~E+AHmdX<_jtK{%1t>{co7U zjEEOzM7%H~Y{F#4YjBJdMz-x(nYm)>PHNj6_d%%zZRXpgnpB~hYlJkULb~+*(}5JK zNp({k#xm(mNmVY0G_sF0$-jXHK{E51hsnY&yQptXl^MPzGwA!fh%If2gM#`pbqeky zmt9l}S@fhY%UrpZVqB&YwdteKuKFq0pJ;Cy7vHIlP~V@9?l=VxLK2qZ*fJ9~c*;dR z4tr+V+#6IfKYKQHHIbzLI4OM|v(#v!qf4~!uU%f|wub6R?xV*b$7K3wNUZ=Fe$BMVqJt-7iiUb1TkYpG(!DQd!FTpZe6o4JnC zKjJ3Mm&F&E#V zou>ALI4XTmYIBz<&nL1Fa&71$dA_LRnQ;qA(m9BQ7?_kWqh zyB^a5C@4-_y&i)mzM12wRo1yEzFOvcSY$`FKB9bV6zjNJG-+nDi@(lAz5q>|GhU#M zSmhE^?!jHt=s2L78KPfmGv||imvMS+p5XkES-{OhRRLwPfCIa-nPHiWaCAz*49g|M z@)@+FrB}Mh!$Q|YHK^d3%OI(~%td?Snk;3lS;|2wg}E+ct}sWzW;th|8ErM?56UF^ z$_J$1LRROqxq{JkCO>VM;#Vm7)n%884Ai;6FS~=r$wDb5jDHO&X$kYYYXHA;li!kf zeoJI~OMXjY{8Fg7uXd4RQ!4q%0R+u3%?jrFF#6Cs*r&RrVCR$h%d z6#R)3d3iz#k2JD%GY(PDO_JQ!Kq%^SGpA8SE<0&vZjnN*GKC5bS3+HOQvao@vR*Gc zsYcMN5bCm1bd;cw>9SLF=ltv}vg^xEA<`i!QolskX_Fr#nJzlX?w8BbXPBjb)hzv@ zEWM5!<)V`|CmdZhV(hx;q_K+Gq?n9H^+h%3@$g19U(q@aJt3vR5 zTk;Fe_!=4QubskAK(BI;g5O~Fw@UU?P4?G}P`Y|UNh|ohA^EM-W`0c7eU%yHNCvVq zpqqcrWbmpf9}mv2N(SXKW>EcpA;oRbCO<^!!_4p7(}g5^O@ZDq`5iX--A}E3*h%{} zsPBy5Q3a343f9cv(vHf~&^ilkxrg8!H%_#QUdw`HNebZ8(c$Tn^zc~YFOux(Ui z^VpsuTRWJ26P2ct`PpBksVapnhbPn`vXvAkElS9oXOvJn)k)=Gh?_xvxt_+tU_^%b z($?JM8%d*1C%HIpN)ciHeChj-kciC2sn}@K`zXi9j;N%*!K6NCQh)4_h2jZ+D)l`_ znxv)`6kYoMr6U#Z_ayb2Y~HJU&!K$S6I9ZB4$&9NXYkJ9`wp?n!kqN4q>g7f{i-yh znA_?arL-$3$ZciqKI;(LT`IKuEVF0*v3gY+!vX8}SqJq@8V<5qzt1{^elgKUNxWkY zDv72{*6(pC-kM3Pv$>+$T_VtCyg}l=;z(g~cu*dL_Gdi??Wj&pX1n5=KO^fBYlcFq z3%ebMWodQV^jgaC9mmy@Ix36N_kY2p{*I(xGoymK>0`3&bu;?NG9EWYnchI@2OJMi z5lp&FUgu0+4=7%uksdG`iT8^iFdK;t`arCazDe!Bi_>pR7JPqdvfnydHIkq(yTC5l zNU{s;lI&#{P)XSZcF88fh|W#4OEwX@0Jq6*Q<~gv(!(~E{e+YTqcUGuojFO?X2+)` z=0+3K139Nu5l)z9x#+jel5tR*c`Y$+;Iv<6k9CY$V?_1_nSGteF373QuaPA+C>@G^ zu99H>6KbA1X8y}bLa6Ia**+tg*TpjzZl9OjN=$AqNNzPIHy(p( zWcD>eHkHKw#bacK>zLaz$!)30%@`{xzRuJeb6cmHQ=9w=RjtfHli|A)MZTNO>}!xc z`+Y${0|(XSqBU7A_6Ev1KRNM}AEtI#=4b=;6O!M2li&TsZzwhLGKZM*>ZVlJDSFI@ z+T;hRlNLH?Hs2%j=b8D>P<0xbh~V=qPQ#QstkzYkj!Z-)YP6XXNz^6GYn|jJHH6{M zd!^C zmC7~i_OPU%6QdtTv-NSE#=8lU{s$&~I&OuUg7;q$g>)aL@V?h^-n6I5@u#HApKyM1 zv9Sz#UgBz|HN+C@H2?2t+AE@g_Q&Hz3DssnVHA|dXK_pb8yL?_;T59SNfH29)D0Zk_!!>96 z!qjV1i?P&kXMhAV6$O+|nxau)%oQ~5;$hc~T!h&?Spq;L04c+CXL@QX@zIeXb%@Dy zKKP}{B=S>oh$<30;ksTtjB;d*M@hLrW)4GED&q>$_)w4PW$AxSNF@VT$CY0A)gsi{L!(^9FqhR@ZOvjvdKt?KyywWX6sHq2`7-ht-sQ|3NAX6_?|xo5?j z^vJl(+yh2gd%)=U-Z4hzmOXSVW8JVm&UqzwPB+f15;ccEkrB)8GCsb$Oo;Dj6XUzf zB-Je@n;hLS|$=}V%f4ZiJK{k_yj}UDP6_taomXCWjCU4mH387e8XmHp@akj}vN+6=RVCW>SiI+M)H5@#`O_ z55cdF+H3gJb0e)Sx%G|J4UwAK+->vch33tj)llCU**0rqVGoM zhpO>*OhJee>zm9x90ghH_SO(K=o*kw;MA)iRe4xG(Ut5_H~uZX|JNAN-Hj+bYa|`)Cq3irCdcql)slowIdgF@}?2EAotpvC)x3k;TT@BTH1$ z`H3Uv@isDQ-9z@Id$!~nCpcn!!}F%2V3_lameXb8h0zgZ68#vsg~FBUS(_K5a1z`_ z@Fc)rK0%rS9T9s=Y2JoFk2LV3pfOdj?)rVQJ+;+Z_-^*u(N@eTtIdm={3 z9OLY4BjVhe<4p6fa3&L{14izVBS(&&U2+7y`f;Oc*BwY6S<-fpa_@0oiScjano|!# zZy0PN#@VfppM4tR?8bQ$SIkw}joc+ij2Bh52io>HhaPq|=NPYVJ%aLAyni%%h4Vf= z=kdrMV@c%kJpMni>*(6N3lXT|eNso>7Bo;7U3WVs`X1N@x}o_F>;N_5yXuz9Wh=wver2?$1&YU!=o@F z#|F;`jjmWUP4S$R=ZXo^j)f{x_Z5jq4Xr%`?_MAVi@O z^|e{cs6L4(SJUNLl53nj|Fc1ml*I*` zrN9usG`+fv#m=zN>CEuAp|-h(;vM#E0ao{L9W7-rn=gqzWjyAIeBs}qQcE^ua@feh z1dok=>2>4r2Y(M@s=;6~eyM9q?)$sB;0+$*dvy@)E@#T3iN?)mjkBLEdF^4c59-3Y z2MzdwG3;?;{A}awgA;O%aST1)n$J#462Q@zYD^e!?de(SeI>H@lt>=s*6O*Im z6A0?d2K*B25Kk*LTBx-S??+!B*`S4r%R+dG_oh%-E5meDL9fcLzoWLr_J;NlUfj;F zwwJH(#+?dP)%D@+oF9BbbmOq4RQ1|>_?Gz3R9jo>!?jF@hsNwhSUy%@Wuw3YKS)3Y zBzjlB?Pd9)%~dU%YFk>ZOs(HC!27)A3(K2YLRHn_`liMZy(`^HuY?HLzSBS=6w<5j zL(NTb1u#Oq${*^Ym!6ZBTdTH+>Mvhe=`Wf+TRisfpS3w0X{=qmv9__crM?=;s+Q`y z#aI%|nm5-!YomYGhSqRZ^`=>PQ+>F$8t+=4g+0Ee#*J19&CenPVvSe<-+urNq{WvI z8j#)3Kas{(yc55+#!rvvTbeJycQdF`vG@0@3A@^wi%7%=0x8$XYiq9)pMdg>n#{}n33s^F7BZ;qK zP=UfQx$ayxZK&2%g{!piCQ*BdMq0I<`YlF} zdJHXWP>qqz>oGEg&^k4 zrP!2cEam~8yEUs0V+g*7QKm+CtvZ4(gPyT5TsJ@x+lNg=qe#QW_`Rhb!w)z1vf`3J zsJS5$*E!9xh`z)k`XfEvn?TJ2KUo7s(5FCnLefG_4K+&pR5dEi%7(NizEKjdV^Jti zFs%*rsRn$S0@g`iZlIecX>h;}h#dE->#AT-t!gF|y@0wR$Z6<6=EiVsBer8gBnyTR zp;(iFZQxWUgq~&lXi(x$Ma4GmQrTjyA7s)*E=e1ul1G9k318fPut z50)Ad0?(TZkwcM2dDO|R~3{p$V1l<${xf_K_%a#U0H?6{Vb~OG(OGwQfZ1b(PweSa< z*jH-}*EUnUv36Tn;}6bkMt3k7-4qP0EDD4Q1Ivq7n!o@)6SXQ-yz<6^612VScrerE z?OIc7Xme9dtw#M0ItjH@HEtA>7JVtkGVSy1Nm=P@EBJy>?PeAcAC*Bb=8wwMgm60> zQPk9~k8DI%_GIK_M?(U3Ezn2k2vk*DN?TO93g4!x&^A+l6J5S#tJ&k}OEN-8_8s6x zn5b}VLxU!~M0Brm3}6*&L(3{x7F86Ntqg_WD74h0avLz<)L?=SSJ&0UQA3a0AQVhW zl;W%Lg{B4!&W$xyEj1d?INFw~hDfZ;n%dUtmU_6+EgHskdOmCY_Aoq~Sk2{Ud(2wm z%Tz0u7U0WeWtA1>l@&}0MT9oCG;u9y7=-Sz?G$b#B!ABazIh9M$%g=9vR4{q`7!No zt!jWLt)T_zHf7O(@Vz3N&3IKqb6phyFc#EqGs|tQYpHMCL`kc4aW2fPJi?+OT8Xn7 z?@6lKs^*wIFf-B6;_FBzJ2oep<4g#*D5uDgM`dX|CwXZe$Lw8gQu1u6M)*)oeG43H zLJF0@&Re$Ax1!J>ly3{6gz*s#X_1!-%DPOwv;8w4(Yes~Yg-z@q`9SbOK5ZL<|gnR zP{mN3$)kZVYk~-^PlhDYP!Wn{)E;rU6ESm9`U6*t7+73Nr47(i@k(i)Tqf$qZVA+`%s|!M?D}e$ z5)H(ax2Q;^nO!yN5RMr|bwd-aEU4?SlVlq0);j2jzXxSjh5CV*hAma5s9-ET0*pJP zLC(d4muj(ChYG>sBFzK&hN>HC;ddyGX8$LzjH+)MnRL6A=D2}Z-K1@(Z)sIj;THM^ zR*MEBpG`k=gsF?+Cnj86gK<4tH`TLfoZtq>%w*A~nL`*R?2ZQ=lRU;dPVZamY8$Ir zE0*rQwWX@L8A5VR&3eO45d#hvMPQ-2X8KH6Q>3N3mRXnsn;gEeax+04}S;6N=tF4mZYio zomz2DJTR@^lNt|C){G=8M8ut1il*M%YQ;LWRP+6{@$fWlU4|8+_zckw;!Y|1<%` zQyXr+2REJ`cLA;QTR|Lm(pz<_6Txv_o#4Ww(+Qx|zM}_$<5t52ms7)Cb_p)0hC9@3 z7oBgrv_JRT!2I4!2iohrt-WxQ6RbR4%fp>*)@!_k@3z6O0bGY345K~o?%>%VFT=T67v~ox3eU@-Tw0#KCmCH zWHc7(m59ZC5aQjo91rlz5=<)^$x8E*Gugauy?T>kX zTEgv5GM~YTaw2{11brszdwzYqHug$B_NNBEBH<@&_ilen!tFQ1x3b;_j?X`2`hgAb zvgBjGlX(T&C6WAZN_zXP#&jzt>BoM5s1x_LB;qri;pv+FNwJB8&@YknZF5B(UX)d# zC!45T`?E1OOSt{fxVl03-zn+sPs`sk2tB=QmCCh0sDBeczDqpV7dJ z>+>See$Q~3umm1%mvqg3%Y7E$WLNfiZL*}dKVmUo!tJ*?U(aw$fifDB^!7)wHv{e; zNUq%}>Fp2R-6P@l2QR)3_!W*3n*F`y-(vcK1so=Ni@$*+UoS9y`hZ*Oe<9)aCkf9< z_<+Z0aF-voul;#}p%Q-jI#FJ&EO&y0+uz?XPr~g_?=5Gz%xnp6k@WT_akojh{kC^{ zm2f8J>&$Aug$r)wm-O~~zps?_?UsJR44Lc8lHUG|6TLWv^q}q!QFmn1cWVi5e?RE+ z4386q6TbqS{!dDJ`=id!Nx1!qo}Ws% z{mJm(4Z@#ZD@*;+-d;|uL$1I$bD+x4iYUi?L)R66Q#;z9p_~Y~pDE&h7E5~jVPZ-EvyO;aLz;)9Tl8^ldlwCbkK&9pgElXK0y1=l1d!rH#Eo_5iywqvK6w%RtdV6!z;6WP2O_Z47o%}nv; zR~#wr?~2=8`S54Jxo_;?iSXv8zT6h3od&T7LOb1Rb0WcxZqD4R<}H9M%T^VX210aX zOy?@J(PK)3n<iyTY3-!fW{cPL`KxgB8n*yDE z+BZe5jQN~vU>(f;c&?SXy>02J${1x8Xkauqe7OK~n^2rt45&L3#qYJtLkQJP=ro0N zY1!>ZQnk6-c$H{*GQu5|hdgxyi){4x@73WLWTw`oAD^BJK zTPRe$t%_y}FuY@+*5$bYcq&tgbxm;xU#x8FfX2J!T2AZs&2-S1gNZ|gbt=Y3SG)h;d(0H51BjY1fKR3Y7s-0u;-KPH>(|p+fW+|8ql`mK34FKzFCf~X zCD#?(7JRAm0TtSJYNeYisqrR$#Ng7I`PDgs3jHRfh`_y!yJjP0&9BZIR5&S)n)Vjs zucb(Sh;OAS`RNs$bg59~$1;j9<%i0owh|FMLTJk0E%U2zpG;#JzmD z-?Zhg$QKwDCM!Z2+Ux&qz^VSK{nq6RLKSXSiWOi}|1!xhZ?xuD=TjcUxj}F%9`KYw_GRkoVV%U zFTm#SdBlj9Dqo%3onJ3Vl$LQ`G>lf+4hL5>)^8@c7Y~W Y%caUyAQCT8{)ee!;#y+MU`uNM4>uY>{Qv*} literal 50624 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 diff --git a/onyx.c b/onyx.c index e08127de..42fbb892 100644 --- a/onyx.c +++ b/onyx.c @@ -6,6 +6,7 @@ #include // TODO: Replace with custom lib #include "onyxlex.h" +#include "onyxparser.h" int main(int argc, char *argv[]) { bh_file source_file; diff --git a/onyxlex.c b/onyxlex.c index 0eef2e79..b25256f0 100644 --- a/onyxlex.c +++ b/onyxlex.c @@ -34,6 +34,7 @@ static const char* onyx_token_type_names[] = { "TOKEN_TYPE_SYM_MINUS", "TOKEN_TYPE_SYM_STAR", "TOKEN_TYPE_SYM_PERCENT", + "TOKEN_TYPE_SYM_DOT", "TOKEN_TYPE_SYM_FSLASH", "TOKEN_TYPE_SYM_BSLASH", "TOKEN_TYPE_SYM_TYPE_SIGNATURE", @@ -163,8 +164,9 @@ OnyxToken onyx_get_token(OnyxTokenizer* tokenizer) { LITERAL_TOKEN("+", TOKEN_TYPE_SYM_PLUS); LITERAL_TOKEN("-", TOKEN_TYPE_SYM_MINUS); LITERAL_TOKEN("*", TOKEN_TYPE_SYM_STAR); - LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH); + LITERAL_TOKEN(".", TOKEN_TYPE_SYM_DOT); LITERAL_TOKEN("%", TOKEN_TYPE_SYM_PERCENT); + LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH); LITERAL_TOKEN("\\", TOKEN_TYPE_SYM_BSLASH); LITERAL_TOKEN("::", TOKEN_TYPE_SYM_TYPE_SIGNATURE); LITERAL_TOKEN(":", TOKEN_TYPE_SYM_COLON); @@ -221,7 +223,7 @@ OnyxToken onyx_get_token(OnyxTokenizer* tokenizer) { // Number literal if (char_is_num(*tokenizer->curr)) { u64 len = 0; - while (char_is_num(*tokenizer->curr) || *tokenizer->curr == '.') { + while (char_is_num(*(tokenizer->curr + 1)) || *(tokenizer->curr + 1) == '.') { len++; INCREMENT_CURR_TOKEN(tokenizer); } diff --git a/onyxlex.h b/onyxlex.h index 399ca1cb..15b19b40 100644 --- a/onyxlex.h +++ b/onyxlex.h @@ -43,6 +43,7 @@ typedef enum OnyxTokenType { TOKEN_TYPE_SYM_MINUS, TOKEN_TYPE_SYM_STAR, TOKEN_TYPE_SYM_PERCENT, + TOKEN_TYPE_SYM_DOT, TOKEN_TYPE_SYM_FSLASH, TOKEN_TYPE_SYM_BSLASH, TOKEN_TYPE_SYM_TYPE_SIGNATURE, diff --git a/onyxparser.c b/onyxparser.c index 873380b6..8db202c7 100644 --- a/onyxparser.c +++ b/onyxparser.c @@ -1,2 +1,23 @@ #include "onyxparser.h" + +struct OnyxTypeInfo builtin_types[] = { + { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" }, + { ONYX_TYPE_INFO_KIND_VOID, 0, "void" }, + + { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 0, 0, 1 }, + + { ONYX_TYPE_INFO_KIND_UINT8, 1, "u8", 1, 1, 0, 0 }, + { ONYX_TYPE_INFO_KIND_UINT16, 2, "u16", 1, 1, 0, 0 }, + { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0 }, + { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0 }, + + { ONYX_TYPE_INFO_KIND_INT8, 1, "i8", 1, 0, 0, 0 }, + { ONYX_TYPE_INFO_KIND_INT16, 2, "i16", 1, 0, 0, 0 }, + { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0 }, + { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0 }, + + { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0 }, + { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0 }, + { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0 }, +}; \ No newline at end of file diff --git a/onyxparser.h b/onyxparser.h index eccf9610..c8b2c7e2 100644 --- a/onyxparser.h +++ b/onyxparser.h @@ -1,3 +1,4 @@ +#define BH_NO_STRING #include "bh.h" #include "onyxlex.h" @@ -7,12 +8,135 @@ typedef struct OnyxParser { OnyxToken *prev; OnyxToken *curr; - bh_hash(OnyxIdentifier) idens; - - bh_arr(OnyxToken) tokens; /* Maybe don't store the whole array? Ask for one as you need it? */ + bh_allocator allocator; } OnyxParser; -typedef struct OnyxParseNode { +typedef enum OnyxAstNodeKind { + ONYX_PARSE_NODE_KIND_ERROR, + ONYX_PARSE_NODE_KIND_PROGRAM, + + ONYX_PARSE_NODE_KIND_FUNCDEF, + ONYX_PARSE_NODE_KIND_BLOCK, + ONYX_PARSE_NODE_KIND_SCOPE, + + ONYX_PARSE_NODE_KIND_ADD, + ONYX_PARSE_NODE_KIND_SUB, + ONYX_PARSE_NODE_KIND_MUL, + ONYX_PARSE_NODE_KIND_DIVIDE, + ONYX_PARSE_NODE_KIND_MODULUS, + ONYX_PARSE_NODE_KIND_NEGATE, + + ONYX_PARSE_NODE_KIND_TYPE, + ONYX_PARSE_NODE_KIND_LITERAL, + ONYX_PARSE_NODE_KIND_CAST, + ONYX_PARSE_NODE_KIND_PARAM, + ONYX_PARSE_NODE_KIND_CALL, + ONYX_PARSE_NODE_KIND_RETURN, + + ONYX_PARSE_NODE_KIND_EQUAL, + ONYX_PARSE_NODE_KIND_NOT_EQUAL, + ONYX_PARSE_NODE_KIND_GREATER, + ONYX_PARSE_NODE_KIND_GREATER_EQUAL, + ONYX_PARSE_NODE_KIND_LESS, + ONYX_PARSE_NODE_KIND_LESS_EQUAL, + ONYX_PARSE_NODE_KIND_NOT, + + ONYX_PARSE_NODE_KIND_IF, + ONYX_PARSE_NODE_KIND_LOOP, + + ONYX_PARSE_NODE_KIND_COUNT +} OnyxAstNodeKind; + +typedef enum OnyxTypeInfoKind { + ONYX_TYPE_INFO_KIND_UNKNOWN, + ONYX_TYPE_INFO_KIND_VOID, + ONYX_TYPE_INFO_KIND_BOOL, + + ONYX_TYPE_INFO_KIND_UINT8, + ONYX_TYPE_INFO_KIND_UINT16, + ONYX_TYPE_INFO_KIND_UINT32, + ONYX_TYPE_INFO_KIND_UINT64, + + ONYX_TYPE_INFO_KIND_INT8, + ONYX_TYPE_INFO_KIND_INT16, + ONYX_TYPE_INFO_KIND_INT32, + ONYX_TYPE_INFO_KIND_INT64, + + ONYX_TYPE_INFO_KIND_FLOAT32, + ONYX_TYPE_INFO_KIND_FLOAT64, + ONYX_TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit +} OnyxTypeInfoKind; + +typedef struct OnyxTypeInfo { + OnyxTypeInfoKind kind; + u32 size; // in bytes + const char* name; + u32 is_int : 1; + u32 is_unsigned : 1; + u32 is_float : 1; + u32 is_bool : 1; +} OnyxTypeInfo; + +extern OnyxTypeInfo builtin_types[]; + +typedef union OnyxAstNode OnyxAstNode; +typedef struct OnyxAstNodeBlock OnyxAstNodeBlock; +typedef struct OnyxAstNodeParam OnyxAstNodeParam; +typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef; + +typedef enum OnyxAstFlags { + ONYX_AST_BLOCK_FLAG_HAS_RETURN = BH_BIT(1), + ONYX_AST_BLOCK_FLAG_TOP_LEVEL = BH_BIT(2), + ONYX_AST_BLOCK_FLAG_EXPORTED = BH_BIT(3), +} OnyxAstFlags; + +struct OnyxAstNodeBlock { + OnyxAstNodeKind kind; + u32 flags; OnyxToken *token; + OnyxTypeInfo *return_type; + OnyxAstNode *next; + OnyxAstNode *unused1; + OnyxAstNode *unused2; +}; + +struct OnyxAstNodeParam { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *token; + OnyxTypeInfo *type; + OnyxAstNode *next; + OnyxAstNode *left; + OnyxAstNode *right; +}; + +struct OnyxAstNodeFuncDef { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *token; // This will point to the symbol token to identify it + OnyxTypeInfo *return_type; + OnyxAstNodeBlock *body; + OnyxAstNodeParam *params; + u64 param_count; // Same size as ptr + u64 unused1; +}; + +union OnyxAstNode { + + // Generic node structure for capturing all binary ops and statements + struct { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *token; + OnyxTypeInfo* type; + OnyxAstNode *next; + OnyxAstNode *left; + OnyxAstNode *right; + } as_node; + + OnyxAstNodeBlock as_block; +}; -}; \ No newline at end of file +ptr onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind); +OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer tokenizer); +OnyxAstNode* onyx_parse(OnyxParser parser); \ No newline at end of file diff --git a/progs/minimal.onyx b/progs/minimal.onyx new file mode 100644 index 00000000..7b9209ad --- /dev/null +++ b/progs/minimal.onyx @@ -0,0 +1,3 @@ +add :: proc(a i32, b i32) -> i32 { + return a + b +}; \ No newline at end of file diff --git a/progs/mvp.onyx b/progs/mvp.onyx index cef77e50..1cfbedc2 100644 --- a/progs/mvp.onyx +++ b/progs/mvp.onyx @@ -2,9 +2,9 @@ /* nested comments /* are /* okay */ */ */ */ -foreign "console" "log" :: proc (data ptr, length i32) -> void ---; - -global thing :: +foreign console { + log :: proc (data ptr, length i32) -> void ---; +} export add :: proc (a i32, b i32) -> i32 { return a + b; @@ -19,4 +19,9 @@ export max :: proc (a i32, b i32) -> i32 { } else { return b; } +}; + +export main :: proc () -> void { + console.log(add(2, 3)); + console.log(max(5, 10)); }; \ No newline at end of file -- 2.25.1