From 769d8bfc514ef5093d611a97fa138eeef70a5866 Mon Sep 17 00:00:00 2001 From: Michael Netshipise Date: Mon, 19 Jan 2026 20:32:14 +0200 Subject: [PATCH] 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 --- grammar.js | 261 +++-------------------------------------- queries/highlights.scm | 24 ++-- 2 files changed, 25 insertions(+), 260 deletions(-) diff --git a/grammar.js b/grammar.js index ef0e4c3..06900c3 100644 --- a/grammar.js +++ b/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(""), 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: ($) => "@@", diff --git a/queries/highlights.scm b/queries/highlights.scm index c409381..5ea7e47 100644 --- a/queries/highlights.scm +++ b/queries/highlights.scm @@ -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