sulpher

package module
v0.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

README

sulpher

A Cypher-compatible parser written in Go. Parses openCypher 9 queries into an Abstract Syntax Tree (AST).

Features

  • Full openCypher 9 reading and writing clause set (MATCH, OPTIONAL MATCH, CREATE, MERGE, SET, DELETE, DETACH DELETE, REMOVE, FOREACH, RETURN, WITH, UNWIND, CALL … YIELD)
  • UNION / UNION ALL between query parts
  • Pattern matching with node patterns, directed and undirected relationships, multi-label nodes, multiple relationship types (|), and variable-length ranges ([*1..5])
  • Graph path functions: shortestPath, allShortestPaths, with path variable assignment (p = shortestPath(…))
  • Pratt expression parser handling the full operator precedence hierarchy
  • List comprehensions [x IN list WHERE pred | expr], pattern comprehensions, quantifier expressions (ALL, ANY, NONE, SINGLE, FILTER)
  • EXISTS subquery predicates
  • Case-insensitive keywords (Cypher is case-insensitive for keywords)
  • Backtick-quoted identifiers `My Label`
  • Named parameters ($param)
  • Line/block comment tokenisation (// and /* … */)
  • Source-position (line, column) on every token
  • Visitor and Inspector utilities for AST traversal

Installation

go get github.com/ha1tch/sulpher

Usage

package main

import (
    "fmt"
    "github.com/ha1tch/sulpher"
)

func main() {
    input := `MATCH (n:Person)-[:KNOWS]->(m:Person) RETURN n.name, m.name`

    query, errors := sulpher.Parse(input)
    if len(errors) > 0 {
        for _, err := range errors {
            fmt.Println("Error:", err)
        }
        return
    }

    fmt.Println(query.String())
}

Supported Syntax

Reading clauses
  • MATCH (and OPTIONAL MATCH)
  • WITH (with ORDER BY, SKIP, LIMIT, WHERE)
  • UNWIND … AS
  • CALL … YIELD … WHERE
Writing clauses
  • CREATE
  • MERGE (with ON CREATE SET and ON MATCH SET)
  • SET (property assignment, property merge +=, label addition)
  • DELETE / DETACH DELETE
  • REMOVE
  • FOREACH
Projection
  • RETURN (with DISTINCT, ORDER BY, SKIP, LIMIT)
  • RETURN *
Composite
  • UNION / UNION ALL
Patterns
  • Node patterns: (var:Label1:Label2 {prop: val})
  • Directed relationship: -[r:TYPE]-> or <-[r:TYPE]-
  • Undirected relationship: -[r:TYPE]-
  • Multiple types: -[:A|B|C]->
  • Variable-length: -[*]->, -[*1..5]->
  • Path variables: p = (a)-[:KNOWS]->(b)
  • shortestPath(…), allShortestPaths(…)
Expressions
  • Arithmetic: +, -, *, /, %, ^
  • Comparison: =, <>, <, >, <=, >=
  • Logical: AND, OR, XOR, NOT
  • String predicates: STARTS WITH, ENDS WITH, CONTAINS, =~ (regex)
  • IN, IS NULL, IS NOT NULL, NOT IN
  • Property access: n.prop
  • Dynamic access / list slice: list[idx], list[from..to]
  • Function calls: f(args), f(DISTINCT arg), qualified names apoc.util.sleep(…)
  • count(*), count(DISTINCT expr)
  • List literals: [1, 2, 3]
  • Map literals: {name: 'Alice', age: 30}
  • Named parameters: $param
  • List comprehension: [x IN list WHERE pred | expr]
  • Pattern comprehension: [(a)-[r]->(b) WHERE pred | expr]
  • Quantifiers: ALL(x IN list WHERE pred), ANY(…), NONE(…), SINGLE(…)
  • EXISTS subquery: EXISTS { MATCH (n) WHERE … }
  • CASE (simple and searched)

Project Structure

sulpher/
├── token/          # Token types and keywords
├── lexer/          # Lexical analysis
├── ast/            # Abstract syntax tree nodes
├── parser/         # Recursive descent parser with Pratt expression parsing
├── version/        # Version information package
├── testdata/       # Cypher query samples for integration testing
├── cmd/example/    # Example usage
├── sulpher.go      # Main API
├── VERSION         # Version number (single source of truth)
└── go.mod

Version

Access the library version programmatically:

import "github.com/ha1tch/sulpher/pkg/version"

fmt.Println(version.Version)  // "0.1.0"
fmt.Println(version.Full())   // "sulpher version 0.1.0"

Testing

Run all tests:

go test ./...

Run parser tests verbosely:

go test ./parser -v

Run benchmarks:

go test ./parser -bench=.

Requirements

  • Go 1.22 or later

Specification

This parser targets the openCypher 9 specification, with partial coverage of Neo4j Cypher 5 and Cypher 25 extensions.

For a detailed feature-by-feature breakdown across all three language layers, see docs/COMPAT.md.

For the release process and versioning policy, see docs/RELEASE.md.

For a history of changes, see CHANGELOG.md.

License

Copyright (c) 2026 haitch

Licensed under the Apache License, Version 2.0. See LICENSE for the full licence text, or visit https://www.apache.org/licenses/LICENSE-2.0.

Contact

h@ual.li
https://oldbytes.space/@haitchfive

Documentation

Overview

Package sulpher provides a parser for the Cypher graph query language.

Cypher is a declarative, SQL-inspired graph query language developed by Neo4j and standardised through the openCypher project. This package parses Cypher queries into an Abstract Syntax Tree (AST) that can be analysed, transformed, or executed in Go.

Example usage:

query, errors := sulpher.Parse(`MATCH (n:Person)-[:KNOWS]->(m) RETURN n.name`)
if len(errors) > 0 {
    for _, err := range errors {
        fmt.Println("Error:", err)
    }
    return
}
fmt.Println(query.String())

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Parse

func Parse(input string) (*ast.Query, []string)

Parse parses a Cypher query string and returns the AST root and any errors. The returned slice is empty when parsing succeeds without errors.

func Tokenize

func Tokenize(input string) []token.Token

Tokenize returns all tokens produced by scanning the input, including EOF.

func Walk

func Walk(v Visitor, node ast.Node)

Walk traverses the AST rooted at node in depth-first order, calling v.Visit on each node. If Visit returns nil the subtree is not descended.

Types

type BooleanLiteral

type BooleanLiteral = ast.BooleanLiteral

Expression types

type CallClause

type CallClause = ast.CallClause

Clause types

type CaseExpression

type CaseExpression = ast.CaseExpression

Expression types

type CaseWhen

type CaseWhen = ast.CaseWhen

Expression types

type CountStar

type CountStar = ast.CountStar

Expression types

type CreateClause

type CreateClause = ast.CreateClause

Clause types

type DeleteClause

type DeleteClause = ast.DeleteClause

Clause types

type DynamicPropertyAccess

type DynamicPropertyAccess = ast.DynamicPropertyAccess

Expression types

type ExistsSubquery

type ExistsSubquery = ast.ExistsSubquery

Expression types

type Expression

type Expression = ast.Expression

Statement and Expression base interfaces

type FloatLiteral

type FloatLiteral = ast.FloatLiteral

Expression types

type ForeachClause

type ForeachClause = ast.ForeachClause

Clause types

type FunctionCall

type FunctionCall = ast.FunctionCall

Expression types

type Identifier

type Identifier = ast.Identifier

Expression types

type InExpression

type InExpression = ast.InExpression

Expression types

type InfixExpression

type InfixExpression = ast.InfixExpression

Expression types

type Inspector

type Inspector struct {
	// contains filtered or unexported fields
}

Inspector collects all AST nodes for convenient querying.

func NewInspector

func NewInspector(query *ast.Query) *Inspector

NewInspector creates a new Inspector for the given query AST.

func (*Inspector) FindFunctionCalls

func (insp *Inspector) FindFunctionCalls() []*ast.FunctionCall

FindFunctionCalls returns all function call expressions in the AST.

func (*Inspector) FindMatchClauses

func (insp *Inspector) FindMatchClauses() []*ast.MatchClause

FindMatchClauses returns all MATCH clauses in the AST.

func (*Inspector) FindNodePatterns

func (insp *Inspector) FindNodePatterns() []*ast.NodePattern

FindNodePatterns returns all node patterns in the AST.

func (*Inspector) FindParameters

func (insp *Inspector) FindParameters() []*ast.Parameter

FindParameters returns all parameter references in the AST.

func (*Inspector) FindRelationshipPatterns

func (insp *Inspector) FindRelationshipPatterns() []*ast.RelationshipPattern

FindRelationshipPatterns returns all relationship patterns in the AST.

func (*Inspector) FindReturnClauses

func (insp *Inspector) FindReturnClauses() []*ast.ReturnClause

FindReturnClauses returns all RETURN clauses in the AST.

type IntegerLiteral

type IntegerLiteral = ast.IntegerLiteral

Expression types

type IsNullExpression

type IsNullExpression = ast.IsNullExpression

Expression types

type LabelExpression

type LabelExpression = ast.LabelExpression

Expression types

type ListComprehension

type ListComprehension = ast.ListComprehension

Expression types

type ListLiteral

type ListLiteral = ast.ListLiteral

Expression types

type ListSlice

type ListSlice = ast.ListSlice

Expression types

type MapLiteral

type MapLiteral = ast.MapLiteral

Expression types

type MapPair

type MapPair = ast.MapPair

Expression types

type MatchClause

type MatchClause = ast.MatchClause

Clause types

type MergeClause

type MergeClause = ast.MergeClause

Clause types

type Node

type Node = ast.Node

Statement and Expression base interfaces

type NodePattern

type NodePattern = ast.NodePattern

Pattern types

type NullLiteral

type NullLiteral = ast.NullLiteral

Expression types

type Parameter

type Parameter = ast.Parameter

Expression types

type Pattern

type Pattern = ast.Pattern

Pattern types

type PatternComprehension

type PatternComprehension = ast.PatternComprehension

Expression types

type PatternPart

type PatternPart = ast.PatternPart

Pattern types

type PrefixExpression

type PrefixExpression = ast.PrefixExpression

Expression types

type ProjectionItem

type ProjectionItem = ast.ProjectionItem

Projection types

type PropertyAccess

type PropertyAccess = ast.PropertyAccess

Expression types

type QualifiedName

type QualifiedName = ast.QualifiedName

Expression types

type QuantifierExpression

type QuantifierExpression = ast.QuantifierExpression

Expression types

type Query

type Query = ast.Query

Root types

type RelationshipPattern

type RelationshipPattern = ast.RelationshipPattern

Pattern types

type RemoveClause

type RemoveClause = ast.RemoveClause

Clause types

type RemoveItem

type RemoveItem = ast.RemoveItem

Projection types

type ReturnClause

type ReturnClause = ast.ReturnClause

Clause types

type SetClause

type SetClause = ast.SetClause

Clause types

type SetItem

type SetItem = ast.SetItem

Projection types

type ShortestPathExpression

type ShortestPathExpression = ast.ShortestPathExpression

Expression types

type SingleQuery

type SingleQuery = ast.SingleQuery

Root types

type SortItem

type SortItem = ast.SortItem

Projection types

type Statement

type Statement = ast.Statement

Statement and Expression base interfaces

type StringLiteral

type StringLiteral = ast.StringLiteral

Expression types

type StringPredicate

type StringPredicate = ast.StringPredicate

Expression types

type Token

type Token = token.Token

Token type

type UnionPart

type UnionPart = ast.UnionPart

Root types

type UnwindClause

type UnwindClause = ast.UnwindClause

Clause types

type Visitor

type Visitor interface {
	Visit(node ast.Node) Visitor
}

Visitor defines an interface for depth-first AST traversal.

type WithClause

type WithClause = ast.WithClause

Clause types

type YieldItem

type YieldItem = ast.YieldItem

Projection types

Directories

Path Synopsis
Package ast defines the Abstract Syntax Tree nodes for Cypher.
Package ast defines the Abstract Syntax Tree nodes for Cypher.
cmd
example command
Command example demonstrates sulpher's public API.
Command example demonstrates sulpher's public API.
Package lexer implements a lexical scanner for Cypher.
Package lexer implements a lexical scanner for Cypher.
Graph label boolean expression miniparser for sulpher.
Graph label boolean expression miniparser for sulpher.
pkg
version
Package version exposes the current version of sulpher.
Package version exposes the current version of sulpher.
Package token defines constants representing the lexical tokens of Cypher.
Package token defines constants representing the lexical tokens of Cypher.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL