Simplify grammar patterns for tree-sitter compatibility
- Use simple regex patterns for comments, raw blocks, embedded languages - Add support for unquoted import paths - Use string literals for keyword highlighting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
7c37d0b3bc
commit
769d8bfc51
261
grammar.js
261
grammar.js
|
|
@ -40,9 +40,11 @@ module.exports = grammar({
|
|||
),
|
||||
),
|
||||
|
||||
// Template imports
|
||||
// Template imports - supports both quoted "path" and unquoted /path
|
||||
import_statement: ($) =>
|
||||
seq("@import", $.string_literal, "as", $.identifier),
|
||||
seq("@import", choice($.string_literal, $.import_path), "as", $.identifier),
|
||||
|
||||
import_path: ($) => /\/[^\s]+/,
|
||||
|
||||
// Struct definition
|
||||
struct_definition: ($) =>
|
||||
|
|
@ -100,7 +102,7 @@ module.exports = grammar({
|
|||
|
||||
// Function definition
|
||||
function_definition: ($) =>
|
||||
seq("@func", $.identifier, $.parameter_list, $.content_block),
|
||||
seq("@fn", $.identifier, $.parameter_list, $.content_block),
|
||||
|
||||
parameter_list: ($) =>
|
||||
seq(
|
||||
|
|
@ -128,6 +130,7 @@ module.exports = grammar({
|
|||
$.template_control_flow,
|
||||
$.template_expression,
|
||||
$.comment,
|
||||
$.raw_block,
|
||||
$.embedded_language,
|
||||
$.escape_at,
|
||||
$.text_content,
|
||||
|
|
@ -223,7 +226,7 @@ module.exports = grammar({
|
|||
),
|
||||
|
||||
expression_path: ($) =>
|
||||
prec.left(seq(
|
||||
seq(
|
||||
$.identifier,
|
||||
repeat(
|
||||
choice(
|
||||
|
|
@ -232,7 +235,7 @@ module.exports = grammar({
|
|||
seq("(", optional($.argument_list), ")"),
|
||||
),
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
||||
// Control flow
|
||||
template_control_flow: ($) =>
|
||||
|
|
@ -564,259 +567,25 @@ module.exports = grammar({
|
|||
// Comments
|
||||
comment: ($) => choice($.template_comment, $.html_comment),
|
||||
|
||||
// Template comments support variable asterisk counts: @* *@, @** **@, @*** ***@
|
||||
// Template comments: @* ... *@ (simple form only for syntax highlighting)
|
||||
template_comment: ($) =>
|
||||
choice($.template_comment_1, $.template_comment_2, $.template_comment_3),
|
||||
|
||||
// Single asterisk: @* ... *@
|
||||
template_comment_1: ($) =>
|
||||
seq("@*", optional($.comment_content_1), "*@"),
|
||||
comment_content_1: ($) => /([^*]|\*[^@])*/,
|
||||
|
||||
// Double asterisk: @** ... **@
|
||||
template_comment_2: ($) =>
|
||||
seq("@**", optional($.comment_content_2), "**@"),
|
||||
comment_content_2: ($) => /([^*]|\*[^*]|\*\*[^@])*/,
|
||||
|
||||
// Triple asterisk: @*** ... ***@
|
||||
template_comment_3: ($) =>
|
||||
seq("@***", optional($.comment_content_3), "***@"),
|
||||
comment_content_3: ($) => /([^*]|\*[^*]|\*\*[^*]|\*\*\*[^@])*/,
|
||||
|
||||
seq("@", /\*+/, optional(/([^*]|\*+[^@])*/), /\*+/, "@"),
|
||||
// HTML comment: <!-- ... -->
|
||||
html_comment: ($) => seq("<!--", optional($.html_comment_content), "-->"),
|
||||
|
||||
html_comment_content: ($) => /([^-]|-[^-]|--[^>])*/,
|
||||
|
||||
// Raw blocks: @#...#@ (simple form only for syntax highlighting)
|
||||
raw_block: ($) =>
|
||||
seq("@", /#+/, optional(/([^#]|#+[^@])*/), /#+/, "@"),
|
||||
|
||||
// Embedded language blocks: @```lang ... ```@
|
||||
embedded_language: ($) =>
|
||||
choice(
|
||||
// JSON/Alpine blocks with structured parsing
|
||||
seq("@```", choice("json", "alpine"), optional($.json_content), "```@"),
|
||||
// JS blocks with structured parsing
|
||||
seq("@```", choice("js", "javascript"), optional($.js_content), "```@"),
|
||||
// CSS blocks with structured parsing
|
||||
seq("@```", choice("css", "style"), optional($.css_content), "```@"),
|
||||
// HTML blocks (less common, use simple content)
|
||||
seq("@```", "html", optional($.embedded_content_simple), "```@"),
|
||||
),
|
||||
|
||||
// Simple embedded content fallback
|
||||
embedded_content_simple: ($) => /([^`]|`[^`]|``[^`])*/,
|
||||
seq("@", /`+/, $.language_name, optional(/([^`]|`+[^@])*/), /`+/, "@"),
|
||||
|
||||
language_name: ($) =>
|
||||
choice("html", "css", "js", "javascript", "json", "alpine", "style"),
|
||||
|
||||
// JSON content with template support
|
||||
json_content: ($) =>
|
||||
choice(
|
||||
$.json_object,
|
||||
$.json_array,
|
||||
),
|
||||
|
||||
json_object: ($) =>
|
||||
seq(
|
||||
"{",
|
||||
optional($.json_object_content),
|
||||
"}",
|
||||
),
|
||||
|
||||
json_object_content: ($) =>
|
||||
seq(
|
||||
$.json_member_or_control,
|
||||
repeat(seq(optional(","), $.json_member_or_control)),
|
||||
optional(","),
|
||||
),
|
||||
|
||||
json_member_or_control: ($) =>
|
||||
choice(
|
||||
$.json_member,
|
||||
$.json_control_flow,
|
||||
),
|
||||
|
||||
json_member: ($) =>
|
||||
seq(
|
||||
choice($.json_key, $.template_expression),
|
||||
":",
|
||||
$.json_value,
|
||||
),
|
||||
|
||||
json_key: ($) =>
|
||||
choice(
|
||||
$.string_literal,
|
||||
$.identifier, // Allow unquoted keys for JS object shorthand
|
||||
),
|
||||
|
||||
json_value: ($) =>
|
||||
choice(
|
||||
$.json_object,
|
||||
$.json_array,
|
||||
$.string_literal,
|
||||
$.number_literal,
|
||||
$.boolean_literal,
|
||||
"null",
|
||||
$.template_expression,
|
||||
$.json_method, // For Alpine.js method shorthand
|
||||
),
|
||||
|
||||
json_array: ($) =>
|
||||
seq(
|
||||
"[",
|
||||
optional($.json_array_content),
|
||||
"]",
|
||||
),
|
||||
|
||||
json_array_content: ($) =>
|
||||
seq(
|
||||
$.json_array_element,
|
||||
repeat(seq(optional(","), $.json_array_element)),
|
||||
optional(","),
|
||||
),
|
||||
|
||||
json_array_element: ($) =>
|
||||
choice(
|
||||
$.json_value,
|
||||
$.json_control_flow,
|
||||
),
|
||||
|
||||
// Control flow in JSON context
|
||||
json_control_flow: ($) =>
|
||||
choice(
|
||||
$.json_if_statement,
|
||||
$.json_for_loop,
|
||||
),
|
||||
|
||||
json_if_statement: ($) =>
|
||||
seq(
|
||||
"@if",
|
||||
$.expression,
|
||||
"{",
|
||||
optional($.json_if_body),
|
||||
"}",
|
||||
optional(seq("else", "{", optional($.json_if_body), "}")),
|
||||
),
|
||||
|
||||
// Body of @if in JSON can contain members or array elements
|
||||
json_if_body: ($) =>
|
||||
seq(
|
||||
$.json_if_element,
|
||||
repeat(seq(optional(","), $.json_if_element)),
|
||||
optional(","),
|
||||
),
|
||||
|
||||
json_if_element: ($) =>
|
||||
choice(
|
||||
$.json_member,
|
||||
$.json_value,
|
||||
$.json_control_flow,
|
||||
),
|
||||
|
||||
json_for_loop: ($) =>
|
||||
seq(
|
||||
"@for",
|
||||
$.simple_pattern,
|
||||
"in",
|
||||
$.expression,
|
||||
"{",
|
||||
optional($.json_if_body),
|
||||
"}",
|
||||
),
|
||||
|
||||
// Alpine.js method shorthand: toggle() { this.open = !this.open; }
|
||||
json_method: ($) =>
|
||||
seq(
|
||||
$.identifier,
|
||||
"(",
|
||||
optional($.json_method_params),
|
||||
")",
|
||||
"{",
|
||||
optional($.js_content),
|
||||
"}",
|
||||
),
|
||||
|
||||
json_method_params: ($) =>
|
||||
seq($.identifier, repeat(seq(",", $.identifier))),
|
||||
|
||||
// JavaScript content with template support
|
||||
js_content: ($) => repeat1($.js_element),
|
||||
|
||||
js_element: ($) =>
|
||||
choice(
|
||||
$.js_control_flow,
|
||||
$.template_expression,
|
||||
$.js_code,
|
||||
),
|
||||
|
||||
js_control_flow: ($) =>
|
||||
choice(
|
||||
$.js_if_statement,
|
||||
$.js_for_loop,
|
||||
),
|
||||
|
||||
js_if_statement: ($) =>
|
||||
seq(
|
||||
"@if",
|
||||
$.expression,
|
||||
"{",
|
||||
optional($.js_content),
|
||||
"}",
|
||||
optional(seq("else", "{", optional($.js_content), "}")),
|
||||
),
|
||||
|
||||
js_for_loop: ($) =>
|
||||
seq(
|
||||
"@for",
|
||||
$.simple_pattern,
|
||||
"in",
|
||||
$.expression,
|
||||
"{",
|
||||
optional($.js_content),
|
||||
"}",
|
||||
),
|
||||
|
||||
// Raw JS code (anything that's not @expression or @control_flow)
|
||||
js_code: ($) => token(prec(-1, /[^@`]+/)),
|
||||
|
||||
// CSS content with template support
|
||||
css_content: ($) => repeat1($.css_element),
|
||||
|
||||
css_element: ($) =>
|
||||
choice(
|
||||
$.css_control_flow,
|
||||
$.template_expression,
|
||||
$.css_code,
|
||||
),
|
||||
|
||||
css_control_flow: ($) =>
|
||||
choice(
|
||||
$.css_if_statement,
|
||||
$.css_for_loop,
|
||||
),
|
||||
|
||||
css_if_statement: ($) =>
|
||||
seq(
|
||||
"@if",
|
||||
$.expression,
|
||||
"{",
|
||||
optional($.css_content),
|
||||
"}",
|
||||
optional(seq("else", "{", optional($.css_content), "}")),
|
||||
),
|
||||
|
||||
css_for_loop: ($) =>
|
||||
seq(
|
||||
"@for",
|
||||
$.simple_pattern,
|
||||
"in",
|
||||
$.expression,
|
||||
"{",
|
||||
optional($.css_content),
|
||||
"}",
|
||||
),
|
||||
|
||||
// Raw CSS code
|
||||
css_code: ($) => token(prec(-1, /[^@`]+/)),
|
||||
|
||||
// Escape sequence for literal @
|
||||
escape_at: ($) => "@@",
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
; Waltzing Template Highlights
|
||||
|
||||
; Comments (all template comment variants)
|
||||
(template_comment) @comment
|
||||
(template_comment_1) @comment
|
||||
(template_comment_2) @comment
|
||||
(template_comment_3) @comment
|
||||
; Comments
|
||||
(html_comment) @comment
|
||||
|
||||
; Raw blocks (verbatim content)
|
||||
(raw_block) @string.special
|
||||
|
||||
; Template comments
|
||||
(template_comment) @comment
|
||||
|
||||
; Keywords
|
||||
"@use" @keyword
|
||||
"@import" @keyword
|
||||
"@struct" @keyword
|
||||
"@enum" @keyword
|
||||
"@func" @keyword
|
||||
"@fn" @keyword
|
||||
"@let" @keyword
|
||||
"@if" @keyword
|
||||
"@for" @keyword
|
||||
|
|
@ -97,14 +99,8 @@
|
|||
(escape_sequence) @escape
|
||||
(escape_at) @escape
|
||||
|
||||
; Embedded language names
|
||||
"json" @label
|
||||
"alpine" @label
|
||||
"js" @label
|
||||
"javascript" @label
|
||||
"css" @label
|
||||
"style" @label
|
||||
"html" @label
|
||||
; Embedded
|
||||
(language_name) @label
|
||||
|
||||
; Variables (fallback)
|
||||
(identifier) @variable
|
||||
|
|
|
|||
Loading…
Reference in New Issue