From 8be139ab271e9dc23922efc968d5d9da196ec186 Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Thu, 29 Jan 2026 15:38:10 +0100 Subject: [PATCH] Implemented regex validation for variables --- internal/parser/lexer.go | 2 +- internal/parser/parser.go | 6 +++++ test/regex_variable_test.go | 53 +++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 test/regex_variable_test.go diff --git a/internal/parser/lexer.go b/internal/parser/lexer.go index 0ffe17d..789dd15 100644 --- a/internal/parser/lexer.go +++ b/internal/parser/lexer.go @@ -137,7 +137,7 @@ func (l *Lexer) NextToken() Token { return l.emit(TokenLBracket) case ']': return l.emit(TokenRBracket) - case '&', '?', '!', '<', '>', '*', '(', ')': + case '&', '?', '!', '<', '>', '*', '(', ')', '~', '%', '^': return l.emit(TokenSymbol) case '"': return l.lexString() diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 2d18140..fc44980 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -296,6 +296,12 @@ func (p *Parser) parseVariableDefinition(startTok Token) (Definition, bool) { break } if t.Type == TokenEqual { + if p.peekN(1).Type == TokenSymbol && p.peekN(1).Value == "~" { + p.next() + p.next() + typeTokens = append(typeTokens, Token{Type: TokenSymbol, Value: "=~", Position: t.Position}) + continue + } break } typeTokens = append(typeTokens, p.next()) diff --git a/test/regex_variable_test.go b/test/regex_variable_test.go new file mode 100644 index 0000000..3e88d09 --- /dev/null +++ b/test/regex_variable_test.go @@ -0,0 +1,53 @@ +package integration + +import ( + "strings" + "testing" + + "github.com/marte-community/marte-dev-tools/internal/index" + "github.com/marte-community/marte-dev-tools/internal/parser" + "github.com/marte-community/marte-dev-tools/internal/validator" +) + +func TestRegexVariable(t *testing.T) { + content := ` +#var IP: string & =~"^[0-9.]+$" = "127.0.0.1" +#var BadIP: string & =~"^[0-9.]+$" = "abc" + ++Obj = { + IP = $IP +} +` + // Test Validator + pt := index.NewProjectTree() + p := parser.NewParser(content) + cfg, err := p.Parse() + if err != nil { + t.Fatalf("Parse failed: %v", err) + } + pt.AddFile("regex.marte", cfg) + + v := validator.NewValidator(pt, ".") + v.CheckVariables() + + foundError := false + for _, d := range v.Diagnostics { + if strings.Contains(d.Message, "Variable 'BadIP' value mismatch") { + foundError = true + } + } + + if !foundError { + t.Error("Expected error for BadIP") + for _, d := range v.Diagnostics { + t.Logf("Diag: %s", d.Message) + } + } + + // Test valid variable + for _, d := range v.Diagnostics { + if strings.Contains(d.Message, "Variable 'IP' value mismatch") { + t.Error("Unexpected error for IP") + } + } +}