From 012bfbbf3903297c540029abffe7f6ddbf6f2eef Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Wed, 20 May 2020 21:36:27 -0500 Subject: [PATCH] Working on parser and custom printf alternative --- bh.h | 220 ++++++++++++++++++++++++++++++++++++++++++++- onyx | Bin 68704 -> 71424 bytes onyx.c | 2 +- onyxparser.c | 203 +++++++++++++++++++++-------------------- progs/minimal.onyx | 2 +- 5 files changed, 326 insertions(+), 101 deletions(-) diff --git a/bh.h b/bh.h index 6ee6f882..556f3f86 100644 --- a/bh.h +++ b/bh.h @@ -8,6 +8,7 @@ #include // TODO: Replace with custom implementation of printf #include +#include #include // TODO: Replace with needed functions #include @@ -42,6 +43,7 @@ typedef void* ptr; #ifdef BH_DEBUG void* bh__debug_malloc(size_t size, const char* file, u64 line); +void* bh__debug_aligned_alloc(size_t size, size_t alignment, const char* file, u64 line); void bh__debug_free(void* ptr, const char* file, u64 line); void* bh__debug_realloc(void* ptr, size_t size, const char* file, u64 line); @@ -121,8 +123,13 @@ i64 chars_match(char* ptr1, char* ptr2); //------------------------------------------------------------------------------------- // Helpful macros //------------------------------------------------------------------------------------- +#define bh_offset_of(Type, elem) ((isize)&(((Type)*) 0)->elem) +#define bh_aligh_of(Type) bh_offset_of(struct { char c; Type member; }, member) +#define bh_swap(Type, a, b) do { Type tmp = (a); (a) = (b); (b) = tmp; } while(0) + #define bh_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm)) #define BH_BIT(x) (1 << (x)) +#define BH_MASK_SET(var, set, mask) ((set) ? (var) |= (mask) : (var) &= ~(mask)) @@ -217,6 +224,7 @@ BH_ALLOCATOR_PROC(bh_scratch_allocator_proc); + //------------------------------------------------------------------------------------- // Better strings //------------------------------------------------------------------------------------- @@ -288,7 +296,8 @@ void bh_string_print(bh_string* str); typedef enum bh_file_error { BH_FILE_ERROR_NONE, - BH_FILE_ERROR_INVALID + BH_FILE_ERROR_INVALID, + BH_FILE_ERROR_BAD_FD, } bh_file_error; typedef enum bh_file_mode { @@ -363,6 +372,55 @@ i32 bh_file_contents_delete(bh_file_contents* contents); +//------------------------------------------------------------------------------------- +// Alternate printing +//------------------------------------------------------------------------------------- +// Barebones implementation of printf. Does not support all format options +// Currently supports: +// %c - chars +// %_(u)d - ints where _ is: +// nothing - decimal +// o - octal +// x - hexadecimal +// %_(u)l - longs where _ is: +// nothing - decimal +// o - octal +// x - hexadecimal +// %f - floating points +// %s - null terminated strings +// %p - pointers +// %% - literal % + +enum bh__print_format { + BH__PRINT_FORMAT_DECIMAL = BH_BIT(0), + BH__PRINT_FORMAT_OCTAL = BH_BIT(1), + BH__PRINT_FORMAT_HEXADECIMAL = BH_BIT(2), + BH__PRINT_FORMAT_UNSIGNED = BH_BIT(3), +}; + +isize bh_printf(char const *fmt, ...); +isize bh_printf_va(char const *fmt, va_list va); +isize bh_printf_err(char const *fmt, ...); +isize bh_printf_err_va(char const *fmt, va_list va); +isize bh_fprintf(bh_file* f, char const *fmt, ...); +isize bh_fprintf_va(bh_file* f, char const *fmt, va_list va); +char* bh_bprintf(char const *fmt, ...); +char* bh_bprintf_va(char const *fmt, va_list va); +isize bh_snprintf(char *str, isize n, char const *fmt, ...); +isize bh_snprintf_va(char *str, isize n, char const *fmt, va_list va); + + + + + + + + + + + + + //------------------------------------------------------------------------------------- // Better dynamically-sized arrays //------------------------------------------------------------------------------------- @@ -969,6 +1027,8 @@ bh_file_error bh_file_get_standard(bh_file* file, bh_file_standard stand) { sd_fd = STDERR_FILENO; filename = "stderr"; break; + default: + return BH_FILE_ERROR_BAD_FD; } file->fd = sd_fd; @@ -1144,6 +1204,164 @@ b32 bh_file_contents_delete(bh_file_contents* contents) { + + + + + + + + +//------------------------------------------------------------------------------------- +// ALTERNATE PRINTF IMPLEMENTATION +//------------------------------------------------------------------------------------- +isize bh_printf(char const *fmt, ...) { + isize res; + va_list va; + va_start(va, fmt); + res = bh_printf_va(fmt, va); + va_end(va); + return res; +} + +isize bh_printf_va(char const *fmt, va_list va) { + bh_file file; + bh_file_get_standard(&file, BH_FILE_STANDARD_OUTPUT); + return bh_fprintf_va(&file, fmt, va); +} + +isize bh_printf_err(char const *fmt, ...) { + isize res; + va_list va; + va_start(va, fmt); + res = bh_printf_err_va(fmt, va); + va_end(va); + return res; +} + +isize bh_printf_err_va(char const *fmt, va_list va) { + bh_file file; + bh_file_get_standard(&file, BH_FILE_STANDARD_ERROR); + return bh_fprintf_va(&file, fmt, va); +} + +isize bh_fprintf(bh_file* f, char const *fmt, ...) { + isize res; + va_list va; + va_start(va, fmt); + res = bh_fprintf_va(f, fmt, va); + va_end(va); + return res; +} + +isize bh_fprintf_va(bh_file* f, char const *fmt, va_list va) { + static char buf[4096]; + isize len = bh_snprintf_va(buf, sizeof(buf), fmt, va); + bh_file_write(f, buf, len - 1); + return len; +} + +char* bh_bprintf(char const *fmt, ...) { + char* res; + va_list va; + va_start(va, fmt); + res = bh_bprintf_va(fmt, va); + va_end(va); + return res; +} + +char* bh_bprintf_va(char const *fmt, va_list va) { + static char buffer[4096]; + bh_snprintf_va(buffer, sizeof(buffer), fmt, va); + return buffer; +} + +isize bh_snprintf(char *str, isize n, char const *fmt, ...) { + isize res; + va_list va; + va_start(va, fmt); + res = bh_snprintf_va(str, n, fmt, va); + va_end(va); + return res; +} + +isize bh__print_string(char* dest, isize n, char* src) { + isize len = 0; + while (n-- && (*dest++ = *src++)) len++; + return len; +} + +isize bh__printi64(char* str, isize n, enum bh__print_format format, i32 value) { + char buf[130]; + buf[129] = 0; + char* walker = buf + 129; + + while (value > 0) { + *--walker = '0' + (value % 10); + value /= 10; + } + + return bh__print_string(str, n, walker); +} + + +isize bh_snprintf_va(char *str, isize n, char const *fmt, va_list va) { + char const *text_start = str; + isize res; + + while (*fmt) { + i32 base = 10, size; + isize len = 0; + + while (*fmt && *fmt != '%') { + *(str++) = *(fmt++); + len++; + } + + fmt++; + + switch (*fmt++) { + case 'o': base = 8; break; + case 'x': base = 16; break; + default: fmt--; + } + + switch (*fmt) { + case 'c': { + char c = (char) va_arg(va, int); + *(str++) = c; + } break; + + case 'd': { + i64 value = (i64) va_arg(va, int); + len = bh__printi64(str, n, 0, value); + } break; + + default: fmt--; + } + + fmt++; + + str += len; + } + + return str - text_start + 1; +} + + + + + + + + + + + + + + + //------------------------------------------------------------------------------------- // ARRAY IMPLEMENTATION //------------------------------------------------------------------------------------- diff --git a/onyx b/onyx index bd859e2258a9ab525bdcccf169e25f0891856924..43688daaadd05e62c3bd93ac00a2631ccd72878e 100755 GIT binary patch literal 71424 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 Q7yk$e2G_k_1n<%OF9xdK7XSbN literal 68704 zcmeFa4SZC^)jxjkZnC+_E+mj$2=6Pe2`|Zlh@gN8u&_u15fTMOLx4b11Hoh$@Fjo^ zscd7~#Hyuz=p#OTk+x##n?(W|&eYD-(tV63HL+h}R?`+jHU-o3j7pZ52( z{eS-dzZbGIbIzGFXU?3NIrFl6w+9R7J9J$$AE!23W2(5Hgybv4DQAo(Uz@I_YWdno z?J~^;d=maly2P+sWivwqw0xZSW4`GQrY;VLO0Z^zX6X!*6|T1+qg+DGP}BSZzqmZODC|;I-lg=?sme1$Rb4Hwx@z^bsd?3FCskK% zjBK5>b^5eP)28Ou)#OeQ^(KGPE?8VDN@9B}Rs!!unlR$WOdmV&o%ibAUVmil;=A8_ ztm1Fq-}6P%4#A(p#B$wwaiPv-Isv>1#mz95+BOY8~??Z zfZuruxc?IH=1ahrUjjbk67U6=fZu%y_`yrS@4We~C{W0R6NqZB?CLpv-YVLqA!=ZZS=(3)gO3 zvtg4AH{GsniiGR5va-5x`I=kH)>PhFwywOYTC1%nudc3H14MaUT}5qJLN`=wsH+HT zo9i}is;$}>UZ+*pRaD%n0lWsB%B!o^Z>(5bCUe$>*H+ZlYU{StR)s6HHPtnB68vdiEeK;bW zQR&Fws#KQwd!+f8^Mu*1#mcz-YCbUG847M}@{4>X+)Vou;P)>PWLkCt{1F8YB*2d- z`1Az$Nd?bOfWM;Pp#=CZ6udYA{u>2fo&Z0i;HwhgZ!36Z0{mSC-;@CVgMx2OfOjkS zjs&?pN?r3Gk5$-kAU&t>EVp;A0iMI{}`p;M#5Rb~|3djRg2a1unkI2}lSqGf3(_=&v#Uh< zJ*H^_XNyJpZKm1uXY)n+H%zn1&jv*LHKy6rXZ<4m6Qw8rrFeI z&;1R6F^8CD*E@Skq`$*7oBZrak^TnLZ0fV^BK==Xvx(0h5a};6&89uO*UG=H1!?h2 z{@udpk8cS@e-mmreXh8qusM0~Y)uO__xbWH2D9c~t!X{Jb>Q)S`iOY~bhO;Bm4=#= zpFkLz(H)AO2@gV3UIiL9WuKdSPOZyLAF)&LzxiplVk`}ocQaq}6?X_WIe$a`(9yp+ zL(y}gqn+1;^k+jq{#!T;40XlOLxz{)w`10I;G;$ILJhNCxf!ui%Hs(&&3X-~&OXp! zX9yq9Cg*@or#L$_Jm;SVOVo$tH=kVx3dUfSfl#!*GZc-S3PnphqD3!T1%O>wqL`(+wz zqsLU#AIdovik@s}*F$SgDl(EYn}M)9q)XChv2l?0-<8b8ulC&2lssC0p(%JF)a?Bs zVQ8K6E1~74B*)DH4N+KRR!BdY{^)L1{tB zve4b{>>|tPkxFQ3EqIQ}7U^Ke)e!$AfzzD70XrpzYv+(DC3tsxJo4 z0{CDonT=$7EGe7FWMONi-Jm;R(Ituy@t}B?bN0*V{1%ziQeJxFqZqPm&=A_4`Wv6# zcwYjhx!7S6qUpgE__(a7)Vkx1+fZX&J9`vmn&kiTHo0`ALl=vIN^=*)CY)92$ZhFA z5EXzH)-={Kx31v`n^Q|~oQyI1->3>X937BDQK+HQ0UO_U z_Scy1Ld}uAN{}ZwyM~&5`O^`gJ0AP6r>C(!y|E~PELoC`R%HL7$Z`_MI5&ga2UkjN zVMUglK*lK=WN#?4B1QIVOwD%LICF#S2}L$mksV1O;{*+|uPU;h4`da-kU)kc$u=pn z4n-D8Amj88vSLN{ZAErn0vT#VvayQn(~4|T0vVkJko8k!YZO^(0vUY>ko|rd0<^+R zMRo=nuq%YF1;}1fWIjc9w0E*^DzbOGr9!@xKt@Ld-0o3i#}(P_31sw7K(<#b0a=zJTdK(VB#_a`0onO05I`Xl6xmr=j$I*iXF>KOMV6$< zewaWuK$3l3k-hO}sgQ>g$OcNXor>&nMOL3c#x)WOEmLHlRb(p?$mk-2>?%c8smQKK zAmhpkWIjb!pvd|qknzL;WbaKy0EG-zWWPhlv@3+`F_1l{$j<*s*7UgqvSE_!Yl`dz zMfTMMGR)27cDEw?sv^5Pfoy~%TdBylDYBar$o!J*N=0^qBAbywc9|sWugC(5%$Gnm zQj-1da;cD1MfL{_L3V|Vl4K_o*>C?lhjSthqI3C=^iXjv$nt%07dA5m#H3WAh>TqSm18|ETYN%+@yNrLAJPGxMR?4Wj zhWZw`4pN79RsSozb2!vovcLyLJLOP4O~GBlYxw3xE}%4p2^jThnTKV=?M5Iib9bUv z|CNgg<$Fqzc4NMx2eT#KI!*sHH+|>Lz@UQTWd-T_?@LhrKV8_a4J}=tXz5zt(zUjw ztGuP_mX@xYTDq3Ebd|PrEp6#q($ZDf(zURqYko`D+?KBVmabVXU01bqUD?t#wWVuv zOIL17*Myd??3S)EEnOp9x<<5g4Q=Tf)Y3Jer7N?gE2E{WPfJ%?OIJ!uS5ixt-V&=$ zfXjHSz)jN$z!A)9%FmeBT&Z`t3XY&%(aHi_*t{xWC+sDoT)twp+WAK`d?0^n7M-G}I(L(ykD=VDf{*lmjA++5t*G$*4uq(`sK-~u^%GNiX-IU729 zDk;?Lal!2NVo|#<6ooNfhxH%~v#Io8C|Zz#G-|^&UFiv={YYn9rG(;2f&4L4zFF~$ z%4_Hhbftujx1XfF=qEx=H+QTJT|QJSjKj&DkNghcyPx6EbW_2~f}7PEyy2Zy*j#`} z=fph8%9mEz|^REllIQ4-_Deg)%t9waAK5;YBW*vL;|9O@LU zbv$?u!eEjEyXIn4na+H0U%^2f8ET>tR0|x%EFWqr!gAQum#Iz^!W|Gxou`oQjHxq- zN)>=HSJL&}(8f$t8((;*r$=s5V0#53)^~#nnC2OFC#HmB)F@C{9FBUPc+!svnji0lfP$ERw(-FlWeww{OBCT1yRE@ev#@* zB1;%vx6&Oo(wzK8kzZ5RCIK(R0aR5{kfrD+#o7hJjHSfKgWW7k@CK|!tUg&zeg?JW z505ob_mG^8)0|w1GD0(g-H}uzZbG6Ycf6iWvRK2C&jV`nSZKi zLrtM+Nm>-D;n5**VXYEZJcie=TH+X&+S=RD+@Du`ua;(MJ%kF=P@O(gYvR&!R|Z z(@u?>|6%OEi&eqSiu+*qd?V#eUNCL^VgF#xa;!aZd6V ztlJK~&AK#S@e1M?ciuqI`O`DdR&$@%iGEk24@&ftM1PNHS+5M$pkmG&j_n!3pA_q3 z2>97Vz%~UiTgej{BN%~ptvOl<;}>c)fa^Z{X{l>!QM9ZxG6J&YQ??!{+fXUnNXnLF zlTA!o|M3=t!XnL-mlJ=}wW9A@LqRC|-jl-BFuQJ;?TxP6VoEm`8!ficmow<}P!z2p zJ;L*FgHDE`H+Mu!Uw{X464^Qq(LD@F)1SuO9yv;NHkH00#=TAyF#RTTMm7&B>UY~+ ztQ~N%c7b$HW-9#)2xGX5$t1N7<^nHUTtYPp|*twB=touSy2bPR`X>xnn+j=5j zMHH+lEse7j1|Dod{D25Ce<0qD;YBDB4lHW}5HwY^8zdm3ziawy?MR-m`D-8({+nOA zzdWKU2p}7>-rQ;TUeEppY?b$Fd9E4g3*DerGtKeNDbS1QjmcB94xsU;1}$X^?D>6T zy_-`Vw2XeJJPk3hqq4_4@8LjeO?9K8^9<@7e#J-5cBV<|k;hTKIl0~a4#!}eS!F>- z(eHbOrXE-&f@Ypq!5B7)pqX0S*&g<%=LC18=M=T1=alYE&$;8 z={fc1YJT&IqbG&gXV#5BLgV~{I<8(4>ZY*XHZOli|)F|o|JM&AQ2Zhm-YI;Bv z(tHQT%m>IZ6#X&G?nz#;=;S%NDSAUY8n)37iY^~ujBqX${)kFhK)4;bHX1q0XW_K1 z_J{wA%n`UURuN5NBJz{xV-^_7k(v~ff})ibjApa|$<}}Y%X3LAzp_z5Ym$Om)rtaR zAMLAa8OB%79lc&aVt3majWeKC;DU5=hJbp&U#vdm-uC&aK-GSMY7NWJNk&iWu zMozO!CHr7G(*J0vKdnW^9S@$)2Wi)EA;Qs9$#V4JVRBRO{m^c?fP~=al02-9mUgN= zx#0T^_3vxpzUWjyL`%=j2%g^l1Vri%9s2I?W?om_(hhS!5&AP0? zR2G5d`O#Ab!ADOy2+zSN|2)8QM2U9q3SQVze__=&7e4RU=D}zFwm$g0aeFVTEt5P? zkj&_fgo`IZmi}b$0)~?ZVH9vU(^c|ukqpQ2wrnILmXU3@4|8uPw$`~dDQTjAh@Omo zxU2L+^!Z(-5dD1|m0!3D!GE@=KYkKLbmPpK@%Gr_D|!xeU3ApDq0#BV_aiRkdLLb- zA=r(bE&<-z9{Hsh&aHfCXxu$8N5^y!cVbsDc#0n)+bM9vc-5axmi{ zr$4agQ7X*a@lqAaZ4o6|q*L~*(o<48$RHLSrf46ns)qUwO{{`ZKMpLV9VVBPqOONT zRWZ(LJttf2%4<%hIt5xacEdaQX4hqBhx-FTPZUOrILUXDPgC$Tw;|Tyqc(+`6?40) zSR~YOQe8$F@;XO%4ne{823QHkv>+VfZY?}pQFaT(bBbN^3k+Q26!?TdJSZH3w3T+F=}huxkC9uW;Qeaq`#)7zb4D!E`o;WppeuYzo;~rUU4>1TnYH$ zfN3Hw*0W;hB@K*9jH-xZR6S08*gOtcPu#dp6M-qh>?esBW-+n47FTe_5j#H z6I_YO#Ub{A(6;G2{|p9fWCM+Swo8_a8ez>dBY0wSn&>}gU$Nj~b#y{r2vTIn(m(l0 z6CcwlkV4N0?Fx9?TxQZxBCv?$q?vvw?C7D1;355ZjDv7iJHPp=^4hy@g7Dp{9S~)? zS+bcjWYTIemI{<0@yi(oEx=^F;F!>*oyFE%0nw~~r=5*5tI>2RJEILzIutLY^NWyE zs&$zvE9S*!pm261{Fx4bU2DH$aY6@j{#9{5R7N|2ZshXXWZ0{1sJS|^!&5}|Vl{cA zJh8#V!}BkPiJJN6fJ^f*qSvgmrYSP$+Z^YFbnR)rGx@s!|h7vTiB_ zLpWMP6_9GO5eaAITnm8bVsjI`jN`%gF_l_7g=&QITO-u?uB$;JRMMRMIrJe`s|$X} z`y3PD)i;{3Ou#sd1GZJcSX^gQ>HBJNC)>;r^|QJb>c^2Na_V^SLYmNg>8Ylo3(Uz= zh2xz$09xagY*Nk#+*Uvh)gtw{_=2ECCd`gL6xs!R!9k3@r_vj`JzJK??Nv>mcpc`OI#h$Wn0SQl zH8pde#H`x^W$yWzoE(3}umD4HSm#4QCDgCk^$oCHT}#Ir4#f;`kvgC3Z4 zV0dnZh)vA!<3ltJ6jqBs)Ne-cWP~0o$(l;rArpB12o$qk7UG=i8fIcS@sJ{N0_Z0d z8qyw=(jEl%Tu4cqcrwxRQ`gvgGri6+M(gCRzicYVhua zJ3zH`^r{xiST9z^Inj-1?^FeB6aE)eLB1$%J^Pp#GK+Ya;xP|X3hg2b?*B7qaHRnX zHvp_Xmtg&epV+kVQG!!M$d(|uYQx9OxfKfqyWpR@h zv-kU`?9V1<=Z45Rv-&LHCvwvS!!>7ya|SQ2wP)$FD*i4IVL#iBy!{~QV;@Up}y;YqMT$2Xn3 zQ%FKa>y!{0E%0}3M|mg2`m(7AGCzyzoTtS z!Fa5utAp)#{Z>l(4y6o1N?|786p*?ScMCoxg_Zj+VRZm_ z4@U}nlV(JN+@tD*jc}qM>HXVT}7xolsD8PKFT2Oo`@!2MonM z!y{u+C*dEkGwyjoNuO{D!3(%G0t8}h7%h5Taxm==+Q1=VJ{zq5)`t4mwQZFOLT{k- zb^ZCAlPLN$+Dy0zX_&VOelPu7rKdw{eiCY)3LlNLNLo`VS{F-Q0CjG^qStgzl=88J z3BlI^Lupu|$SXKfKy@%8){oKBlhL9V8tPxr(s%YpZv=UVGP#A)_n<@AArvjXCc=9* z&A2zwRR2N~zq}IZSQu@`SA2?i%5qXD`8}~i@@(hNF`}M5A}v-hm8}KIgPmCaGzDL1 z9*QFh?sxQ3NHzDcaDM!(Ga|VaxRE+ur*6Iva_HX zah-ZJZzK`lOQ*IrDthU`*4EMeyhefHvLX0#J{X~~FvhaR6gA3%@duInhzKkR2CgE_~|XepM#k*C4)A1sjB zx9YS{vC3d}h>&l@MwyOor4hE4IefigE~-I8Zxg-C(ECc_(y!Tr6<@XMyh$ zN5f*)PHZAM)0zTrFolA4xI0Nh0Y$vz@3cS|A;UYcr7IvjH4!JgTMC~hv$yAWd1-lK z9_WVcD4VkcFNUU1L?h2&2sn7LeIK+G|GhV*eY3cK$hPJ50cmfA49&>Dil( zKET{jvmE^nYnO;khCjPs^cPAmpxASQu5M%kP9Bo*Bm?|1A@7FxAxxtlSbS zccoE+tPAHxnTRuHswXefcQyCa7ZY)UlgfTfwvTv8{PYCu{=QJM?MKl-f05^ebdVt7<^iPj>-uDJ&cZ%Uh0#CFi~hc#$NPGy;b}cI+?4o99qeeMZv{oB`b=9Wu=Q3EnafNVmm0fcwX7ElBL0dB0F^MlA@yE;u8M2 zRAfz9i{Lk(Dz$D2|T9me~rdC^9gWs15M{4nFPBpa^_|Yi*=u^!aZGCmk z>hfxB(rj(!BrRLZ(eBjhwVSk?wVC)ezzNzUZM-%{%hmF)!IaDmbOaUhF|}? zMH_1uV%dtKIZF!dkivx}!KDR-6nNp{1-)Swmlg$=E}Uye&0SK8nv{)(p=ptgw{EQ2 zvQgVyQ?*uGT~kx7MW$;J{QOkp@+n$m+ElG-x>ki`6_Qm*u0yyEVI4n$OP4NLs%Zgq zprGx~WsBS4BNg2H5qOivp3jWW?j@g{o^kW9X5;N!Hkrr5TCveTZcN>{iT?F9VG)C#dcm98^M`NWR3YiI z$JAXlrg|;^a{OcJ(zNWjl;%(E!$SbAptfRTxxauvMOGfJslCd-rY2IocH_9PU;M}z zgz|5!*y1lI8H{c%ejp5=HIXm_{`?r8+b|-`#2;>8_b|R#g^ZhjHz2-BrK=Fm$8VsC zI{NvOW&U+Y2{H8{&a3&GhbzE$`jMUHtvuOr-ruo}CZk0Pu`_yWSuAbbbm z7Z7?dCFs~Yo``TS!a{^!!f;fL@BrHRUW9L8uznQbkynr(;cy)Ny@PNg!VDa7K8JJR zsR%m}mLTNG@m7SN#F)4nVK#=eg9s}Tb|4&r@v$4>wFt9PG;IUI=?K4ua5=)~5pG5J zA;R4Vr<_85g!dxsKzI^iH^QM9QL}JJybj@Xgg-#I9AO^}`F9~4fp8DP=MWx7c;jz- zdR|BPTZ9)7b|V~`s%evPuW=^A#}KYW*n{vcgkJc5dl3Ez;bDZ!F!;WX@NR?`5bi@b z6joM^_MVCG^9WZWJd5xygx|#4Xb(aSH;NAJ5S~D|7UA9aKIl$_Td@@S3c~jh zK7%m*!=9eg2rIF|G;pD|17R^Q*5bkU^Teayu~gHyX6QpaDMpK)l0o=T{2gfP>6su& z#AomHnl@U|XBq_&_dQd0RI+ve62W!zfIyP-(mcH z0Q_S98jG2~u-SQUQbV$HR=QQrX`n~E(9`2!Jxn^sUoCtR;QEV~mSZ&Y0Y4srmA@h; z=RDxkfG@G*9ZM|!Yk{8)e6Af|CG-0M+X;Lj@GW+Hu)*p0RICjCB*sC|@Qd4)423cL z3E;o}5qN&h=!?L^Tx0p?$MW;`cO&qXcD!SaAQ%c*Ht;V3|4Vg#@~;&6 z{m9b^{CJG3#rFKvvC;u)JQ&Nb2hB}(9-#)ObFp9}$M7Y<&j)_A z9bXp1hk?Hqc;Tj)^}98OzaRJ;fuC;AUl+rF5BOT(Z?xkbrGh}zANWUspJ&ITtxf&B z5By2s3+;Hv0xQ24bLs`)uZ_b8E&NpA$70UCE)Fj{qaUym;BNr_dOM!BX6vt8K@$Z{ ze>+W4td6^ZzZ3Xx*zu09S~462J{j{o4`^aGa<7H&0Dd#@(K!503*Qa=uYkvW)L8!F zSovA-3tk3(hP^L1r&|4SI`F@Pe^GDG@7QYbUrxW`_1<;FHrfjOoxoqJ{N2EB0{&8S z$3fuJ;MX+9mA}I(zXSLh;CmZ$S$;S0^}vs_=U;8BKm3}Vz&~ThJD#%mPY0gfyZ(oreB9_U{QbID}X;1hd*NR-wk{U{I1eCylf!mKM4Fx;BSe;udwoW z0DlMYH^t$vxA5J-fBz%$)1N#45&7xo<--5tHC)U7HreVA{9NF#vE$hRkrwqwWc5ej zcLRSn@bu3u{*Dq${)50D0)9Z8efG2Lvjg}8@IxPs%m0X#zZ>|O@JDCa@zQ*Sd|B`- zR{&oc$G_O(KOOkbz;FG5J-_2S7XRhIk2&4bGuMvaW~)E&A>g04;~hV=^6v)zJ>VaX z!|xGzKVS!euY-Ra*FQ1FIP-*v8foYw?}E?#2;!CwISzd(CWn@$X>Rz>pSIID8Z9~e zz(;`J9H)odEIs4{|KISlza5wVQ7iu{;8()`<}QyVgX4P^eh2V>1pd!)`1dUQUf^GV zpMF;yev5@~2R<8q`j9yJ1_=55$a4z#QSjTB#LczWin*37IY%VHDOwI6zJh=`eKS7m znA11wGtOXNe{<5DzS;LChx!IS-&|Cv`tNi9U1GXK+gYV^t=cKBr z3C~s$Q|^6AFf3)oW0pT$rA@lO^vL?5I05>bN^>8GPfrXl(m0wC`q-=RAE8aJ~w!SK&GpZdT!^RQR9@zox>+Rrst5f3CteRrn_r zy2QZ(%2(l76;4y3l!XzCR{krRS)yM1|)2U!p2)Dt&K4T6IIs ze9wzX$9_tj`JNZEKe0a(ZocQm?BCcr=TFjU=6haDIENA9%=f&QaCR^9G~e@L!r9Hq z-+a%DDIaOc{~0B}31|N&fAc*rCY<9G^SqEi&+&@%=6hZk=fiQ9^e-!V6V73X@QwsH z#*H3;|F0kO{V@X_%$=GWm^3*eQj@n$o}L?+ znmaj1!f|~@s!Ub@M{rbI>R&jJ%^op!v-)UnZ?jN#BYYM$(TId+M6@ zt~thAlrkde$6RL8XH1sxKMhMDRLRdm64?xf{#~@IXA2nb2Bf!&ICNtQY{%h9*~TC# zWj2T%M#>BZx@)SyC8xsdoJq-evmJ2B+rcYoGcosayF6(E>fvZ+G}&+&4G59*YT#2C zPs)RhIy>edYLtOb(n!bG5O*0o>PW4Ip(l?P(Ko<0dCCohRuFonh_)b|d^MwKZy|Sw z>yOJJn)_``n65t&tht{>0j|H0hvB|}oURLuXSkOU{#VAc+y!9n`WxeZ_acbq5+^O$ zp3ei~(sUvMp4q5~OBadhp4*6Vh(x~UU9wFQiIC?Y1aKvbM6u^<(6GxT63acQOc;6# z2v&JsVKHg?gGf|*#!(iJPJuUheo0J*NQ6DVK&@Q;^$K9NdeSMu0DUSFJ3QC3(1H3w zBtGf!G9YnuUulmX^4I*{tyfDekDJ_iv(*_r}+%!FoY8MmWK z#;p|i8l7;1*L__1GCqVt6^OXY_%xWLbb%zb9Ac&1!{SpPLg^{HM6{gvsEG2**T!JV z)b|gFP6B;DEoCHvR3Y>bLSWu^pe*!&si5i4n{284m2E_EVJ+1=hf!W;OU)vu{=Czc zI!JVb6y!@CA_!KKU??T(zbRa+r4D0zWb#ZsCFyEJQ=^B0^Y%dw&3g@`)xE_mRZAjG zYV&SjlcM-Yec&hf^flw-L;MY3WB~IH*kXN<_kin>)Y9(4XGZGhM}U|6^N6SJW>jy?)Gw0hzzQ^6cIq6x7POx4;CJ9t=jvma&$EX_^K|Mr!!rquk{Z-m zaF$1KoG%Q>uVs-#>H3sw6ByT22lD+?hxXZho4e#9#a>L6X{7?0M z9YUvh-$dN)oefHl_ZeXOc=_d`zTR&Fp6>lB1@eYK+0XkS;QhV(D2MkRK)l{}f%SQZ zgZ}{UQ-BZj{t_IrymjC<$jkd-gT2=RGQ`V4WT=-X#lyT&@EPu1kGvzij|1ZO?!xC~ z-VQ)Ude0%(DDU0iIoi7klw-U+_Z#cI1(0#xr-9A(jzd{F-bFC>@!muBB+We^@U&U92E*+|UK!8Ol9(ZF_GvIm8;(qYwEUZy_dyQ; z1yr-04$XvCb5{bV!pDfFY~^Q zh!{O4XoLG9kDl}zAgNCOCO=EphEyS`_tiT_i6rjE%17VBDQTz|AHXv1Xk9)me5nzXFT8R>0LTt!iQH-9ZKcP5?yD4Cz@2Rmkq$v)S+VC7Sp#A|f{$QjmN?eQ*8IB;s z2zDv`1NJCqYs+^3x;01<;cVTzeehRF_aSpTTMul91nh;w`P(`A8j4kg@tBXel!Z{= za{&4nA*!*4wQ#m}Y`curSW9iOgptgmpXU#S@)`A(S}gKKJA62*5B@od(eGRY1v*>b z-KLGYVwgleF9YpH5M5S{x6vPTwQ-98%T-VL&O3rPyCx6-J6C>}U;*U`NtJlIc9DxP{f=Nwd;E%zzzhlOU3E z$%cWNE?J_l_#kt9?2>)#lEFAXcFBxhT{8Msne?K1cgd3eAwTTf=x~?z!{{+7Ka5V3 zkAuYT@i%~x0n9sqeO!KA?1y>L!<8S#sOg6>GySl`2$dg3rUUz7aOxhB+MzE7v2?^< z)dw@9XIo#4c&`aWhSrx1$^g%r1Kb6tHi$V>e<9qgIQOX$X7sW96z@K9Sz)?QN1>m8 z#C>W3z3D!sV%kvd6V+_GPqc?P_i3F)O_&Lz%K{9g^N!`N-Gx~KzJ!v-~I+W3Xr{Ob*4;zg5a2?D& zEldw@K)3OWvyhrwzFKndky0|=(uHTY3Gob?nxhqTDs|sdNLT*+?lLz zKgsk3X6Vm&hP#$c;hhAUEcYfDoM*rc#QmbpJy~pXTFafFbs4OV%P0m{ml4Eg5)1PT zVr4RCgO9Xf&k$D0`vGdId6yxod&h##;iZG@^uB_4lJ^vfO7=EGD3>>ac#8MS_%yuR zL6hqJ449>P^HDpuw}Z;_z5#e2?}vc*^?nPV>E1WMIl~(Uw|?GxLD}D13J#gxTM_qq zkK)tkU5dN|y!Qe=&|44sEN?p?gS>3&!CDe!_RP8#h|J$0s>HvBdiLr<{Qnfkv(}6xAW_W!&!;9io}>Z0#}%peLs~&0XV>M+q28 z%Sv@>YW*hd?1awN9ot8?(zoUOaDOdItdC|1uDkY^`IGLu^0<3n*$rc5D|qcwjtn-m$? zrq0&G+sAx`TJ$Q#EZ1^Yz%KN+sP>BSlArjtiKydl@Eb2=eoJb7`Gn_?eILN7&X(&W zdG-q`-DJ<4yu-oS3 zA*%nFw2e73|0%^r-!lotNa=p8Y+|Hf{jy}ed?bfW{S^+IkYgk#4gFWtHHyuCTd|w0 z*p2K*^lQ|EqZJy>DPrcwn0a}&q!HiZK~&%KfK~EiX34{t{c%}V@yO4CjegK9c^dWc zgiI}$+G&&8snl{>*r2;9R&bmwM|_(|l%u0IxVC&@8p~k8Y@ZuDg)H%CabJF&9at|{8J>S{^(ukyHx)g>BI=7M@`l_ zU!fJ<%;eWqJ3nM`Zn8MvEIFgrH&G>pq%TnPkWW1Np64w3LP@`TWEM+XVwN`XYiyek zlhagg$f$CEVC4>(rA_>h(#<3N7)6h|DEb_*mO7qi(GMqmKIy#|(XX)R^G*7keXPx7 zHp9-*l5dN}|Em`LWJwHCX2Z=bj1r4h)@isYqt*iHlC-a3q*A*dOTdh~ABiVlf1_L$%-erUleh!-wpS-t$2o(F&?1Ui5In~PP`a3PrRtl#1k)G z`>~yPQ7=j$mqAg)ifEJx&D8qYPrL{>PrO82op>>>PP_^cP2!!C)Lb5*iNmkddnk!G z{7T&=qU8`WH7cS!{7RFDUrUkq3;64=rF;f~IQ&W*LP-4KS0+!q+~UMb?5ViL*;XbG zwA|uA%Nsk;a!0WZq4~stmQNgL`D_PT?q(i)h>aBY1O3tQ2fT>%Rfr5^WFYenJZ62c zAqM^cNp+y*{yaB3#72sHH=}YR#r*|l=0*y4e8fhI`-@~MSNEQ)A7-vSpz+M4zU1ME zXBIij!x0%*ha;ZZn?Uc4t&#hi()V9v<^*x|_+ zpMdQ78OVl;gNq!N1;=El@F;VLfDerFZbfX^yUagyyvqMIE58q8zRWRH=2$*_L*05! z7t+%C8n%@=)66MAe0LYQ^*zm2&NSw9w(i~Z*<{j8X@2m@(4TsRJj?q7+)h49 z!lS}_(UM4{ANvmJ{{Y#t^%umPBxHC|$}pWIKN2!zaerCHv&6BzjQh1DX4YT&4fqV2 zG0>{xW%@!4p1!*P(R{U(QyWaQK3X3S#Gv~ity0HWopX;b3m1%aUm8dqz9htxd|Oa$ z!*?fyNY@54gFZydn8Zk=U#{N=^x)4EafP_5G~^dT zIalg`0%GVoRBF2ZG@|kfi#|hKVKKD9B-5|bc>+9WF$7V<&eX?YCh+B=(wgrFqP$d4 zqC67m`MLw>A>y8lK1b(*NgU7Ub9JFoaZg6K-;>dUIvZ2olhMt4GK0xMU!Y%3ZsMMd zUZ+29aSJPMyoaGjboK#xPevuY+F)kVH|uwkK?igLepyNM zhgibv`8ApSOy^E~7WxOR3fp^NJ(#TZpX)AQhRKsHy+eNxDXF?wRb_dyrN1T+IN4(U zM?f=t4q5_k;b7*}f1z&x%xk|G^dj~be2d`JYCdr>h%E;b6BmPg;$o0bTnzGwi$Okd zG03+cG=@)H4Dx*)GN$>&#UP)!8032f*gigSF~}z_2KmIrAfLDxST*~HBm3OkM%N7wn$>0 zY%M^XUb_>a@Y-)c#O}4bvxqWJw(db(oovbRSDtJUOs}1p)ydXsM&-%Yml5@=ldYd4 ze%WetlaV@No))G@%9E|fu=zAno@~wGK9oAy`ZXxblP$v4$<}=A*O(_;E1^{LWQ$5Q zPqz5GSLVsqo!B2VPqr90PqrAhPPU4`-#po(IO=4}R@QB{vT9{n@?^_aR``09Yo2V$ zvgFB@DodVhJ;Acn$<|;9A_+46~#EuT2q@`;lzpE%j_iIXj#IN9>mgFeeAPPTk;CtLSXeEZ4P z4=BDk+46~#EuT2q@`;lzpE%j_iIXj#IN9=vlP#Y(+46~#EuT2q@`;lzpE%j_#hq+j z2ma>CRvubV8bS$+HBYvrA=pl~M#+;c0msSKD0#9alfyGc$&)Ra9F{Rko@~iv>}2a0 z3h2uMgZQ&fwyr|LWf1H#*xg(PyXa_~Y&`{-lZRP~USDd&pxS$HXiNoUO0lHTGSR{2K7i){}RQ zE1@^lht3iXi|VuagOHBC^zEFj@7y(xXG;z*Ef-7X`fOZSbPS-=<7_=uKaO3(F^J~O zbEk356l4f%f#hA|hSAd-L%)}+?Qy%vX`JM=w|*SA5F9ydZf9$I{kWOLPL#y$+s36b znJbA8)Q{uok0Wpo^uU{u<9O)in9S-sTf6Vlay~;>ZcFlR3}ky2Q304~)wM+2lE>!4 zcphk{QRT z)U9w!E zSblH&c;U>gNT%E1Y~8m#Z$1>G-E zrIIC+sx-Y^C5pAcK`JdMvTj-^g%ZCcgQ&iz0UDCE4XWCPq-a6KV4jpLs3be6B%2>E zSx8A%DMeYNGAlugRC1*j@NtbXRkYw!At}taWdLFL#ZD>A)Oca0#tSnwL6|F)FqKkG zS1MsvNi|(%3L|B^Iws5lw%8y+y>Nk)Li|RL(9C~Y!VHQRW>CB^gA#-p9Iu(-N*JYz z5h`=ZgfCMQf#ipk7PP=-0{TeR%$L%9+EUH$Eou5BGY%t|{NIYISW&Uv`zrp`9Fl0h zf$Q1)nqZryGCX3jy&h&YQEd6)3peP%GqI(etcm1ir)Whqh1eF@^|uOII4dtN$FG;E;Gb>|5KuLXY2R2%L3X} z0jnmhDaY;RV@dTwOC@<>R_qy39NJwATtM~pCz3b}PFBUM09sFl8OidVFe@wBABxFe zNCsaK4DR5n3(pT^00#G148CGAklOl+sjcxsJ~LS?**{`RKlw+BWszbz36=S#lD-la z*-h>35T%bPkTl{a!VuN>jK$b2wYMW)dpm?MG41WJv?s+e(+89`@3!Q5R~53^CQqv= zPhKWKT!6ZfD2k%O0Tct0cWCYt}6BsoPN*glEh8mJHq(J!^Y4`~L)B0csR$yxk# z8>0FiKk`bw6~_t?42zS9V*!HUbtc0+UI)@|Na7lgYDGO*a^TmLVnGrwoW3|)79)N^ zP8745#R#?w1Y6jnLkJilw=`CSv^_Z_zPv?O{$gB8CkWVIpR zI*Z>lv%Zt)Iq6r53~2sIwG}v-n63<{S_{miya7@FrVgl{57z{TVOgx1?pfXqjjj;Gl8Ab~kAX;#l;#X=_@Q>g(p1XMi z%swgE4N&=uCk~L=xm^f@m?+dYAc^@f!^q|ssEFA)X~==|%;OS8wq7mEI%XC5X?!nN z>cFL{5RzrO6q|f$lddG*PZL9sFiMx|I|sH;{F&rWPITX-6e-HcR^?qs8#5HQ6M~UK5%l2)zP|E4qhKPIe3X~Ii5!N zOTn)AD#_;=i``+1-7l@me34f5ODDIC9jzsj-!B!vP~HPH+EY&HD48Z5F@FS%Wqwcb!q+ywj}UVO7Dkd7`u5}gui~Yi35SL%aR1~z0g_Otb{E2A&l8It)cPnEEOMiQD;U@3%ihB7(aoTa-VLGv^Skifi z>FR5i|fjpF{)aZ-@O zg~EyxN_QDN7s~lMEu~G=yh+t1)(pl7)I~U>ZK||NyfuWD_^897sH2u*ODyU~74`Bw zahAScmAxuY+%9~~5+&Em()T)UyFxN)wRnBY;NvLgf#~8tEFg z{|=EpK2`GlhQ)rC-)tmFVReBWs*zL|*rC{~E?_2A7ucbi2n%x2L_1Uyp$mvMx!aQF z^3Ci6w+q?7ucSeb6OXlo)%_6;igDw$o9v(6i6NgGTZ%6@Jp!F&Uor%Et?=5i_2wU%rJmr2>G;+acwi+PpF zTni+zunNI#tKw#Et>}9`tGHEI+{74Ep|UTRvYAP2Ost|AmJ4oE6}NeoY(G-m$}PPK zZslfkYB^tG)ruXQ3}2ff^WA7=A3hT1@i|GsfrGW#ZBG`<&4KGgetPjagV}@&91WoU zFU3!dQ}6?CA-~5Yg`Dy#$FHe0=`kNd9(K~X4$kJaDu2L|=NrgBzPg44pBCa&kFUgX z-Aq-|M9jomE%4t|^fiLlV#RB;#p^Zl0{t~6D=jdAl3gw6eTrVqNsv8ll%&7fqR;uQ z7xY&O`u8SF#vl@pzUL}Me`SpRvuvu%1^v^C-rNq*_k2RpUvAM)Jw*B+>KyOP%QfG% z_>ad6k%(2U!+5co^+R#e$cfR1eMS9Qk(cf@)>lg-!c68!zYHbi0hy7BtSqA+ ztX%64Qp1!kGYN&vc2hL7Aa6FPha#KLr;i&XSq(@QLJzb=N@f9Bs!+&)!)^$q*ixXu zvFbRouy2~HUo%K3C3)N+YA-+Q!8wD-WN5Ob2oerMKC%H%CWl-3+>|9QC%ghv%_Q|B zsRUs1GQ|irV{&AgBJQW-iw17AW&acwKUzj{dD>o*Ea&r5!m)OYDTBg|%Z2`^xj5;d z<&TX;8cQ{c^4-fD&j17jXx^Fs&5bphN4r=<;#^#mNT#u9FKAGgO% z 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, it->pos.filename, it->pos.line, it->pos.column); + // printf("%s (%s:%ld:%ld)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column); // onyx_token_null_toggle(*it); // } diff --git a/onyxparser.c b/onyxparser.c index f194266b..d8c9fd86 100644 --- a/onyxparser.c +++ b/onyxparser.c @@ -5,23 +5,23 @@ 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 }, - + { 0xffffffff } // Sentinel }; @@ -35,12 +35,12 @@ static void parser_next_token(OnyxParser* parser) { static b32 is_terminating_token(OnyxTokenType token_type) { switch (token_type) { - case TOKEN_TYPE_SYM_SEMICOLON: - case TOKEN_TYPE_CLOSE_BRACE: - case TOKEN_TYPE_OPEN_BRACE: - case TOKEN_TYPE_END_STREAM: + case TOKEN_TYPE_SYM_SEMICOLON: + case TOKEN_TYPE_CLOSE_BRACE: + case TOKEN_TYPE_OPEN_BRACE: + case TOKEN_TYPE_END_STREAM: return 1; - default: + default: return 0; } } @@ -49,7 +49,7 @@ static b32 is_terminating_token(OnyxTokenType token_type) { static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type) { OnyxToken* token = parser->curr_token; parser_next_token(parser); - + if (token->type != token_type) { onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_EXPECTED_TOKEN, @@ -57,10 +57,14 @@ static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type) { onyx_get_token_type_name(token_type), onyx_get_token_type_name(token->type)); return NULL; } - + return token; } +static OnyxAstNode* parse_factor(OnyxParser* parser) { + return &error_node; +} + static OnyxAstNode* parse_expression(OnyxParser* parser) { return &error_node; } @@ -70,50 +74,54 @@ static OnyxAstNode* parse_if_stmt(OnyxParser* parser) { } static OnyxAstNode* parse_expression_statement(OnyxParser* parser) { - + } static OnyxAstNode* parse_return_statement(OnyxParser* parser) { expect(parser, TOKEN_TYPE_KEYWORD_RETURN); - + + OnyxAstNode* return_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_RETURN); + return_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_VOID]; OnyxAstNode* expr = NULL; - + parser_next_token(parser); if (parser->curr_token->type != TOKEN_TYPE_SYM_SEMICOLON) { expr = parse_expression(parser); - - if (expr == &error_node) { + + if (expr == NULL || expr == &error_node) { return &error_node; } } + + return return_node; } static OnyxAstNodeBlock* parse_block(OnyxParser* parser); static OnyxAstNode* parse_statement(OnyxParser* parser) { switch (parser->curr_token->type) { - case TOKEN_TYPE_KEYWORD_RETURN: + case TOKEN_TYPE_KEYWORD_RETURN: return parse_return_statement(parser); - - case TOKEN_TYPE_OPEN_BRACE: + + case TOKEN_TYPE_OPEN_BRACE: return (OnyxAstNode *) parse_block(parser); - - case TOKEN_TYPE_SYMBOL: - case TOKEN_TYPE_OPEN_PAREN: - case TOKEN_TYPE_SYM_PLUS: - case TOKEN_TYPE_SYM_MINUS: - case TOKEN_TYPE_SYM_BANG: - case TOKEN_TYPE_LITERAL_NUMERIC: - case TOKEN_TYPE_LITERAL_STRING: + + case TOKEN_TYPE_SYMBOL: + case TOKEN_TYPE_OPEN_PAREN: + case TOKEN_TYPE_SYM_PLUS: + case TOKEN_TYPE_SYM_MINUS: + case TOKEN_TYPE_SYM_BANG: + case TOKEN_TYPE_LITERAL_NUMERIC: + case TOKEN_TYPE_LITERAL_STRING: return parse_expression_statement(parser); - - case TOKEN_TYPE_KEYWORD_IF: + + case TOKEN_TYPE_KEYWORD_IF: return parse_if_stmt(parser); - - case TOKEN_TYPE_SYM_SEMICOLON: + + case TOKEN_TYPE_SYM_SEMICOLON: return NULL; - - default: + + default: printf("ERROR\n"); parser_next_token(parser); return NULL; @@ -128,140 +136,139 @@ static OnyxAstNodeBlock* parse_block(OnyxParser* parser) { expect(parser, TOKEN_TYPE_SYM_MINUS); return NULL; } - + expect(parser, TOKEN_TYPE_OPEN_BRACE); - + OnyxAstNodeBlock* block = (OnyxAstNodeBlock *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BLOCK); - + OnyxAstNode** next = &block->body; OnyxAstNode* stmt = NULL; while (parser->curr_token->type != TOKEN_TYPE_CLOSE_BRACE) { stmt = parse_statement(parser); - + if (stmt != NULL && stmt->kind != ONYX_AST_NODE_KIND_ERROR) { *next = stmt; next = &stmt->next; } - + expect(parser, TOKEN_TYPE_SYM_SEMICOLON); } - + return block; } static OnyxTypeInfo* parse_type(OnyxParser* parser) { OnyxTypeInfo* type_info = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN]; - + OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL); if (symbol == NULL) return type_info; - + onyx_token_null_toggle(*symbol); - + if (!bh_hash_has(OnyxAstNode*, parser->identifiers, symbol->token)) { onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->token); } else { OnyxAstNode* type_info_node = bh_hash_get(OnyxAstNode*, parser->identifiers, symbol->token); - + if (type_info_node->kind == ONYX_AST_NODE_KIND_TYPE) { type_info = type_info_node->type; } } - + onyx_token_null_toggle(*symbol); return type_info; } static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) { expect(parser, TOKEN_TYPE_OPEN_PAREN); - + if (parser->curr_token->type == TOKEN_TYPE_CLOSE_PAREN) { parser_next_token(parser); return NULL; } - + OnyxAstNodeParam* first_param = NULL; - + OnyxAstNodeParam* curr_param = NULL; OnyxAstNodeParam* trailer = NULL; - + OnyxToken* symbol; while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) { if (parser->curr_token->type == TOKEN_TYPE_SYM_COMMA) parser_next_token(parser); - + symbol = expect(parser, TOKEN_TYPE_SYMBOL); - + curr_param = (OnyxAstNodeParam *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PARAM); curr_param->token = symbol; curr_param->type = parse_type(parser); - + if (first_param == NULL) first_param = curr_param; - + curr_param->next = NULL; if (trailer) trailer->next = curr_param; - + trailer = curr_param; } - + parser_next_token(parser); // Skip the ) return first_param; } static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser) { expect(parser, TOKEN_TYPE_KEYWORD_PROC); - + OnyxAstNodeFuncDef* func_def = (OnyxAstNodeFuncDef *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FUNCDEF); func_def->param_count = 0; - + OnyxAstNodeParam* params = parse_function_params(parser); func_def->params = params; - + for (OnyxAstNode* walker = (OnyxAstNode *) params; walker != NULL; walker = walker->next) func_def->param_count++; - + expect(parser, TOKEN_TYPE_RIGHT_ARROW); - + OnyxTypeInfo* return_type = parse_type(parser); func_def->return_type = return_type; - + func_def->body = parse_block(parser); return func_def; } - static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { switch (parser->curr_token->type) { - case TOKEN_TYPE_KEYWORD_USE: + case TOKEN_TYPE_KEYWORD_USE: assert(0); break; - - case TOKEN_TYPE_KEYWORD_EXPORT: + + case TOKEN_TYPE_KEYWORD_EXPORT: assert(0); - break; - - case TOKEN_TYPE_SYMBOL: { - OnyxToken* symbol = parser->curr_token; - parser_next_token(parser); - - expect(parser, TOKEN_TYPE_SYM_COLON); - expect(parser, TOKEN_TYPE_SYM_COLON); - - if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) { - OnyxAstNodeFuncDef* func_def = parse_function_definition(parser); - func_def->token = symbol; - return (OnyxAstNode *) func_def; - - } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) { - // Handle struct case - assert(0); - } else { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, - parser->curr_token->pos, - onyx_get_token_type_name(parser->curr_token->type)); - } - } break; + break; + + case TOKEN_TYPE_SYMBOL: { + OnyxToken* symbol = parser->curr_token; + parser_next_token(parser); + + expect(parser, TOKEN_TYPE_SYM_COLON); + expect(parser, TOKEN_TYPE_SYM_COLON); + + if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) { + OnyxAstNodeFuncDef* func_def = parse_function_definition(parser); + func_def->token = symbol; + return (OnyxAstNode *) func_def; + + } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) { + // Handle struct case + assert(0); + } else { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, + parser->curr_token->pos, + onyx_get_token_type_name(parser->curr_token->type)); + } + } break; } - + parser_next_token(parser); return NULL; } @@ -275,15 +282,15 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { OnyxAstNode* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind) {\ OnyxAstNode* node = (OnyxAstNode *) bh_alloc(alloc, sizeof(OnyxAstNode)); node->kind = kind; - + return node; } OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs) { OnyxParser parser; - + bh_hash_init(bh_heap_allocator(), parser.identifiers); - + OnyxTypeInfo* it = &builtin_types[0]; while (it->kind != 0xffffffff) { OnyxAstNode* tmp = onyx_ast_node_new(alloc, ONYX_AST_NODE_KIND_TYPE); @@ -291,13 +298,13 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, Onyx bh_hash_put(OnyxAstNode*, parser.identifiers, (char *)it->name, tmp); it++; } - + parser.allocator = alloc; parser.tokenizer = tokenizer; parser.curr_token = tokenizer->tokens; parser.prev_token = NULL; parser.msgs = msgs; - + return parser; } @@ -307,18 +314,18 @@ void onyx_parser_free(OnyxParser* parser) { OnyxAstNode* onyx_parse(OnyxParser *parser) { OnyxAstNode* program = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PROGRAM); - + OnyxAstNode** prev_stmt = &program->next; OnyxAstNode* curr_stmt = NULL; while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) { curr_stmt = parse_top_level_statement(parser); - + // Building a linked list of statements down the "next" chain if (curr_stmt != NULL && curr_stmt != &error_node) { *prev_stmt = curr_stmt; prev_stmt = &curr_stmt->next; } } - + return program; } diff --git a/progs/minimal.onyx b/progs/minimal.onyx index 9985f5a7..bbb2d1c8 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -1,6 +1,6 @@ /* This is a comment */ -log :: proc (a i32, b i64) -> i32 ---; +log :: proc (a i32, b i32) -> i32 ---; add :: proc (a i32, b i32) -> i32 { /* More comments */ -- 2.25.1