feat: add 'reserved word' construct
Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
This commit is contained in:
parent
2a63077cac
commit
201b41cf11
31 changed files with 2367 additions and 1628 deletions
101
test/fixtures/test_grammars/reserved_words/corpus.txt
vendored
Normal file
101
test/fixtures/test_grammars/reserved_words/corpus.txt
vendored
Normal 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))))
|
||||
67
test/fixtures/test_grammars/reserved_words/grammar.js
vendored
Normal file
67
test/fixtures/test_grammars/reserved_words/grammar.js
vendored
Normal 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*/,
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue