             let parser = NTriplesPatternParser(reader: "")
             guard let pattern = parser.parseTriplePattern(line: rest) else { return nil }
             return .triple(pattern)
+        } else if op == "countall" {
+            let name = parts[1]
+            let groups = parts.suffix(from: 2).map { (name) -> Expression in .node(.variable(name)) }
+            guard let child = stack.popLast() else { return nil }
+            return .aggregate(child, groups, [(.countAll, name)])
         } else if op == "limit" {
             guard let count = Int(rest) else { return nil }
             guard let child = stack.popLast() else { return nil }

            var variables = child.inscope
            variables.insert(v)
            return variables
        }
    }
    

    case distinct(Algebra)
    case slice(Algebra, Int?, Int?)
    case order(Algebra, [Expression])
    case aggregate(Algebra, [Expression], [(Aggregation, String)])
    // TODO: add property paths
    
    private func inscopeUnion(children : [Algebra]) -> Set<String> {
        if children.count == 0 {
