diff --git a/compiler.go b/compiler.go index 341d4ed..f53b73c 100644 --- a/compiler.go +++ b/compiler.go @@ -5,6 +5,7 @@ import ( "fmt" "html/template" "reflect" + "regexp" "github.com/gobuffalo/plush/ast" @@ -379,6 +380,12 @@ func (c *compiler) stringsOperator(l string, r interface{}, op string) (interfac return l <= rr, nil case "==": return l == rr, nil + case "~=": + x, err := regexp.Compile(rr) + if err != nil { + return nil, errors.WithStack(errors.Errorf("couldn't compile regex %s", rr)) + } + return x.MatchString(l), nil } return nil, errors.WithStack(errors.Errorf("unknown operator for string %s", op)) } diff --git a/if_test.go b/if_test.go index f1cf4fb..2e1c3cb 100644 --- a/if_test.go +++ b/if_test.go @@ -109,3 +109,11 @@ func Test_Render_If_Else_True(t *testing.T) { r.NoError(err) r.Equal("

hi

", s) } + +func Test_Render_If_Matches(t *testing.T) { + r := require.New(t) + input := `

<%= if ("foo" ~= "bar") { return "hi"} else { return "bye"} %>

` + s, err := Render(input, NewContext()) + r.NoError(err) + r.Equal("

bye

", s) +} diff --git a/lexer/lexer.go b/lexer/lexer.go index b8d416e..f427dc4 100644 --- a/lexer/lexer.go +++ b/lexer/lexer.go @@ -137,6 +137,13 @@ func (l *Lexer) nextInsideToken() token.Token { break } tok = newToken(token.LT, l.ch) + case '~': + if l.peekChar() == '=' { + l.readChar() + tok = token.Token{Type: token.MATCHES, Literal: "~="} + break + } + tok = newToken(token.MATCHES, l.ch) case '>': if l.peekChar() == '=' { l.readChar() diff --git a/parser/parser.go b/parser/parser.go index ca631d2..ee433c8 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -57,6 +57,7 @@ func newParser(l *lexer.Lexer) *parser { p.registerInfix(token.ASTERISK, p.parseInfixExpression) p.registerInfix(token.EQ, p.parseInfixExpression) p.registerInfix(token.NOT_EQ, p.parseInfixExpression) + p.registerInfix(token.MATCHES, p.parseInfixExpression) p.registerInfix(token.LT, p.parseInfixExpression) p.registerInfix(token.GT, p.parseInfixExpression) p.registerInfix(token.LTEQ, p.parseInfixExpression) diff --git a/parser/parser_test.go b/parser/parser_test.go index ac96db0..271396b 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -294,6 +294,10 @@ func Test_OperatorPrecedence(t *testing.T) { "add(a * b[2], b[1], 2 * [1, 2][1])", "add((a * (b[2])), (b[1]), (2 * ([1, 2][1])))", }, + { + "foo ~= bar", + "(foo ~= bar)", + }, } for _, tt := range tests { diff --git a/parser/precedences.go b/parser/precedences.go index c82bacb..fae387a 100644 --- a/parser/precedences.go +++ b/parser/precedences.go @@ -17,6 +17,7 @@ const ( var precedences = map[token.Type]int{ token.EQ: EQUALS, token.NOT_EQ: EQUALS, + token.MATCHES: EQUALS, token.LT: LESSGREATER, token.LTEQ: LESSGREATER, token.GT: LESSGREATER, diff --git a/token/const.go b/token/const.go index 9170e95..d3a6444 100644 --- a/token/const.go +++ b/token/const.go @@ -26,10 +26,11 @@ const ( GT = ">" GTEQ = ">=" - EQ = "==" - NOT_EQ = "!=" - AND = "&&" - OR = "||" + EQ = "==" + NOT_EQ = "!=" + AND = "&&" + OR = "||" + MATCHES = "~=" // Delimiters