scratch work

This commit is contained in:
Peter Harpending
2026-06-11 18:23:00 -07:00
parent fe380fcdb3
commit 9a6879cc4a
4 changed files with 864 additions and 0 deletions
+263
View File
@@ -0,0 +1,263 @@
-spec consume_token(SourceStr) -> {tok, Token, Rest}
| none
when SourceStr :: string(),
Token :: token(),
Rest :: string().
consume_token(SrcStr) ->
consume_token_II(token_parsers(), SrcStr).
consume_token_II([TokenParser | Rest], SrcStr) ->
case consume_token(TokenParser, SrcStr) of
none -> consume_token_II(Rest, SrcStr);
Tok -> Tok;
end;
consume_token_II([], _) ->
none.
% - `Id = [a-z_][A-Za-z0-9_']*` identifiers start with a lower case letter.
consume_token(identifier, [LowerUnder | Rest])
when (($a =< LowerUnder) andalso (LowerUnder =< $z))
orelse ($_ =:= LowerUnder)
->
{TokenTail, NewRest} = takewhile(fun is_ulduq/1, Rest),
TokenStr = [LowerUnder | TokenTail],
Token = #identifier{str = TokenStr},
{tok, Token, NewRest};
consume_token(identifier, _) ->
none;
% - `Con = [A-Z][A-Za-z0-9_']*` constructors start with an upper case letter.
consume_token(constructor, [Upper | Rest])
when ($A =< Upper) andalso (Upper =< $Z) ->
{TokenTail, NewRest} = takewhile(fun is_ulduq/1, Rest),
TokenStr = [Upper | TokenTail],
Token = #constructor{str = TokenStr},
{tok, Token, NewRest};
consume_token(constructor, _) ->
none;
% - `QId = (Con\.)+Id` qualified identifiers (e.g. `Map.member`)
consume_token(qualified_identifier, Str) ->
case consume_qualifiers(Str) of
{[], _} ->
none;
{Qualifiers, Rest0} ->
case consume_token(identifier, Rest0) of
{tok, Identifier, Rest1} ->
Token = #qualified_identifier{qualifiers = Qualifiers,
identifier = Identifier},
{tok, Token, Rest1};
none ->
none
end
end;
consume_token(qualified_constructor, Str) ->
case consume_qualifiers(Str) of
{[], _} ->
none;
{Qualifiers, Rest0} ->
case consume_token(constructor, Rest0) of
{tok, Constructor, Rest1} ->
Token = #qualified_constructor{qualifiers = Qualifiers,
constructor = Constructor},
{tok, Token, Rest1};
none ->
none
end
end;
% - `TVar = 'Id` type variable (e.g `'a`, `'b`)
consume_token(type_variable, [$' | Rest0]) ->
case consume_token(identifier, Rest0) of
{tok, Identifier, Rest1} ->
Token = #type_variable{identifier = Identifier},
{tok, Token, Rest1};
none ->
none
end;
consume_token(type_variable, _) ->
none;
consume_token(int, Str) ->
case {consume_int16(Str), consume_int10(Str)} of
{{tok, Int16, Rest}, _} ->
{tok, #int{inner_int = Int16}, Rest};
{none, {tok, Int10, Rest}} ->
{tok, #int{inner_int = Int10}, Rest};
{none, none} ->
none
end;
consume_token(string, _) ->
none;
consume_token(char, _) ->
none;
consume_token(akstr, _) ->
none;
consume_token(ctstr, _) ->
none;
consume_token(sgstr, _) ->
none.
-spec consume_int16(SrcStr) -> {tok, #int16{}, Rest} | none
when SrcStr :: string(),
Rest :: string().
consume_int16("0x" ++ Rest0) ->
case consume_hex_digits(Rest0) of
{piece16, Piece0, Rest1} ->
{Pieces, Rest2} = consume_uhexs(Rest1),
Token = #int16{hex_pieces = [Pieces0 | Pieces]},
{tok, Token, Rest2};
none ->
none
end;
consume_int16(_) ->
none.
-spec takewhile(Pred, List) -> {Taken, Rest}
when Pred :: fun( (Item) -> boolean() ),
List :: [Item],
Item :: any(),
Taken :: [Item],
Rest :: [Item].
takewhile(Pred, List) ->
takewhile(Pred, List, []).
takewhile(Pred, [X | Xs], Acc) ->
case Pred(X) of
true -> takewhile(Pred, Xs, [X | Acc]);
false -> {lists:reverse(Acc), Xs};
end;
takewhile(_, [], Acc) ->
{lists:reverse(Acc), []}.
-spec is_ulduq(Char) -> boolean()
when Char :: integer().
% @doc upper lower digit underscore quote
is_ulduq(C) ->
(($A =< C) andalso (C =< $Z))
orelse (($a =< C) andalso (C =< $z))
orelse (C =:= $_)
orelse (C =:= $').
% - `Id = [a-z_][A-Za-z0-9_']*` identifiers start with a lower case letter.
-record(id,
{str :: string()}).
% - `Con = [A-Z][A-Za-z0-9_']*` constructors start with an upper case letter.
-record(con,
{str :: string()}).
% - `QId = (Con\.)+Id` qualified identifiers (e.g. `Map.member`)
-record(qid,
{qualifiers :: [#con{}],
identifier :: #id{}}).
% - `QCon = (Con\.)+Con` qualified constructor
-record(qcon,
{qualifiers :: [#con{}],
constructor :: #con{}}).
% - `TVar = 'Id` type variable (e.g `'a`, `'b`)
-record(tvar,
{identifier :: #identifier{}}).
% - `Int = [0-9]+(_[0-9]+)*|0x[0-9A-Fa-f]+(_[0-9A-Fa-f]+)*` integer literal with optional `_` separators
-record(int16,
{hex_pieces :: [string()]}).
% - `Int = [0-9]+(_[0-9]+)*|0x[0-9A-Fa-f]+(_[0-9A-Fa-f]+)*` integer literal with optional `_` separators
-record(int10,
{dec_pieces :: [string()]}).
-type int() :: int10() | int16().
% @doc
% - `Id = [a-z_][A-Za-z0-9_']*` identifiers start with a lower case letter.
% - `Con = [A-Z][A-Za-z0-9_']*` constructors start with an upper case letter.
% - `QId = (Con\.)+Id` qualified identifiers (e.g. `Map.member`)
% - `QCon = (Con\.)+Con` qualified constructor
% - `TVar = 'Id` type variable (e.g `'a`, `'b`)
% - `Int = [0-9]+(_[0-9]+)*|0x[0-9A-Fa-f]+(_[0-9A-Fa-f]+)*` integer literal with optional `_` separators
% - `Bytes = #[0-9A-Fa-f]+(_[0-9A-Fa-f]+)*` byte array literal with optional `_` separators
% - `String` string literal enclosed in `"` with escape character `\`
% - `Char` character literal enclosed in `'` with escape character `\`
% - `AccountAddress` base58-encoded 32 byte account pubkey with `ak_` prefix
% - `ContractAddress` base58-encoded 32 byte contract address with `ct_` prefix
% - `Signature` base58-encoded 64 byte cryptographic signature with `sg_` prefix
-type token() :: #id{}
| #con{}
| #qid{}
| #tvar{}
| int()
| {string, string()}
| {char, string()}
| {akstr, string()}
| {ctstr, string()}
| {sgstr, string()}.
-type token_shape() :: id
| con
| qid,
| qcon
| tvar
| int
| string
| char
| akstr
| ctstr
| sgstr.
%-----------------------------------------
% functions
%-----------------------------------------
-spec token_parsers() -> [atom()].
% in parse order
token_parsers() ->
[id,
con,
qid,
qcon,
tvar,
int,
string,
char,
akstr,
ctstr,
sgstr].
-spec token_consume(Matcher, SourceString) -> MaybeToken
when Matcher :: token_shape(),
SourceString :: string(),
MaybeToken :: {match, Token :: token(), Rest :: string()}
| nomatch.
% - `Id = [a-z_][A-Za-z0-9_']*` identifiers start with a lower case letter.
token_consume(id, [AZU | Src1]) when $_ =:= AZU; $a =< AZU, AZU =< $z ->
{RestOfId, Src2} = tdw(fun is_ulduq/1, Src1),
{match, #id{str = [AZU | RestOfId]}, Src2};
token_consume(id, _) ->
nomatch;
% - `Con = [A-Z][A-Za-z0-9_']*` constructors start with an upper case letter.
token_consume(con, [AZ | Src1]) -> when $A =< AZU, AZU =< $Z ->
{RestOfCon, Src2} = tdw(fun is_ulduq/1, Src1),
{match, #con{str = [AZ | RestOfCon]}, Src2};
token_consume(con, _) ->
nomatch;
% - `QId = (Con\.)+Id` qualified identifiers (e.g. `Map.member`)
token_consume(qid, Src0) ->
case one_or_more({seq, con, {char, $.}}, Src0)