diff --git a/Program.cs b/Program.cs index a5c2c31..e7acf23 100644 --- a/Program.cs +++ b/Program.cs @@ -92,6 +92,7 @@ public enum TokenType Colon, Tick, Backtick, + At, Comma, Period, Equal, @@ -277,6 +278,7 @@ class Scanner case ':': addToken(TokenType.Colon); break; case '\'': addToken(TokenType.Tick); break; case '`': addToken(TokenType.Backtick); break; + case '@': addToken(TokenType.At); break; case ',': addToken(TokenType.Comma); break; case '.': addToken(TokenType.Period); break; case '*': addToken(TokenType.Asterisk); break; diff --git a/grammar.txt b/grammar.txt index 7313f60..ac1dce0 100644 --- a/grammar.txt +++ b/grammar.txt @@ -1,6 +1,6 @@ expression -> | literal -// | IDENTIFIER +// | identifier // | sequence | unary | binary @@ -15,18 +15,19 @@ expression -> | grouping ; literal -> NUMBER | STRING ; +identifier -> IDENTIFIER | "@" STRING ; grouping -> "(" expression ")" ; unary -> ( "-" | "!" ) expression ; binary -> expression operator expression ; operator -> | "==" | "!=" | "<" | "<=" | ">" | ">=" | "+" | "-" | "*" | "/" - | "|>" | "<|" | ">>" | "<<" +// | "|>" | "<|" | ">>" | "<<" | "++" ; if -> "if" expression "then" expression "else" expression ; -variant -> "`" IDENTIFIER ( "(" ( expression ( "," expression)* )? ")" )? ; +variant -> "`" identifier ( "(" ( expression ( "," expression)* )? ")" )? ; record -> - "{" ( IDENTIFIER "=" expression ( "," IDENTIFIER "=" expression )* )? "}" ; + "{" ( identifier "=" expression ( "," identifier "=" expression )* )? "}" ; list -> "[" ( expression ( "," expression )* )? "]" ; field -> expression "." identifier ; index -> expression "[" expression "]" ; diff --git a/strawman4.txt b/strawman4.txt index 6b0ec27..2683fff 100644 --- a/strawman4.txt +++ b/strawman4.txt @@ -2,6 +2,7 @@ # Moved type annotations into bindings. # Added def keyword for top-level bindings. # Added and keyword to multiple-binding let-expressions. +# Added arbitrary strings as identifiers. # v3 # Added type aliases. @@ -37,7 +38,7 @@ def binary_tree(compare: fn('a) -> 'a) -> { empty: tree 'a, insert: fn(tree 'a, 'a) -> tree 'a, find: fn(tree 'a, 'a) -> maybe 'a, - func_we_dont_care_about: fn() -> unit + @"func we don't care about": fn() -> unit } = # A let expression can bind multiple names. Functions have access to all names within the expression, # while other values only have access to names bound before them. @@ -60,22 +61,22 @@ def binary_tree(compare: fn('a) -> 'a) -> { `eq => `some(value) `lt => find(left, needle) `gt => find(right, needle) - and func_we_dont_care_about() = print("ignore me") - in {empty, insert, find, func_we_dont_care_about} + and @"func we don't care about"() = print("ignore me") + in {empty, insert, find, @"func we don't care about"} # Prints "`some(2)". def do_tree_things() = # Assume that int_compare is in the stdlib or something. - let {insert, empty, find | stuff_we_dont_need} = binary_tree(int_compare) + let {insert, empty, find | @"stuff we don't need"} = binary_tree(int_compare) # I invented this fancy partial-application syntax with _, and then found # that Scala does it the same way. Also note the pipe operator from Elm. in empty |> insert(_, 5) |> insert(_, 2) |> insert(_, 10) |> find(2) |> print; - stuff_we_dont_need + @"stuff we don't need" # Prints "`some(2)\nignore me". -def main() = do_tree_things().func_we_dont_care_about() +def main() = do_tree_things().@"func we don't care about"() def annotate(note: 'a, obj: {|'b}) -> {note: 'a | 'b} = { note | obj }