64 lines
1.9 KiB
JavaScript
64 lines
1.9 KiB
JavaScript
import { identifier, literal, Symbol, ws } from './common.js'
|
|
import { Node, Edge, KeyValuePair, Label, Name, Direction, DirectedEdge } from './types.js'
|
|
import { curry, is } from '../fn.js'
|
|
import { many, maybe, map, seq, skip, between, noCaseString, separated, list, any } from '../parser.js'
|
|
|
|
const { Bracket, Colon, Comma, Hyphen } = Symbol
|
|
|
|
const name = map(
|
|
([x]) => new Name(x),
|
|
identifier
|
|
)
|
|
|
|
const trim = curry((parser, state) => (
|
|
between(ws, parser, ws, state)
|
|
))
|
|
|
|
const label = map(([x]) => new Label(x), seq(trim(skip(Colon)), identifier))
|
|
|
|
const bracketed = curry((value, { Left, Right }, state) => (
|
|
between(trim(Left), value, trim(Right), state)
|
|
))
|
|
|
|
const kvp = map(
|
|
([k, v]) => new KeyValuePair(k, v),
|
|
separated(name, trim(Colon), literal)
|
|
)
|
|
export const kvps = list(trim(Comma), kvp)
|
|
export const properties = bracketed(kvps, Bracket.Curly)
|
|
|
|
const id = seq(maybe(name), label)
|
|
|
|
const makeObj = Ctr => params => {
|
|
const [name, label] = is(Name, params[0]) ? [params[0], params[1]] : [undefined, params[0]]
|
|
const properties = !name ? params.slice(1) : params.slice(2)
|
|
return new Ctr(name, label, properties)
|
|
}
|
|
|
|
export const node = map(
|
|
makeObj(Node),
|
|
bracketed(seq(id, maybe(properties)), Bracket.Round)
|
|
)
|
|
|
|
export const edge = map(
|
|
makeObj(Edge),
|
|
bracketed(seq(id, maybe(properties)), Bracket.Square)
|
|
)
|
|
|
|
const arrowRight = map(() => Direction.Right, seq(Hyphen, Bracket.Angle.Right))
|
|
const arrowLeft = map(() => Direction.Left, seq(Bracket.Angle.Left, Hyphen))
|
|
const relationshipRight = map(([edge, direction]) =>
|
|
DirectedEdge.fromEdge(edge, direction),
|
|
seq(skip(Hyphen), edge, arrowRight)
|
|
)
|
|
const relationshipLeft = map(([direction, edge]) =>
|
|
DirectedEdge.fromEdge(edge, direction),
|
|
seq(arrowLeft, edge, skip(Hyphen))
|
|
)
|
|
const relationship = seq(any(relationshipRight, relationshipLeft), node)
|
|
|
|
const keyword = noCaseString('match')
|
|
const params = seq(node, many(relationship))
|
|
|
|
export const statement = seq(skip(keyword), ws, params)
|
|
|