         return nil
     }
     
+    func parsePropertyPath(_ parts : [String]) throws -> PropertyPath? {
+        var stack = [PropertyPath]()
+        var i = parts.makeIterator()
+        let parser = NTriplesPatternParser(reader: "")
+        while let s = i.next() {
+            switch s {
+            case "|":
+                guard stack.count >= 2 else { throw QueryError.parseError("Not enough property paths on the stack for \(s)") }
+                let rhs = stack.popLast()!
+                let lhs = stack.popLast()!
+                stack.append(.alt(lhs, rhs))
+            case "/":
+                guard stack.count >= 2 else { throw QueryError.parseError("Not enough property paths on the stack for \(s)") }
+                let rhs = stack.popLast()!
+                let lhs = stack.popLast()!
+                stack.append(.seq(lhs, rhs))
+            case "^":
+                guard stack.count >= 1 else { throw QueryError.parseError("Not enough property paths on the stack for \(s)") }
+                let lhs = stack.popLast()!
+                stack.append(.inv(lhs))
+            case "nps":
+                guard let c = i.next() else { throw QueryError.parseError("No count argument given for property path operation: \(s)") }
+                guard let count = Int(c) else { throw QueryError.parseError("Failed to parse count argument for property path operation: \(s)") }
+                guard stack.count >= count else { throw QueryError.parseError("Not enough property paths on the stack for \(s)") }
+                var iris = [Term]()
+                for _ in 0..<count {
+                    let link = stack.popLast()!
+                    guard case .link(let term) = link else { throw QueryError.parseError("Not an IRI for \(s)") }
+                    iris.append(term)
+                }
+                stack.append(.nps(iris))
+            default:
+                guard let n = parser.parseNode(line: s) else { throw QueryError.parseError("Failed to parse property path: \(parts.joined(separator: " "))") }
+                guard case .bound(let term) = n else { throw QueryError.parseError("Failed to parse property path: \(parts.joined(separator: " "))") }
+                stack.append(.link(term))
+            }
+        }
+        return stack.popLast()
+    }
+
     public func parse() throws -> Algebra? {
         let lines = self.reader.lines()
         for line in lines {

                } while true
            }
            
        }
    }
    

    case inv(PropertyPath)
    case nps([Term])
    case alt(PropertyPath, PropertyPath)
    case seq(PropertyPath, PropertyPath)
}

public indirect enum Algebra {
