% This is a header file that contains gsc's record types % % This is in order to % 1. share records across modules; and, % 2. allow external modules to just use the gsc records -type tk_shape() :: bcom % /* ... */ | lcom % // | ws % whitespace % literals | char % 'a' | string % "foo" | int10 % 69_420 | int16 % 0xDEAD_BEEF | bytes % #DEAD_BEEF | ak % ak_ABC | ct % ct_ABC | sg % sg_ABC % kwds/variables/etc | id % foo, foo_bar, foo_bar'baz' _'foo' | con % Foo, Foo_Bar, FooBar | qid % Foo.Bar.baz | qcon % Foo.Bar.Baz | tvar % 'foo, 'foo_bar, '_'foo'_'bar''' % kwds ops and punct are all collapsed by % so_scan:scan down to eg {'contract', {420, 69}} % where {420, 69} is the source location % these are three different parsers | kwd % contract, interface, payable, etc | op % "=!<>+-*/:&|?~@^" | punct % ".." | oneof(",.;()[]{}") % kwds and punct are kind of the same thing % but i'll keep them separate now for my own sanity. ok % i guess op or symbol or whatever is fine. % % not going to overthink. if having them separate % becomes an issue it's easy enough to collapse. harder % to separate afterward if collapsing is wrong. . -type tk_pos() :: {Line :: pos_integer(), Col :: pos_integer()}. -record(tk, {shape :: tk_shape(), pos :: tk_pos(), str :: string()}). -type tk() :: #tk{}. % tokens are in essence the "chunk boundaries" of % the file % % because we have semantic whitespace, we have to be % careful about block declarations, because we don't % have an explicit open/close block token. blocks can % be closed in one of two ways: % % 1. a new block at a previous indent level: % switch(foo) % // block starts here % Bar => bar() % Baz => baz() % quux() // ends because indent level % 2. it's part of some type of list: % % [switch(foo) % // block starts here % Bar => bar() % Baz => baz(), // ends here % switch(bizz) % // block starts here % Bar => bar() % Baz => baz()] % % in order to avoid speculatively inserting virtual % close tokens, at least on first write-out, we're % going to disambiguate list notions right away % token groups % lists = (_, _, _) % | [_, _, _] % | {_, _, _} %-record(gsc_ast1_block, % {indent = none :: none | pos_integer(), % decls = none :: [gsc_ast1_decl()]}). % %-type gsc_ast() :: % %-type gsc_list_group() :: {'(', [tk()], ')'} % | {'[', [tk()], ']'} % | {'{', [tk()], '}'} % | {proof, % . % @doc % this one is very specific so it deserves its own % record type: unterminated block comments at the end % of files. these are ok in legacy sophia, so we have to % specifically account for this error -record(gsc_err_bcom_unterminated, {prev_tokens :: [tk()], break_pos :: gsc_pos(), rest :: string()}). -record(gsc_err_no_tokmatch, {prev_tokens :: [tk()], break_pos :: gsc_pos(), rest :: string()}). -record(gsc_err_delims, {past :: [tk()], open_stack :: [tk()], bad_close :: tk(), future :: [tk()]}). % FIXME -record(gsc_err_nyi, {}). -record(gsc_err_empty_file, {}). %-record(src_parse_error, % {atom = none :: none | atom(), % string = %j-record(gsc_err_gulp_ct, %j {gulped :: % @doc % generic placeholder error for now -record(gsc_err, {atom :: atom(), string = none :: none | iolist(), extra = none :: none | any()}). % @doc all errors SFC can return conveniently listed in % one place -type gsc_err() :: #gsc_err_bcom_unterminated{} | #gsc_err_no_tokmatch{} | #gsc_err_nyi{} | #gsc_err_empty_file{} | #gsc_err{}.