diff --git a/do_tag_test.go b/do_tag_test.go index a317916..d650160 100644 --- a/do_tag_test.go +++ b/do_tag_test.go @@ -6,13 +6,13 @@ import ( func TestDoTag(t *testing.T) { engine := New() - + // Add a custom function for testing engine.AddFunction("double", func(args ...interface{}) (interface{}, error) { if len(args) == 0 { return 0, nil } - + // Type conversion var num float64 switch v := args[0].(type) { @@ -27,10 +27,10 @@ func TestDoTag(t *testing.T) { // Return 0 for unsupported types return 0, nil } - + return num * 2, nil }) - + // Disable debug output SetDebugLevel(DebugOff) @@ -140,4 +140,4 @@ func TestDoTagErrors(t *testing.T) { } }) } -} \ No newline at end of file +} diff --git a/html_preserving_tokenizer.go b/html_preserving_tokenizer.go index 7963d85..a76ea0d 100644 --- a/html_preserving_tokenizer.go +++ b/html_preserving_tokenizer.go @@ -254,20 +254,20 @@ func (p *Parser) htmlPreservingTokenize() ([]Token, error) { // Special handling for do tag with assignments and expressions if len(parts) > 1 { doExpr := strings.TrimSpace(parts[1]) - + // Check if it's an assignment (contains =) assignPos := strings.Index(doExpr, "=") if assignPos > 0 && !strings.Contains(doExpr[:assignPos], "==") { // It's an assignment varName := strings.TrimSpace(doExpr[:assignPos]) valueExpr := strings.TrimSpace(doExpr[assignPos+1:]) - + // Add the variable name tokens = append(tokens, createToken(TOKEN_NAME, varName, line)) - + // Add the equals sign tokens = append(tokens, createToken(TOKEN_OPERATOR, "=", line)) - + // Tokenize the expression on the right side p.tokenizeExpression(valueExpr, &tokens, line) } else { diff --git a/node.go b/node.go index 318712d..5ff37b8 100644 --- a/node.go +++ b/node.go @@ -287,61 +287,6 @@ func (n *ForNode) Render(w io.Writer, ctx *RenderContext) error { } } - // Special handling for FunctionNode with name "range" directly in for loop - if funcNode, ok := n.sequence.(*FunctionNode); ok && funcNode.name == "range" { - // Add debug output to see what's happening - fmt.Printf("Found range function in for loop with %d args\n", len(funcNode.args)) - - // Get the engine's function registry to call range function directly - // This handles the case of using range() directly in for loop - if ctx.engine != nil && ctx.engine.environment != nil { - fmt.Println("Engine and environment exist") - - for i, ext := range ctx.engine.environment.extensions { - fmt.Printf("Checking extension %d: %s\n", i, ext.GetName()) - if functions := ext.GetFunctions(); functions != nil { - fmt.Printf("Extension has %d functions\n", len(functions)) - for name := range functions { - fmt.Printf(" - Function: %s\n", name) - } - - if rangeFunc, exists := functions["range"]; exists { - fmt.Println("Found range function!") - // Evaluate all arguments - var args []interface{} - for i, argNode := range funcNode.args { - fmt.Printf("Evaluating arg %d\n", i) - arg, err := ctx.EvaluateExpression(argNode) - if err != nil { - return err - } - fmt.Printf("Arg %d = %v (type: %T)\n", i, arg, arg) - args = append(args, arg) - } - - // Call the range function directly - fmt.Printf("Calling range function with %d args\n", len(args)) - result, err := rangeFunc(args...) - if err != nil { - fmt.Printf("Error from range function: %v\n", err) - return err - } - - fmt.Printf("Range result: %v (type: %T)\n", result, result) - - // Use the result as our sequence - seq := result - // Continue with normal for loop processing - return n.renderForLoop(w, ctx, seq) - } - } - } - fmt.Println("Couldn't find range function in extensions") - } else { - fmt.Println("Engine or environment is nil") - } - } - // Special handling for FilterNode to improve rendering in for loops if filterNode, ok := n.sequence.(*FilterNode); ok { if IsDebugEnabled() { diff --git a/parser.go b/parser.go index 26568fb..ab5ecd3 100644 --- a/parser.go +++ b/parser.go @@ -1977,36 +1977,36 @@ func (p *Parser) parseDo(parser *Parser) (Node, error) { // Check for special case: assignment expressions // These need to be handled specially since they're not normal expressions - if parser.tokenIndex < len(parser.tokens) && - parser.tokens[parser.tokenIndex].Type == TOKEN_NAME { - + if parser.tokenIndex < len(parser.tokens) && + parser.tokens[parser.tokenIndex].Type == TOKEN_NAME { + varName := parser.tokens[parser.tokenIndex].Value parser.tokenIndex++ - - if parser.tokenIndex < len(parser.tokens) && - parser.tokens[parser.tokenIndex].Type == TOKEN_OPERATOR && - parser.tokens[parser.tokenIndex].Value == "=" { - + + if parser.tokenIndex < len(parser.tokens) && + parser.tokens[parser.tokenIndex].Type == TOKEN_OPERATOR && + parser.tokens[parser.tokenIndex].Value == "=" { + // Skip the equals sign parser.tokenIndex++ - + // Parse the right side expression expr, err := parser.parseExpression() if err != nil { return nil, fmt.Errorf("error parsing expression in do assignment at line %d: %w", doLine, err) } - + // Make sure we have the closing tag if parser.tokenIndex >= len(parser.tokens) || parser.tokens[parser.tokenIndex].Type != TOKEN_BLOCK_END { return nil, fmt.Errorf("expecting end of do tag at line %d", doLine) } parser.tokenIndex++ - + // Validate the variable name - it should not be a numeric literal if _, err := strconv.Atoi(varName); err == nil { return nil, fmt.Errorf("invalid variable name %q in do tag assignment at line %d", varName, doLine) } - + // Create a SetNode instead of DoNode for assignments return &SetNode{ name: varName, @@ -2014,7 +2014,7 @@ func (p *Parser) parseDo(parser *Parser) (Node, error) { line: doLine, }, nil } - + // If it wasn't an assignment, backtrack to parse it as a normal expression parser.tokenIndex -= 1 } @@ -2208,13 +2208,6 @@ func (p *Parser) parseMacro(parser *Parser) (Node, error) { return nil, err } - // Debug output for default value - if literalNode, ok := defaultExpr.(*LiteralNode); ok { - fmt.Printf("DEBUG: Default value for %s: %v (type %T)\n", paramName, literalNode.value, literalNode.value) - } else { - fmt.Printf("DEBUG: Default value for %s: %T\n", paramName, defaultExpr) - } - defaults[paramName] = defaultExpr } diff --git a/update_tokenizer.go.tmp b/update_tokenizer.go.tmp deleted file mode 100644 index a55968c..0000000 --- a/update_tokenizer.go.tmp +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "regexp" -) - -func main() { - // Read the html_preserving_tokenizer.go file - filepath := "html_preserving_tokenizer.go" - content, err := ioutil.ReadFile(filepath) - if err != nil { - fmt.Printf("Error reading file: %v\n", err) - return - } - - // Make a backup of the original file - err = ioutil.WriteFile(filepath+".bak", content, 0644) - if err != nil { - fmt.Printf("Error creating backup: %v\n", err) - return - } - - // Define patterns to replace - pattern1 := regexp.MustCompile(`tokens = append\(tokens, Token{Type: TOKEN_([A-Z_]+), Value: ([^,]+), Line: line}\)`) - pattern2 := regexp.MustCompile(`\*tokens = append\(\*tokens, Token{Type: TOKEN_([A-Z_]+), Value: ([^,]+), Line: line}\)`) - pattern3 := regexp.MustCompile(`\*tokens = append\(\*tokens, Token{\s+Type:\s+TOKEN_([A-Z_]+),\s+Value:\s+([^,]+),\s+Line:\s+line,\s+}\)`) - - // Replace patterns - result := pattern1.ReplaceAllString(string(content), `tokens = append(tokens, createToken(TOKEN_$1, $2, line))`) - result = pattern2.ReplaceAllString(result, `*tokens = append(*tokens, createToken(TOKEN_$1, $2, line))`) - result = pattern3.ReplaceAllString(result, `*tokens = append(*tokens, createToken(TOKEN_$1, $2, line))`) - - // Write the updated content back to the file - err = ioutil.WriteFile(filepath, []byte(result), 0644) - if err != nil { - fmt.Printf("Error writing file: %v\n", err) - return - } - - fmt.Println("Updated all token creation sites successfully!") - - // Count the number of replacements - originalTokens := countTokenCreations(string(content)) - updatedTokens := countTokenCreations(result) - - fmt.Printf("Original token creations: %d\n", originalTokens) - fmt.Printf("Remaining token creations: %d\n", updatedTokens) - fmt.Printf("Replaced %d token creation sites\n", originalTokens - updatedTokens) -} - -func countTokenCreations(content string) int { - pattern1 := regexp.MustCompile(`Token{Type: TOKEN_`) - pattern2 := regexp.MustCompile(`Token{\s+Type:\s+TOKEN_`) - - count1 := len(pattern1.FindAllStringIndex(content, -1)) - count2 := len(pattern2.FindAllStringIndex(content, -1)) - - return count1 + count2 -} \ No newline at end of file