Allow underscore separators in number and bytes literals

For instance, `1_000_000_000` or `#FFFF_FFFF_FFFF_FFFF`
This commit is contained in:
Ulf Norell 2019-09-23 14:04:09 +02:00
parent a21715a657
commit f81dc88526
3 changed files with 32 additions and 9 deletions

View File

@ -13,14 +13,15 @@
override/2, push/2, pop/1]). override/2, push/2, pop/1]).
lexer() -> lexer() ->
Number = fun(Digit) -> [Digit, "+(_", Digit, "+)*"] end,
DIGIT = "[0-9]", DIGIT = "[0-9]",
HEXDIGIT = "[0-9a-fA-F]", HEXDIGIT = "[0-9a-fA-F]",
LOWER = "[a-z_]", LOWER = "[a-z_]",
UPPER = "[A-Z]", UPPER = "[A-Z]",
CON = [UPPER, "[a-zA-Z0-9_]*"], CON = [UPPER, "[a-zA-Z0-9_]*"],
INT = [DIGIT, "+"], INT = Number(DIGIT),
HEX = ["0x", HEXDIGIT, "+"], HEX = ["0x", Number(HEXDIGIT)],
BYTES = ["#", HEXDIGIT, "+"], BYTES = ["#", Number(HEXDIGIT)],
WS = "[\\000-\\ ]+", WS = "[\\000-\\ ]+",
ID = [LOWER, "[a-zA-Z0-9_']*"], ID = [LOWER, "[a-zA-Z0-9_']*"],
TVAR = ["'", ID], TVAR = ["'", ID],
@ -53,7 +54,7 @@ lexer() ->
, {CHAR, token(char, fun parse_char/1)} , {CHAR, token(char, fun parse_char/1)}
, {STRING, token(string, fun parse_string/1)} , {STRING, token(string, fun parse_string/1)}
, {HEX, token(hex, fun parse_hex/1)} , {HEX, token(hex, fun parse_hex/1)}
, {INT, token(int, fun list_to_integer/1)} , {INT, token(int, fun parse_int/1)}
, {BYTES, token(bytes, fun parse_bytes/1)} , {BYTES, token(bytes, fun parse_bytes/1)}
%% Identifiers (qualified first!) %% Identifiers (qualified first!)
@ -117,10 +118,18 @@ unescape([$\\, Code | Chars], Acc) ->
unescape([C | Chars], Acc) -> unescape([C | Chars], Acc) ->
unescape(Chars, [C | Acc]). unescape(Chars, [C | Acc]).
parse_hex("0x" ++ Chars) -> list_to_integer(Chars, 16). strip_underscores(S) ->
lists:filter(fun(C) -> C /= $_ end, S).
parse_bytes("#" ++ Chars) -> parse_hex("0x" ++ S) ->
N = list_to_integer(Chars, 16), list_to_integer(strip_underscores(S), 16).
Digits = (length(Chars) + 1) div 2,
parse_int(S) ->
list_to_integer(strip_underscores(S)).
parse_bytes("#" ++ S0) ->
S = strip_underscores(S0),
N = list_to_integer(S, 16),
Digits = (length(S) + 1) div 2,
<<N:Digits/unit:8>>. <<N:Digits/unit:8>>.

View File

@ -152,7 +152,8 @@ compilable_contracts() ->
"manual_stdlib_include", "manual_stdlib_include",
"list_comp", "list_comp",
"payable", "payable",
"unapplied_builtins" "unapplied_builtins",
"underscore_number_literals"
]. ].
not_yet_compilable(fate) -> []; not_yet_compilable(fate) -> [];

View File

@ -0,0 +1,13 @@
contract UnderscoreNumberLiterals =
entrypoint ints() : list(int) =
[ 1_999_000_000,
19_99_00_00_00,
0xfff_FFF_010 ]
entrypoint bytes() : list(bytes(4)) =
[ #abcd_ef_00,
#01_02_03_04,
#aaaa_FFFF ]