Mostly everything!

This commit is contained in:
Scott Richmond 2023-11-26 17:28:15 -05:00
parent f1554ef2e3
commit 2bec60f608
4 changed files with 369 additions and 19 deletions

View File

@ -2,19 +2,321 @@
@skip { space | comment } @skip { space | comment }
line { expression terminator+ } line { (expression | toplevel) terminator+ }
expression { Boolean | Nil | String | Number } toplevel {
Import
| Use
| Ns
}
Import {
skw<"import">
String
skw<"as">
Word
}
Use { skw<"use"> Word }
Ns {
skw<"ns"> Word "{"
separator*
assoc_term (separator+ assoc_term)*
separator*
"}"
}
expression { non_binding | binding }
binding { Let | Ref | Fn_Named | Fn_Compound }
Ref { skw<"ref"> Word "=" expression }
non_binding { simple | complex }
synth_root { Word | Keyword }
synth_term { Args | Keyword }
arg_term { Placeholder | expression }
Args {
("(" separator* ")")
| ("("
separator*
arg_term (separator+ arg_term)*
separator*
")")
}
Synthetic { synth_root synth_term+ }
complex {
Block
| If
| If_Let
| Match
| When
//| Do
//| Bind
| Loop
| Repeat
| Each
}
Repeat { skw<"repeat"> (Word | Number) Block }
Each { skw<"each"> simple "do" (Fn_Clause | Fn_Clauses) }
Recur { skw<"recur"> Args }
Loop { skw<"loop"> simple "with" (Fn_Clause | Fn_Clauses) }
simple { atom | collection | Synthetic | Fn_Lambda | Recur }
Fn_Clause { Tuple_Pattern "->" non_binding }
Fn_Clauses {
"{"
terminator*
Fn_Clause (terminator+ Fn_Clause)*
terminator*
"}"
}
Fn_Compound { skw<"fn"> Word Fn_Clauses }
Fn_Named {
skw<"fn"> Word Fn_Clause
}
Fn_Lambda { skw<"fn"> Fn_Clause }
// TODO: figure out precedence with do/bind exprs
// do_expr { Fn_Lambda | Synthetic | Word | Keyword }
// Do {
// skw<"do"> simple (~ambig newline* ">" do_expr)+
// }
// Bind {
// skw<"bind">
// simple
// (!pipeline pipeline)+
// }
Pattern {
Tuple_Pattern
| List_Pattern
| Dict_Pattern
| Struct_Pattern
| atom
| Placeholder
}
Placeholder { "_" }
ellipsis { "..." }
Splattern { ellipsis (Word | Placeholder) }
Tuple_Pattern {
("(" separator* ")")
| ("("
separator*
(Pattern separator+)* (Pattern | Splattern)
separator*
")")
}
List_Pattern {
("[" separator* "]")
| ("["
separator*
(Pattern separator+)* (Pattern | Splattern)
separator*
"]")
}
Assoc_Pattern {
Word
| (Keyword Pattern)
}
Dict_Pattern {
("#{" separator* "}")
| ("#{"
separator*
(Assoc_Pattern separator+)* (Assoc_Pattern | Splattern)
separator*
"}")
}
Struct_Pattern {
("@{" separator* "}")
| ("@{"
separator*
(Assoc_Pattern separator+)* (Assoc_Pattern | Splattern)
separator*
"}")
}
Let {
skw<"let">
Pattern
"="
non_binding
}
Else { skw<"else"> }
Match_Clause {(Pattern | Else) "->" newline* expression}
match_body {
Match_Clause
| (
"{"
terminator*
Match_Clause (terminator+ Match_Clause)*
terminator*
"}"
)
}
Match {
skw<"match">
simple
skw<"with">
match_body
}
When_Clause {
(simple | Placeholder | Else) "->" newline* expression
}
When {
skw<"when"> "{"
terminator*
When_Clause (terminator+ When_Clause)*
terminator*
"}"
}
If {
skw<"if"> simple newline*
skw<"then"> expression ~ambig newline*
skw<"else"> expression
}
If_Let {
skw<"if"> skw<"let">
Pattern "=" simple
skw<"then"> expression newline*
skw<"else"> expression
}
Block {
"{"
terminator*
expression (terminator+ expression)*
terminator*
"}"
}
collection {
Tuple
| List
| Set
| Dict
| Struct
}
Tuple {
( "(" // non-empty
separator*
non_binding (separator+ non_binding)*
separator*
")" )
| "(" separator* ")" // empty
}
Splat { ellipsis Word }
linear_term { Splat | non_binding }
List {
("["
separator*
linear_term (separator+ linear_term)*
separator*
"]" )
| "[" separator* "]"
}
Set {
("${"
separator*
linear_term (separator+ linear_term)*
separator*
"}")
| "${" separator* "}"
}
assoc_term {
Word
| (Keyword non_binding)
}
dict_term {
assoc_term
| Splat
}
Dict {
("#{"
separator*
dict_term (separator+ dict_term)*
separator*
"}" )
| "#{" separator* "}"
}
Struct {
("@{"
separator*
assoc_term (separator+ assoc_term)*
separator*
"}")
| "@{" separator* "}"
}
atom { Boolean | Nil | String | Number | Keyword | Word }
kw<term> { @specialize[@name={term}]<Word, term> }
skw<term> { @specialize<Word, term> }
Keyword { ":" Word }
Boolean {
kw<"true">
| kw<"false">
}
Nil {
skw<"nil">
}
@tokens { @tokens {
Word { $[a-z] $[a-zA-Z_\-?/!]* }
space { $[ \t\r]+ } space { $[ \t\r]+ }
comment { "&" ![\n]* } comment { "&" ![\n]* }
Boolean { "true" | "false" }
Nil { "nil" }
String { '"' (!["\\] | "\\" _)* '"' } String { '"' (!["\\] | "\\" _)* '"' }
int { $[1-9]$[0-9]* } int { $[1-9]$[0-9]* | "0" }
float { ("0" | int ) $[0.9]+} float { ("0" | int ) "." $[0-9]+}
Number { int | float } Number { "-"? (int | float) }
separator { $[,\n] } separator { $[,\n] }
terminator { $[;\n] } terminator { $[;\n] }
newline { "\n" }
} }

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,46 @@
export const export const
Script = 1, Script = 1,
Boolean = 2, Boolean = 2,
Nil = 3, Word = 3,
String = 4, Nil = 6,
Number = 5 String = 7,
Number = 8,
Keyword = 9,
Tuple = 10,
List = 11,
Splat = 12,
Set = 13,
Dict = 14,
Struct = 15,
Synthetic = 16,
Args = 17,
Placeholder = 18,
Fn_Lambda = 19,
Fn_Clause = 20,
Tuple_Pattern = 21,
Pattern = 22,
List_Pattern = 23,
Splattern = 24,
Dict_Pattern = 25,
Assoc_Pattern = 26,
Struct_Pattern = 27,
Recur = 28,
Block = 29,
If = 30,
If_Let = 31,
Match = 32,
Match_Clause = 33,
Else = 34,
When = 35,
When_Clause = 36,
Loop = 37,
Fn_Clauses = 38,
Repeat = 39,
Each = 40,
Let = 41,
Ref = 42,
Fn_Named = 43,
Fn_Compound = 44,
Import = 45,
Use = 46,
Ns = 47

View File

@ -1,6 +1,12 @@
import {parser} from "./parser.js" import {parser} from "./parser.js"
const source = "nil; true; false; 12; \"foo\"" const source = `
if foo
then do abcd
> xyz
>
else asdf
`
const parse = (source) => parser.parse(source.concat("\n")) const parse = (source) => parser.parse(source.concat("\n"))