diff --git a/lexer/lexer.mbt b/lexer/lexer.mbt index 07da22a3..6753c55d 100644 --- a/lexer/lexer.mbt +++ b/lexer/lexer.mbt @@ -9,7 +9,7 @@ fn lex_tokens( preserve_comment~ : (Comment, Int, Int) -> Unit, ) -> Unit { fn metavar_enabled() -> Bool { - env.enable_metavar && !env.is_interpolation + env.enable_metavar } fn typed_metavar_payload( diff --git a/lexer/metavar_test.mbt b/lexer/metavar_test.mbt index 5afc0241..1d50348a 100644 --- a/lexer/metavar_test.mbt +++ b/lexer/metavar_test.mbt @@ -279,6 +279,22 @@ test "double-dollar metavariable prefix remains unsupported" { } } +///| +test "metavariable syntax remains enabled in interpolation sublexing" { + let result = tokens_from_string( + "$x", + comment=false, + is_interpolation=true, + enable_metavar=true, + ) + guard result.errors.is_empty() else { + fail("expected metavariable syntax in interpolation sublexing") + } + guard result.tokens[0].0 is LIDENT("$x") else { + fail("expected interpolation sublexer to preserve metavariable tokens") + } +} + ///| test "multiline interpolation keeps precedence over metavariable syntax" { let result = tokens_from_string("$|hello", comment=false, enable_metavar=true) diff --git a/lexer/moon.mod b/lexer/moon.mod index 5048c72b..4ae480ec 100644 --- a/lexer/moon.mod +++ b/lexer/moon.mod @@ -1,6 +1,6 @@ name = "moonbitlang/lexer" -version = "0.3.14" +version = "0.3.15" repository = "https://github.com/moonbitlang/parser" diff --git a/moon.mod b/moon.mod index 2ca8ea6b..c70d3d1f 100644 --- a/moon.mod +++ b/moon.mod @@ -1,11 +1,11 @@ name = "moonbitlang/parser" -version = "0.3.16" +version = "0.3.17" import { "moonbitlang/x@0.4.39", - "moonbitlang/lexer@0.3.14", - "moonbitlang/moon_config@0.3.13", + "moonbitlang/lexer@0.3.15", + "moonbitlang/moon_config@0.3.14", "moonbitlang/async@0.20.3", "moonbit-community/prettyprinter@0.4.10", } diff --git a/moon_config/moon.mod b/moon_config/moon.mod index 3b726638..415c446d 100644 --- a/moon_config/moon.mod +++ b/moon_config/moon.mod @@ -1,9 +1,9 @@ name = "moonbitlang/moon_config" -version = "0.3.13" +version = "0.3.14" import { - "moonbitlang/lexer@0.3.14", + "moonbitlang/lexer@0.3.15", } repository = "https://github.com/moonbitlang/parser" diff --git a/untyped_cst/api.mbt b/untyped_cst/api.mbt index 70af07e4..e444dcab 100644 --- a/untyped_cst/api.mbt +++ b/untyped_cst/api.mbt @@ -9,9 +9,10 @@ fn parse_with_state( source : String, diagnostics : Array[Report], docstrings : Array[List[(Location, Comment)]], + enable_metavar : Bool, parse_root : (ParserState) -> CstNode, ) -> ParseResult { - let state = new_state(tokens, source, diagnostics) + let state = new_state(tokens, source, diagnostics, enable_metavar) let root = parse_root(state) parse_result(root, state.reports, docstrings) } @@ -30,7 +31,14 @@ fn parse_source( comment=true, ) let diagnostics = reports_from_lex_errors(lex.errors) - parse_with_state(lex.tokens, source, diagnostics, lex.docstrings, parse_root) + parse_with_state( + lex.tokens, + source, + diagnostics, + lex.docstrings, + enable_metavar, + parse_root, + ) } ///| diff --git a/untyped_cst/api_test.mbt b/untyped_cst/api_test.mbt index 6d820b72..1933c9bf 100644 --- a/untyped_cst/api_test.mbt +++ b/untyped_cst/api_test.mbt @@ -229,6 +229,26 @@ test "parse entry points gate metavariable syntax" { ) } +///| +test "metavariable option propagates into interpolation expressions" { + for source in ["\"\\{$x}\"", "\"\\{\"\\{$x}\"}\""] { + @test.assert_eq( + @untyped_cst.parse_expression(source).diagnostics_view().is_empty(), + false, + ) + let expression = @untyped_cst.parse_expression(source, enable_metavar=true) + @test.assert_eq(expression.diagnostics_view().is_empty(), true) + @test.assert_eq( + api_has_string_value( + expression.root(), + fn(kind) { kind is Syntax_Identifier }, + "$x", + ), + true, + ) + } +} + ///| test "constant kinds and normalized payloads are parser semantics" { let cases : Array[(String, String, String)] = [ diff --git a/untyped_cst/parse.mbt b/untyped_cst/parse.mbt index c245bab8..8e0dcc8f 100644 --- a/untyped_cst/parse.mbt +++ b/untyped_cst/parse.mbt @@ -11887,12 +11887,18 @@ fn parse_interp_source_expr( interp_source.source, start_pos=interp_source.loc.start, is_interpolation=true, + enable_metavar=state.enable_metavar, comment=true, ) for report in reports_from_lex_errors(lex.errors) { state.reports.push(report) } - let inner_state = new_state(lex.tokens, state.source, state.reports) + let inner_state = new_state( + lex.tokens, + state.source, + state.reports, + state.enable_metavar, + ) parse_expr_until(inner_state, [TokenKind::TK_EOF]) } diff --git a/untyped_cst/state.mbt b/untyped_cst/state.mbt index 6b19f291..89a58274 100644 --- a/untyped_cst/state.mbt +++ b/untyped_cst/state.mbt @@ -3,6 +3,7 @@ priv struct ParserState { tokens : Triples mut pos : Int reports : Array[Report] + enable_metavar : Bool mut abort_current_decl : Bool mut abort_infix_chain : Bool mut report_next_top_level_start : Bool @@ -391,12 +392,14 @@ fn new_state( tokens : Triples, source : String, reports : Array[Report], + enable_metavar : Bool, ) -> ParserState { let mapper = default_location_mapper(source) ParserState::{ tokens, pos: 0, reports, + enable_metavar, abort_current_decl: false, abort_infix_chain: false, report_next_top_level_start: false,