duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 778f643dbfe9a81ee03f6dc26f8a841f5b8717af
parent 5693daf9274857233e9dae883e3e0214a0cc090f
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sun,  2 Apr 2023 20:25:33 -0400

halcc: fix complex declaration parsing

Diffstat:
Mfs/comp/c/ptype.fs | 14++++++++++----
Mfs/comp/c/type.fs | 1+
Mfs/tests/comp/c/type.fs | 56++++++++++++++++++++++++++++----------------------------
3 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/fs/comp/c/ptype.fs b/fs/comp/c/ptype.fs @@ -47,10 +47,16 @@ alias _err parseDeclarator ( type -- cdecl ) \ forward declaration 0 begin ( type lvl ) '*' readChar? while ( type lvl tok ) 1+ repeat ( type lvl tok ) dup '(' isChar? if ( type lvl tok ) - drop swap _parseDeclarator read) ( lvl cdecl ) - \ type recursion in C is "inside out". The cdecl we have now is the result. - \ We need to apply indirection levels we've already parsed to it. - tuck to+ CDecl lvl + \ Complex type parsing is messed up. Example "int (*foo)[42]", a pointer to + \ an array of int (an array of int* is "int *foo[42]"). Right now, "type" is + \ "int" and we're about to parse the "(*foo)" part. This will give us a + \ CDecl {type=int,lvl=1,name=foo}. Now, for the _post part, we want a brand + \ new CDecl {type=int,lvl=0,nbelem=42,name=null}. Then, we set the first + \ CDecl's type to the newly parsed type. We have our "int (*foo)[42]". + \ The "lvl" we've just parsed above goes to the *inner* type. + drop over parseDeclarator read) ( type inner-lvl outer-type ) + rot NULLSTR swap CDecl :new _post ( il ot inner-type ) + rot over to CDecl lvl over to CDecl type ( cdecl ) else ( type lvl tok ) dup isIdent? not if to nexttputback NULLSTR then ( type lvl name ) rot CDecl :new ( lvl cdecl ) tuck to CDecl lvl then _post ; diff --git a/fs/comp/c/type.fs b/fs/comp/c/type.fs @@ -82,6 +82,7 @@ struct[ CDecl dup lvl if drop 0 else _ then ; : :structarrow? ( self -- f ) \ is an indirect Struct reference? dup lvl 1 = if _ else drop 0 then ; + : :funcptr? ( self -- f ) bi lvl 1 = | type :funcsig? and ; : :constfuncsig? ( self -- f ) bi :funcsig? | :isglobal? and ; \ Arrays, function signatures and struct ident "naturally" yield references. diff --git a/fs/tests/comp/c/type.fs b/fs/tests/comp/c/type.fs @@ -55,41 +55,41 @@ dup CDecl lvl 1 #eq dup CDecl nbelem 42 #eq CDecl name S" foo" #s= -\ TODO: This test is not working. It's supposed to yield a pointer to an array -\ of 42 ints, not an array of 42 pointers to ints. -\ _parse int (*foo)[42] STOP -\ dup CDecl type TYPE_INT # -\ dup CDecl type lvl 1 #eq -\ dup CDecl nbelem 0 #eq -\ dup CDecl name S" foo" #s= -\ CDecl type -\ dup CDecl type TYPE_INT #eq -\ dup CDecl nbelem 42 #eq -\ CDecl name NULLSTR #s= +_parse int (*foo)[42] STOP +dup CDecl lvl 1 #eq +dup CDecl nbelem 0 #eq +dup CDecl name S" foo" #s= +CDecl type + dup CDecl type TYPE_INT #eq + dup CDecl lvl 0 #eq + dup CDecl nbelem 42 #eq + CDecl name NULLSTR #s= _parse unsigned int (*foo)(char,short) STOP -dup CDecl :funcsig? # +dup CDecl :funcptr? # dup CDecl name S" foo" #s= -dup CDecl type TYPE_UINT #eq -CDecl args -dup CDecl type TYPE_CHAR #eq -dup CDecl offset 4 #eq \ PS args are always 4b in size -llnext -dup CDecl type TYPE_SHORT #eq -CDecl offset 0 #eq +CDecl type + dup CDecl type TYPE_UINT #eq + CDecl args + dup CDecl type TYPE_CHAR #eq + dup CDecl offset 4 #eq \ PS args are always 4b in size + llnext + dup CDecl type TYPE_SHORT #eq + CDecl offset 0 #eq \ We can also have a function signature with argument names. _parse unsigned int (*foo)(short bar,char baz) STOP -dup CDecl :funcsig? # +dup CDecl :funcptr? # dup CDecl name S" foo" #s= -CDecl args -dup CDecl name S" bar" #s= -dup CDecl type TYPE_SHORT #eq -dup CDecl offset 4 #eq -llnext -dup CDecl name S" baz" #s= -dup CDecl type TYPE_CHAR #eq -CDecl offset 0 #eq +CDecl type + CDecl args + dup CDecl name S" bar" #s= + dup CDecl type TYPE_SHORT #eq + dup CDecl offset 4 #eq + llnext + dup CDecl name S" baz" #s= + dup CDecl type TYPE_CHAR #eq + CDecl offset 0 #eq _parse Struct1 *mystructptr STOP capture printtype