graph-ecs/src/query.js

73 lines
1.6 KiB
JavaScript

import { join } from './fn.js'
import { alpha, alphanumeric, any, char, many, map, noCaseString, parse, seq, skip } from './parser.js'
// MATCH (a:Label)-[e:Label]->(b:Label)
// RETURN a, b
const Identifier = (name, label) => ({ name, label })
const ObjectType = Object.freeze({
Node: 0,
Edge: 1
})
const GraphObject = ({ name, label }, type, properties = []) => Object.freeze({
name,
label,
type,
properties
})
const whitespace = char(' ')
const matchKeyword = noCaseString('match')
const returnKeyword = noCaseString('return')
const name = map(
join(''),
seq(alpha, many(alphanumeric))
)
const colon = char(':')
const label = seq(skip(colon), name)
const id = any(
map(
([name, label]) => Identifier(name, label),
seq(name, label)
),
map(
([name]) => Identifier(name),
name
),
map(
([label]) => Identifier(undefined, label),
label
)
)
const lparen = char('(')
const rparen = char(')')
const node = map(
([id]) => GraphObject(id, ObjectType.Node),
seq(skip(lparen), id, skip(rparen))
)
const lsquare = char('[')
const rsquare = char(']')
const edge = map(
([id]) => GraphObject(id, ObjectType.Edge),
seq(skip(lsquare), id, skip(rsquare))
)
const hyphen = char('-')
const rchevron = char('>')
const arrow = seq(hyphen, rchevron)
const relationship = seq(skip(hyphen), edge, skip(arrow), node)
const matchParameters = seq(node, many(relationship))
const matchStmt = seq(skip(matchKeyword), skip(many(whitespace)), matchParameters)
const query = 'MATCH (:Label)-[e:Label]->(b:Label)'
const result = parse(matchStmt, query)
console.log(result.value[0])