Support arbitrary koral nodes in AST
diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go
index be11da9..d0ff222 100644
--- a/pkg/parser/parser.go
+++ b/pkg/parser/parser.go
@@ -27,6 +27,9 @@
if err := json.Unmarshal(data, &raw); err != nil {
return nil, fmt.Errorf("failed to parse JSON: %w", err)
}
+ if raw.Type == "" {
+ return nil, fmt.Errorf("missing @type field")
+ }
return parseNode(raw)
}
@@ -82,7 +85,45 @@
}, nil
default:
- return nil, fmt.Errorf("unknown node type: %s", raw.Type)
+ // Store the original JSON content
+ rawContent, err := json.Marshal(raw)
+ if err != nil {
+ return nil, fmt.Errorf("failed to marshal unknown node: %w", err)
+ }
+
+ // Create a catchall node
+ catchall := &ast.CatchallNode{
+ NodeType: raw.Type,
+ RawContent: rawContent,
+ }
+
+ // Parse wrap if present
+ if raw.Wrap != nil {
+ var wrapRaw rawNode
+ if err := json.Unmarshal(raw.Wrap, &wrapRaw); err != nil {
+ return nil, fmt.Errorf("failed to parse wrap in unknown node: %w", err)
+ }
+ wrap, err := parseNode(wrapRaw)
+ if err != nil {
+ return nil, err
+ }
+ catchall.Wrap = wrap
+ }
+
+ // Parse operands if present
+ if len(raw.Operands) > 0 {
+ operands := make([]ast.Node, len(raw.Operands))
+ for i, op := range raw.Operands {
+ node, err := parseNode(op)
+ if err != nil {
+ return nil, err
+ }
+ operands[i] = node
+ }
+ catchall.Operands = operands
+ }
+
+ return catchall, nil
}
}
@@ -122,6 +163,38 @@
Value: n.Value,
}
+ case *ast.CatchallNode:
+ // For catchall nodes, use the stored raw content
+ if n.RawContent != nil {
+ // If we have operands or wrap that were modified, we need to update the raw content
+ if len(n.Operands) > 0 || n.Wrap != nil {
+ var raw rawNode
+ if err := json.Unmarshal(n.RawContent, &raw); err != nil {
+ return rawNode{}
+ }
+
+ // Update operands if present
+ if len(n.Operands) > 0 {
+ raw.Operands = make([]rawNode, len(n.Operands))
+ for i, op := range n.Operands {
+ raw.Operands[i] = nodeToRaw(op)
+ }
+ }
+
+ // Update wrap if present
+ if n.Wrap != nil {
+ raw.Wrap = json.RawMessage(nodeToRaw(n.Wrap).toJSON())
+ }
+
+ return raw
+ }
+ // If no modifications, return the original content as is
+ var raw rawNode
+ _ = json.Unmarshal(n.RawContent, &raw)
+ return raw
+ }
+ return rawNode{}
+
default:
return rawNode{}
}