feat: add 'reserved word' construct

Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
This commit is contained in:
Max Brunsfeld 2024-12-23 00:06:32 -08:00 committed by GitHub
parent 2a63077cac
commit 201b41cf11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 2367 additions and 1628 deletions

View file

@ -0,0 +1,101 @@
==============
Valid Code
==============
if (a) {
var b = {
c: d,
e: f,
};
while (g) {
h();
}
}
---
(program
(if_statement
(parenthesized_expression (identifier))
(block
(var_declaration
(identifier)
(object
(pair (identifier) (identifier))
(pair (identifier) (identifier))))
(while_statement
(parenthesized_expression (identifier))
(block (expression_statement (call_expression (identifier))))))))
================================================
Error detected at globally-reserved word
================================================
var a =
if (something) {
c();
}
---
(program
(ERROR (identifier))
(if_statement
(parenthesized_expression (identifier))
(block
(expression_statement (call_expression (identifier))))))
================================================
Object keys that are reserved in other contexts
================================================
var x = {
if: a,
while: b,
};
---
(program
(var_declaration
(identifier)
(object
(pair (identifier) (identifier))
(pair (identifier) (identifier)))))
================================================
Error detected at context-specific reserved word
================================================
var x = {
var y = z;
---
(program
(ERROR (identifier))
; Important - var declaration is still recognized,
; because in this example grammar, `var` is a keyword
; even within object literals.
(var_declaration
(identifier)
(identifier)))
=============================================
Other tokens that overlap with keyword tokens
=============================================
var a = /reserved-words-should-not-affect-this/;
var d = /if/;
---
(program
(var_declaration
(identifier)
(regex (regex_pattern)))
(var_declaration
(identifier)
(regex (regex_pattern))))

View file

@ -0,0 +1,67 @@
const RESERVED_NAMES = ["if", "while", "var"];
const RESERVED_PROPERTY_NAMES = ["var"];
module.exports = grammar({
name: "reserved_words",
reserved: {
global: $ => RESERVED_NAMES,
property: $ => RESERVED_PROPERTY_NAMES,
},
word: $ => $.identifier,
rules: {
program: $ => repeat($._statement),
block: $ => seq("{", repeat($._statement), "}"),
_statement: $ => choice(
$.var_declaration,
$.if_statement,
$.while_statement,
$.expression_statement,
),
var_declaration: $ => seq("var", $.identifier, "=", $._expression, ";"),
if_statement: $ => seq("if", $.parenthesized_expression, $.block),
while_statement: $ => seq("while", $.parenthesized_expression, $.block),
expression_statement: $ => seq($._expression, ";"),
_expression: $ => choice(
$.identifier,
$.parenthesized_expression,
$.call_expression,
$.member_expression,
$.object,
$.regex,
),
parenthesized_expression: $ => seq("(", $._expression, ")"),
member_expression: $ => seq($._expression, ".", $.identifier),
call_expression: $ => seq($._expression, "(", repeat(seq($._expression, ",")), ")"),
object: $ => seq("{", repeat(seq(choice($.pair, $.getter), ",")), "}"),
regex: $ => seq('/', $.regex_pattern, '/'),
regex_pattern: $ => token(prec(-1, /[^/\n]+/)),
pair: $ => seq(reserved('property', $.identifier), ":", $._expression),
getter: $ => seq(
"get",
reserved('property', $.identifier),
"(",
")",
$.block,
),
identifier: $ => /[a-z_]\w*/,
},
});