You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
9.0 KiB
Plaintext

2 years ago
/*
* Copyright 2022, The Cozo Project Authors.
*
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
2 years ago
*/
script = _{sys_script | imperative_script | query_script}
query_script = {SOI ~ (option | rule | const_rule | fixed_rule)+ ~ EOI}
query_script_inner = {"{" ~ (option | rule | const_rule | fixed_rule)+ ~ "}"}
query_script_inner_no_bracket = { (option | rule | const_rule | fixed_rule)+ }
imperative_script = {SOI ~ imperative_stmt+ ~ EOI}
sys_script = {SOI ~ "::" ~ (compact_op | list_relations_op | list_relation_op | remove_relations_op | trigger_relation_op |
2 years ago
trigger_relation_show_op | rename_relations_op | running_op | kill_op | explain_op | access_level_op) ~ EOI}
2 years ago
compact_op = {"compact"}
running_op = {"running"}
kill_op = {"kill" ~ expr}
explain_op = {"explain" ~ "{" ~ query_script_inner_no_bracket ~ "}"}
list_relations_op = {"relations"}
2 years ago
list_relation_op = {"columns" ~ compound_ident}
remove_relations_op = {"remove" ~ (compound_ident ~ ",")* ~ compound_ident }
rename_relations_op = {"rename" ~ (rename_pair ~ ",")* ~ rename_pair }
access_level_op = {"access_level" ~ access_level ~ (compound_ident ~ ",")* ~ compound_ident}
2 years ago
access_level = {("normal" | "protected" | "read_only" | "hidden")}
trigger_relation_show_op = {"show_triggers" ~ compound_ident }
trigger_relation_op = {"set_triggers" ~ compound_ident ~ trigger_clause* }
trigger_clause = { "on" ~ (trigger_put | trigger_rm | trigger_replace) ~ "{" ~ query_script_inner_no_bracket ~ "}" }
trigger_put = {"put"}
trigger_rm = {"rm"}
trigger_replace = {"replace"}
rename_pair = {compound_ident ~ "->" ~ compound_ident}
2 years ago
from_clause = {"from" ~ expr}
to_clause = {"to" ~ expr}
WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
BLOCK_COMMENT = _{ "/*" ~ (BLOCK_COMMENT | !"*/" ~ ANY)* ~ "*/" }
LINE_COMMENT = _{ "#" ~ (!"\n" ~ ANY)* }
COMMENT = _{(BLOCK_COMMENT | LINE_COMMENT)}
prog_entry = {"?"}
var = @{(XID_START | "_") ~ (XID_CONTINUE | "_")*}
2 years ago
param = @{"$" ~ (XID_CONTINUE | "_")*}
ident = @{XID_START ~ ("_" | XID_CONTINUE)*}
2 years ago
underscore_ident = @{("_" | XID_START) ~ ("_" | XID_CONTINUE)*}
relation_ident = @{"*" ~ (compound_ident | underscore_ident)}
compound_ident = @{ident ~ ("." ~ ident)?}
rule = {rule_head ~ ":=" ~ rule_body ~ ";"?}
2 years ago
const_rule = {rule_head ~ "<-" ~ expr ~ ";"?}
fixed_rule = {rule_head ~ "<~" ~ ident ~ fixed_args_list ~ ";"?}
fixed_args_list = {"(" ~ (fixed_arg ~ ",")* ~ fixed_arg? ~ ")"}
rule_head = {(prog_entry | ident) ~ "[" ~ (head_arg ~ ",")* ~ head_arg? ~ "]"}
head_arg = {aggr_arg | var}
aggr_arg = {ident ~ "(" ~ var ~ ("," ~ expr)* ~ ")"}
fixed_arg = _{fixed_rel | fixed_opt_pair}
fixed_opt_pair = {ident ~ ":" ~ expr}
fixed_rel = {fixed_rule_rel | fixed_relation_rel | fixed_named_relation_rel }
fixed_rule_rel = {ident ~ "[" ~ (var ~ ",")* ~ var? ~ "]"}
fixed_relation_rel = {relation_ident ~ "[" ~ (var ~ ",")* ~ var? ~ validity_clause? ~ "]"}
fixed_named_relation_rel = {relation_ident ~ "{" ~ (fixed_named_relation_arg_pair ~ ",")* ~ fixed_named_relation_arg_pair? ~ validity_clause? ~ "}"}
fixed_named_relation_arg_pair = {ident ~ (":" ~ ident)?}
validity_clause = {"@" ~ expr}
rule_body = {(disjunction ~ ",")* ~ disjunction?}
2 years ago
rule_apply = {underscore_ident ~ "[" ~ apply_args ~ "]"}
relation_named_apply = {relation_ident ~ "{" ~ named_apply_args ~ validity_clause? ~ "}"}
relation_apply = {relation_ident ~ "[" ~ apply_args ~ validity_clause? ~ "]"}
disjunction = {(atom ~ "or" )* ~ atom}
atom = _{ negation | relation_named_apply | relation_apply | rule_apply | unify_multi | unify | expr | grouped}
2 years ago
unify = {var ~ "=" ~ expr}
unify_multi = {var ~ "in" ~ expr}
negation = {"not" ~ atom}
apply = {ident ~ "(" ~ apply_args ~ ")"}
apply_args = {(expr ~ ",")* ~ expr?}
named_apply_args = {(named_apply_pair ~ ",")* ~ named_apply_pair?}
named_apply_pair = {ident ~ (":" ~ expr)?}
grouped = _{"(" ~ rule_body ~ ")"}
expr = {unary_op* ~ term ~ (operation ~ unary_op* ~ term)*}
operation = _{ (op_and | op_or | op_pow | op_concat | op_add | op_sub | op_mul | op_div | op_mod |
op_ge | op_le | op_gt | op_lt | op_eq | op_ne | op_coalesce )}
op_or = { "||" }
op_and = { "&&" }
op_concat = { "++" }
op_add = { "+" }
op_sub = { "-" }
op_mul = { "*" }
op_div = { "/" }
op_mod = { "%" }
op_eq = { "==" }
op_ne = { "!=" }
op_gt = { ">" }
op_lt = { "<" }
op_ge = { ">=" }
op_le = { "<=" }
op_pow = { "^" }
op_coalesce = { "~" }
unary_op = _{ minus | negate }
minus = { "-" }
negate = { "!" }
2 years ago
term = _{ literal | param | grouping | apply | var | list }
list = { "[" ~ (expr ~ ",")* ~ expr? ~ "]" }
grouping = { "(" ~ expr ~ ")" }
option = _{(limit_option|offset_option|sort_option|relation_option|timeout_option|sleep_option|
assert_none_option|assert_some_option) ~ ";"?}
out_arg = @{var ~ ("(" ~ var ~ ")")?}
2 years ago
limit_option = {":limit" ~ expr}
offset_option = {":offset" ~ expr}
2 years ago
sort_option = {(":sort" | ":order") ~ (sort_arg ~ ",")* ~ sort_arg }
relation_option = {relation_op ~ (compound_ident | underscore_ident) ~ table_schema?}
relation_op = _{relation_create | relation_replace | relation_put | relation_rm | relation_ensure | relation_ensure_not}
relation_create = {":create"}
relation_replace = {":replace"}
relation_put = {":put"}
relation_rm = {":rm"}
relation_ensure = {":ensure"}
relation_ensure_not = {":ensure_not"}
2 years ago
timeout_option = {":timeout" ~ expr }
sleep_option = {":sleep" ~ expr }
sort_arg = { sort_dir? ~ out_arg }
sort_dir = _{ sort_asc | sort_desc }
sort_asc = {"+"}
sort_desc = {"-"}
assert_none_option = {":assert" ~ "none"}
assert_some_option = {":assert" ~ "some"}
// literals
quoted_string = ${ "\"" ~ quoted_string_inner ~ "\"" }
quoted_string_inner = { char* }
char = {
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
s_quoted_string = ${ "\'" ~ s_quoted_string_inner ~ "\'" }
s_quoted_string_inner = { s_char* }
s_char = {
!("\'" | "\\") ~ ANY
| "\\" ~ ("\'" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
raw_string = {
PUSH("_"*) ~ "\"" // push the number signs onto the stack
~ raw_string_inner
~ "\"" ~ POP // match a quotation mark and the number signs
}
raw_string_inner = {
(
!("\"" ~ PEEK) // unless the next character is a quotation mark
// followed by the correct amount of number signs,
~ ANY // consume one character
)*
}
string = _{(raw_string | s_quoted_string | quoted_string)}
// Boolean and null
boolean = { "true" | "false" }
null = { "null" }
// Numbers
pos_int = @{ASCII_DIGIT ~ ("_" | ASCII_DIGIT)*}
hex_pos_int = @{"0x" ~ ASCII_HEX_DIGIT ~ ("_" | ASCII_HEX_DIGIT)*}
octo_pos_int = @{"0o" ~ ASCII_OCT_DIGIT ~ ("_" | ASCII_OCT_DIGIT)*}
bin_pos_int = @{"0b" ~ ASCII_BIN_DIGIT ~ ("_" | ASCII_BIN_DIGIT)*}
int = _{(hex_pos_int | octo_pos_int | bin_pos_int | pos_int)}
dot_float = @{
("0" | ASCII_NONZERO_DIGIT ~ ("_" | ASCII_DIGIT)*)
2 years ago
~ ("." ~ ("_" | ASCII_DIGIT)*)
}
sci_float = @{
("0" | ASCII_NONZERO_DIGIT ~ ("_" | ASCII_DIGIT)*)
2 years ago
~ ("." ~ ("_" | ASCII_DIGIT)*)?
~ (^"e" ~ ("+" | "-")? ~ ("_" | ASCII_DIGIT)+)
}
float = _{(sci_float | dot_float)}
number = _{(float | int)}
literal = _{ null | boolean | number | string}
// schema
table_schema = {"{" ~ table_cols ~ ("=>" ~ table_cols)? ~ "}"}
table_cols = {(table_col ~ ",")* ~ table_col?}
table_col = {ident ~ (":" ~ col_type)? ~ (("default" ~ expr) | ("=" ~ out_arg))?}
col_type = {(any_type | bool_type | int_type | float_type | string_type | bytes_type | uuid_type | validity_type | list_type | tuple_type) ~ "?"?}
col_type_with_term = {SOI ~ col_type ~ EOI}
any_type = {"Any"}
int_type = {"Int"}
float_type = {"Float"}
string_type = {"String"}
bytes_type = {"Bytes"}
uuid_type = {"Uuid"}
bool_type = {"Bool"}
validity_type = {"Validity"}
list_type = {"[" ~ col_type ~ (";" ~ expr)? ~ "]"}
tuple_type = {"(" ~ (col_type ~ ",")* ~ col_type? ~ ")"}
imperative_stmt = _{
break_stmt | continue_stmt | return_stmt | debug_stmt |
query_script_inner | ignore_error_script | if_chain | while_block | do_while_block | temp_swap | remove_stmt
}
imperative_condition = _{underscore_ident | query_script_inner}
if_chain = {"%if" ~ imperative_condition
~ "%then" ~ imperative_block
~ ("%else" ~ imperative_block)? ~ "%end" }
imperative_block = {imperative_stmt+}
break_stmt = {"%break" ~ ident?}
ignore_error_script = {"%ignore_error" ~ query_script_inner}
continue_stmt = {"%continue" ~ ident?}
return_stmt = {"%return" ~ (ident | underscore_ident | query_script_inner)?}
while_block = {("%mark" ~ ident)? ~ "%while" ~ imperative_condition ~ "%loop" ~ imperative_block ~ "%end"}
do_while_block = {("%mark" ~ ident)? ~ "%loop" ~ imperative_block ~ "%while" ~ imperative_condition ~ "%end"}
temp_swap = {"%swap" ~ underscore_ident ~ underscore_ident}
remove_stmt = {"%remove" ~ underscore_ident}
debug_stmt = {"%debug" ~ (ident | underscore_ident)}
/*
yield is no longer necessary!
*/