Added arbitrary-string idents to grammar

This commit is contained in:
Brandon Dyck 2023-06-28 16:06:44 -06:00
parent aa440742ca
commit 1264aca7f3
3 changed files with 14 additions and 10 deletions

View File

@ -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;

View File

@ -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 "]" ;

View File

@ -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 }