From f2e254abc3b7d080fe97fab74554f2fb215eeef4 Mon Sep 17 00:00:00 2001 From: Philip Vejre Date: Fri, 5 Jul 2024 12:56:14 +0200 Subject: [PATCH] Fix missing flag from regex literal in corner case In the specific corner case where a regex contains a flag but is not followed by any symbols, the ast.RegExpLiteral.Literal value would drop (part of) that flag. This happens because the p.next() call during the parsing of the flag wouldn't actually advance the p.chrOffset, and thus endOffset would be erroneously adjusted. The fix is just to use the current p.chrOffset and then call p.next() afterwards. --- parser/expression.go | 2 +- parser/parser_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/parser/expression.go b/parser/expression.go index fe73fa27..2c8e2994 100644 --- a/parser/expression.go +++ b/parser/expression.go @@ -136,8 +136,8 @@ func (p *parser) parseRegExpLiteral() *ast.RegExpLiteral { flags := "" if p.token == token.IDENTIFIER { // gim flags = p.literal + endOffset = p.chrOffset p.next() - endOffset = p.chrOffset - 1 } var value string diff --git a/parser/parser_test.go b/parser/parser_test.go index 165a688b..303e01d9 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -975,6 +975,32 @@ func Test_parseNumberLiteral(t *testing.T) { }) } +func Test_praseRegExpLiteral(t *testing.T) { + tt(t, func() { + test := func(input, literal, pattern, flags string) { + parser := newParser("", input, 1, nil) + program, err := parser.parse() + is(err, nil) + + regex := program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.RegExpLiteral) + is(regex.Literal, literal) + is(regex.Pattern, pattern) + is(regex.Flags, flags) + } + + test("/abc/", "/abc/", "abc", "") + test("/abc/gim", "/abc/gim", "abc", "gim") + test("/abc/ ", "/abc/", "abc", "") + test("/abc/gim ", "/abc/gim", "abc", "gim") + test("/abc/;", "/abc/", "abc", "") + test("/abc/gim;", "/abc/gim", "abc", "gim") + test("/abc/\n", "/abc/", "abc", "") + test("/abc/gim\n", "/abc/gim", "abc", "gim") + test("/abc/;\n", "/abc/", "abc", "") + test("/abc/gim;\n", "/abc/gim", "abc", "gim") + }) +} + func TestPosition(t *testing.T) { tt(t, func() { parser := newParser("", "// Lorem ipsum", 1, nil)