117 lines
3.6 KiB
Ruby
117 lines
3.6 KiB
Ruby
# -*- coding: utf-8 -*- #
|
|
# frozen_string_literal: true
|
|
|
|
module Rouge
|
|
module Lexers
|
|
class Cypher < RegexLexer
|
|
tag 'cypher'
|
|
aliases 'cypher'
|
|
filenames '*.cypher'
|
|
mimetypes 'application/x-cypher-query'
|
|
|
|
title "Cypher"
|
|
desc 'The Cypher query language (neo4j.com/docs/cypher-manual)'
|
|
|
|
def self.functions
|
|
@functions ||= Set.new %w(
|
|
ABS ACOS ALLSHORTESTPATHS ASIN ATAN ATAN2 AVG CEIL COALESCE COLLECT
|
|
COS COT COUNT DATE DEGREES E ENDNODE EXP EXTRACT FILTER FLOOR
|
|
HAVERSIN HEAD ID KEYS LABELS LAST LEFT LENGTH LOG LOG10 LOWER LTRIM
|
|
MAX MIN NODE NODES PERCENTILECONT PERCENTILEDISC PI RADIANS RAND
|
|
RANGE REDUCE REL RELATIONSHIP RELATIONSHIPS REPLACE REVERSE RIGHT
|
|
ROUND RTRIM SHORTESTPATH SIGN SIN SIZE SPLIT SQRT STARTNODE STDEV
|
|
STDEVP STR SUBSTRING SUM TAIL TAN TIMESTAMP TOFLOAT TOINT TOINTEGER
|
|
TOSTRING TRIM TYPE UPPER
|
|
)
|
|
end
|
|
|
|
def self.predicates
|
|
@predicates ||= Set.new %w(
|
|
ALL AND ANY CONTAINS EXISTS HAS IN NONE NOT OR SINGLE XOR
|
|
)
|
|
end
|
|
|
|
def self.keywords
|
|
@keywords ||= Set.new %w(
|
|
AS ASC ASCENDING ASSERT BY CASE COMMIT CONSTRAINT CREATE CSV CYPHER
|
|
DELETE DESC DESCENDING DETACH DISTINCT DROP ELSE END ENDS EXPLAIN
|
|
FALSE FIELDTERMINATOR FOREACH FROM HEADERS IN INDEX IS JOIN LIMIT
|
|
LOAD MATCH MERGE NULL ON OPTIONAL ORDER PERIODIC PROFILE REMOVE
|
|
RETURN SCAN SET SKIP START STARTS THEN TRUE UNION UNIQUE UNWIND USING
|
|
WHEN WHERE WITH CALL YIELD
|
|
)
|
|
end
|
|
|
|
state :root do
|
|
rule %r/[\s]+/, Text
|
|
rule %r(//.*?$), Comment::Single
|
|
rule %r(/\*), Comment::Multiline, :multiline_comments
|
|
|
|
rule %r([*+\-<>=&|~%^]), Operator
|
|
rule %r/[{}),;\[\]]/, Str::Symbol
|
|
|
|
# literal number
|
|
rule %r/(\w+)(:)(\s*)(-?[._\d]+)/ do
|
|
groups Name::Label, Str::Delimiter, Text::Whitespace, Num
|
|
end
|
|
|
|
# function-like
|
|
# - "name("
|
|
# - "name ("
|
|
# - "name ("
|
|
rule %r/(\w+)(\s*)(\()/ do |m|
|
|
name = m[1].upcase
|
|
if self.class.functions.include? name
|
|
groups Name::Function, Text::Whitespace, Str::Symbol
|
|
elsif self.class.keywords.include? name
|
|
groups Keyword, Text::Whitespace, Str::Symbol
|
|
else
|
|
groups Name, Text::Whitespace, Str::Symbol
|
|
end
|
|
end
|
|
|
|
rule %r/:\w+/, Name::Class
|
|
|
|
# number range
|
|
rule %r/(-?\d+)(\.\.)(-?\d+)/ do
|
|
groups Num, Operator, Num
|
|
end
|
|
|
|
# numbers
|
|
rule %r/(\d+\.\d*|\d*\.\d+)(e[+-]?\d+)?/i, Num::Float
|
|
rule %r/\d+e[+-]?\d+/i, Num::Float
|
|
rule %r/0[0-7]+/, Num::Oct
|
|
rule %r/0x[a-f0-9]+/i, Num::Hex
|
|
rule %r/\d+/, Num::Integer
|
|
|
|
rule %r([.\w]+:), Name::Property
|
|
|
|
# remaining "("
|
|
rule %r/\(/, Str::Symbol
|
|
|
|
rule %r/[.\w$]+/ do |m|
|
|
match = m[0].upcase
|
|
if self.class.predicates.include? match
|
|
token Operator::Word
|
|
elsif self.class.keywords.include? match
|
|
token Keyword
|
|
else
|
|
token Name
|
|
end
|
|
end
|
|
|
|
rule %r/"(\\\\|\\"|[^"])*"/, Str::Double
|
|
rule %r/'(\\\\|\\'|[^'])*'/, Str::Single
|
|
rule %r/`(\\\\|\\`|[^`])*`/, Str::Backtick
|
|
end
|
|
|
|
state :multiline_comments do
|
|
rule %r(/[*]), Comment::Multiline, :multiline_comments
|
|
rule %r([*]/), Comment::Multiline, :pop!
|
|
rule %r([^/*]+), Comment::Multiline
|
|
rule %r([/*]), Comment::Multiline
|
|
end
|
|
end
|
|
end
|
|
end
|