Skip to content

Commit

Permalink
Add basic if-statement
Browse files Browse the repository at this point in the history
  • Loading branch information
Ce11an committed Feb 11, 2025
1 parent 9b34175 commit 0d5dd10
Show file tree
Hide file tree
Showing 12 changed files with 70,387 additions and 64,315 deletions.
77 changes: 77 additions & 0 deletions examples/if_else.surql
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
-- The smallest possible IF THEN statement simply does something when a condition is true, and nothing otherwise.
IF 9 = 9 { RETURN 'Nine is indeed nine' };

-- As the last line of a scope is its return value, the RETURN keyword can also be placed before the entire IF THEN
-- statement. This is particularly convenient in long IF ELSE chains to avoid using the RETURN keyword at the end
-- of every check for a condition.

LET $num = 100;

RETURN IF $num < 0 {
"Negative"
} ELSE IF $num = 0 {
"Zero"
} ELSE IF $num = 13 {
"Thirteen"
} ELSE {
"Positive uninteresting number"
};

-- The THROW keyword inside {} braces can be used to break out of an IF LET statement early.
LET $badly_formatted_datetime = "2024-04TT08:08:08Z";

IF !type::is::datetime($badly_formatted_datetime) {
THROW "Whoops, that isn't a real datetime"
};

-- ELSE IF branches and a final ELSE can be added into an IF ELSE statement:
RETURN
IF $access = "admin" { (SELECT * FROM account) }
ELSE IF $access = "user" { (SELECT * FROM $auth.account) }
ELSE { THROW "Access method hasn't been defined!" };

-- The output of an IF ELSE statement can be assigned to a parameter:
LET $num = 9;
LET $odd_even =
IF $num % 2 = 0 { "even" }
ELSE { "odd" };

-- If-else statements can also be used as subqueries within other statements.
UPDATE person SET railcard =
IF age <= 10 { 'junior' }
ELSE IF age <= 21 { 'student' }
ELSE IF age >= 65 { 'senior' }
ELSE { NULL };

-- More nested
IF $access = 'admin'
{
CREATE admin_user_event SET
time = time::now(),
info = "Admin user activity registered";
SELECT * FROM admin_data WHERE access_level = 'full';
}
ELSE IF $access = 'user'
{
IF $auth.role = 'premium'
{
CREATE premium_user_event SET
time = time::now(),
info = "Premium user activity registered";

IF $auth.subscription_status = 'active'
{ SELECT * FROM premium_user_data WHERE active = 1 }
ELSE IF $auth.subscription_status = 'trial'
{ SELECT * FROM trial_user_data }
ELSE
{ SELECT * FROM basic_user_data }
}
ELSE IF $auth.role = 'standard'
{ SELECT * FROM standard_user_data WHERE region = 'US' }
ELSE IF $auth.role = 'standard' AND $auth.subscription_status = 'active'
{ SELECT * FROM standard_user_data WHERE region = 'EU' }
ELSE
{ SELECT * FROM unauthorized_user_data }
}
ELSE
{ SELECT * FROM unknown_access_data }
52 changes: 41 additions & 11 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ module.exports = grammar({
semi_colon: _ => token(";"),
keyword_info: _ => token("INFO"),
keyword_if: _ => token("IF"),
keyword_throw: _ => token("THROW"),
keyword_exists: _ => token("EXISTS"),
keyword_tokenizers: _ => token("TOKENIZERS"),
keyword_overwrite: _ => token("OVERWRITE"),
keyword_on: _ => token("ON"),
keyword_let: _ => token("LET"),
keyword_return: _ => token("RETURN"),
keyword_else: _ => token("ELSE"),
keyword_end: _ => token("END"),
keyword_select: _ => token("SELECT"),
keyword_from: _ => token("FROM"),
keyword_only: _ => token("ONLY"),
Expand All @@ -40,7 +40,6 @@ module.exports = grammar({
keyword_parallel: _ => token("PARALLEL"),
keyword_timeout: _ => token("TIMEOUT"),
keyword_fetch: _ => token("FETCH"),
keyword_start_at: _ => token("START AT"),
keyword_limit: _ => token("LIMIT"),
keyword_by: _ => token("BY"),
keyword_rand: _ => token("RAND"),
Expand All @@ -56,7 +55,6 @@ module.exports = grammar({
keyword_split: _ => token("SPLIT"),
keyword_at: _ => token("AT"),
keyword_group: _ => token("GROUP"),
keyword_all: _ => token("ALL"),
keyword_true: _ => token("TRUE"),
keyword_false: _ => token("FALSE"),
keyword_begin: _ => token("BEGIN"),
Expand Down Expand Up @@ -178,10 +176,6 @@ module.exports = grammar({
keyword_count: _ => token("COUNT"),
keyword_set: _ => token("SET"),
keyword_unset: _ => token("UNSET"),
keyword_return: _ => token("RETURN"),
keyword_dimension: _ => token("DIMENSION"),
keyword_mtree: _ => token("MTREE"),
keyword_dist: _ => token("DIST"),

// Expressions
expressions: $ =>
Expand Down Expand Up @@ -222,9 +216,39 @@ module.exports = grammar({
$.use_statement,
$.info_statement,
$.let_statement,
$.if_statement,
$.throw_statement,
$.return_statement,
),

let_statement: $ => seq($.keyword_let, $.variable_name, "=", $.value),
return_statement: $ => $.return_clause,

throw_statement: $ => seq(
$.keyword_throw,
$.value
),

if_statement: $ => seq(
$.keyword_if,
$.value,
$.block,
repeat($.else_if_clause),
optional($.else_clause),
),

else_if_clause: $ => seq(
$.keyword_else,
$.keyword_if,
$.value,
$.block
),

else_clause: $ => seq(
$.keyword_else,
$.block
),

let_statement: $ => seq($.keyword_let, $.variable_name, "=", choice($.value, $.if_statement)),

info_statement: $ => seq($.keyword_info, $.keyword_for, $.info_target),

Expand Down Expand Up @@ -672,7 +696,6 @@ module.exports = grammar({
),

limit_clause: $ => seq($.keyword_limit, $.number),
start_clause: $ => seq($.keyword_start_at, $.number),
fetch_clause: $ => seq($.keyword_fetch, commaSeparated($.identifier)),
timeout_clause: $ => seq($.keyword_timeout, $.duration),
parallel_clause: $ => $.keyword_parallel,
Expand Down Expand Up @@ -876,6 +899,7 @@ module.exports = grammar({
$.keyword_after,
$.keyword_diff,
commaSeparated($.value),
$.if_statement
),
),

Expand All @@ -896,13 +920,13 @@ module.exports = grammar({

// Value-related rules
value: $ =>
choice($.base_value, $.binary_expression, $.path, $.function_call),
choice($.base_value, $.binary_expression, $.path, $.function_call, $.negated_expression),

function_call: $ =>
choice(
seq($.keyword_count, $.argument_list_count),
seq(
choice($.function_name, $.custom_function_name, $.keyword_rand),
choice($.function_name, $.custom_function_name, $.keyword_rand, seq($.identifier, repeat1(seq('::', $.identifier)))),
optional($.version),
$.argument_list,
),
Expand All @@ -929,6 +953,11 @@ module.exports = grammar({

binary_expression: $ => prec.left(seq($.value, $.operator, $.value)),

negated_expression: $ => seq(
'!',
$.function_call,
),

path: $ =>
choice(
seq($.base_value, repeat1($.path_element)),
Expand Down Expand Up @@ -1035,6 +1064,7 @@ module.exports = grammar({
"=",
">",
"<",
"%",
$.keyword_and,
$.keyword_or,
$.keyword_is,
Expand Down
10 changes: 0 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,6 @@
"optional": true
}
},
"tree-sitter": [
{
"file-types": [
"surql"
],
"highlights": [
"queries/highlights.scm"
]
}
],
"devDependencies": {
"prettier": "3.1.0",
"tree-sitter-cli": "^0.22.5",
Expand Down
8 changes: 2 additions & 6 deletions queries/highlights.scm
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
(keyword_from)
(keyword_let)
(keyword_else)
(keyword_end)
(keyword_only)
(keyword_value)
(keyword_as)
Expand All @@ -14,7 +13,6 @@
(keyword_parallel)
(keyword_timeout)
(keyword_fetch)
(keyword_start_at)
(keyword_limit)
(keyword_by)
(keyword_rand)
Expand All @@ -30,7 +28,6 @@
(keyword_split)
(keyword_at)
(keyword_group)
(keyword_all)
(keyword_begin)
(keyword_cancel)
(keyword_commit)
Expand Down Expand Up @@ -154,10 +151,8 @@
(keyword_set)
(keyword_unset)
(keyword_return)
(keyword_dimension)
(keyword_mtree)
(keyword_dist)
(keyword_overwrite)
(keyword_throw)
] @keyword

; Operators
Expand Down Expand Up @@ -222,3 +217,4 @@
(graph_path) @operator

; Errors
(ERROR) @error
Loading

0 comments on commit 0d5dd10

Please sign in to comment.