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, Colon,
Tick, Tick,
Backtick, Backtick,
At,
Comma, Comma,
Period, Period,
Equal, Equal,
@ -277,6 +278,7 @@ class Scanner
case ':': addToken(TokenType.Colon); break; case ':': addToken(TokenType.Colon); break;
case '\'': addToken(TokenType.Tick); break; case '\'': addToken(TokenType.Tick); break;
case '`': addToken(TokenType.Backtick); break; case '`': addToken(TokenType.Backtick); break;
case '@': addToken(TokenType.At); break;
case ',': addToken(TokenType.Comma); break; case ',': addToken(TokenType.Comma); break;
case '.': addToken(TokenType.Period); break; case '.': addToken(TokenType.Period); break;
case '*': addToken(TokenType.Asterisk); break; case '*': addToken(TokenType.Asterisk); break;

View File

@ -1,6 +1,6 @@
expression -> expression ->
| literal | literal
// | IDENTIFIER // | identifier
// | sequence // | sequence
| unary | unary
| binary | binary
@ -15,18 +15,19 @@ expression ->
| grouping ; | grouping ;
literal -> NUMBER | STRING ; literal -> NUMBER | STRING ;
identifier -> IDENTIFIER | "@" STRING ;
grouping -> "(" expression ")" ; grouping -> "(" expression ")" ;
unary -> ( "-" | "!" ) expression ; unary -> ( "-" | "!" ) expression ;
binary -> expression operator expression ; binary -> expression operator expression ;
operator -> operator ->
| "==" | "!=" | "<" | "<=" | ">" | ">=" | "==" | "!=" | "<" | "<=" | ">" | ">="
| "+" | "-" | "*" | "/" | "+" | "-" | "*" | "/"
| "|>" | "<|" | ">>" | "<<" // | "|>" | "<|" | ">>" | "<<"
| "++" ; | "++" ;
if -> "if" expression "then" expression "else" expression ; if -> "if" expression "then" expression "else" expression ;
variant -> "`" IDENTIFIER ( "(" ( expression ( "," expression)* )? ")" )? ; variant -> "`" identifier ( "(" ( expression ( "," expression)* )? ")" )? ;
record -> record ->
"{" ( IDENTIFIER "=" expression ( "," IDENTIFIER "=" expression )* )? "}" ; "{" ( identifier "=" expression ( "," identifier "=" expression )* )? "}" ;
list -> "[" ( expression ( "," expression )* )? "]" ; list -> "[" ( expression ( "," expression )* )? "]" ;
field -> expression "." identifier ; field -> expression "." identifier ;
index -> expression "[" expression "]" ; index -> expression "[" expression "]" ;

View File

@ -2,6 +2,7 @@
# Moved type annotations into bindings. # Moved type annotations into bindings.
# Added def keyword for top-level bindings. # Added def keyword for top-level bindings.
# Added and keyword to multiple-binding let-expressions. # Added and keyword to multiple-binding let-expressions.
# Added arbitrary strings as identifiers.
# v3 # v3
# Added type aliases. # Added type aliases.
@ -37,7 +38,7 @@ def binary_tree(compare: fn('a) -> 'a) -> {
empty: tree 'a, empty: tree 'a,
insert: fn(tree 'a, 'a) -> tree 'a, insert: fn(tree 'a, 'a) -> tree 'a,
find: fn(tree 'a, 'a) -> maybe '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, # 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. # 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) `eq => `some(value)
`lt => find(left, needle) `lt => find(left, needle)
`gt => find(right, needle) `gt => find(right, needle)
and func_we_dont_care_about() = print("ignore me") and @"func we don't care about"() = print("ignore me")
in {empty, insert, find, func_we_dont_care_about} in {empty, insert, find, @"func we don't care about"}
# Prints "`some(2)". # Prints "`some(2)".
def do_tree_things() = def do_tree_things() =
# Assume that int_compare is in the stdlib or something. # 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 # 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. # that Scala does it the same way. Also note the pipe operator from Elm.
in in
empty |> insert(_, 5) |> insert(_, 2) |> insert(_, 10) empty |> insert(_, 5) |> insert(_, 2) |> insert(_, 10)
|> find(2) |> print; |> find(2) |> print;
stuff_we_dont_need @"stuff we don't need"
# Prints "`some(2)\nignore me". # 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} = def annotate(note: 'a, obj: {|'b}) -> {note: 'a | 'b} =
{ note | obj } { note | obj }