Skip to content

Commit 419bd6c

Browse files
committed
First stab at a SPARQL grammar for syntax highlighting
0 parents  commit 419bd6c

File tree

6 files changed

+428
-0
lines changed

6 files changed

+428
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.sublime-workspace

sparql.sublime-project

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"folders":
3+
[
4+
{
5+
"follow_symlinks": true,
6+
"path": "."
7+
}
8+
]
9+
}

sparql.tmLanguage

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>fileTypes</key>
6+
<array>
7+
<string>rq</string>
8+
</array>
9+
<key>name</key>
10+
<string>SPARQL</string>
11+
<key>patterns</key>
12+
<array>
13+
<dict>
14+
<key>comment</key>
15+
<string>Keywords</string>
16+
<key>match</key>
17+
<string>\b(?i:base|prefix|select|distinct|reduced|from|named|construct|ask|describe|where|graph|bind|as|filter|optional|union|order|by|limit|offset|values)\b</string>
18+
<key>name</key>
19+
<string>keyword.sparql</string>
20+
</dict>
21+
<dict>
22+
<key>comment</key>
23+
<string>SPARQL built-in functions</string>
24+
<key>match</key>
25+
<string>\b(?i:concat|regex|asc|desc|bound|isiri|isuri|isblank|isliteral|str|lang|datatype|sameterm|langmatches)\b</string>
26+
<key>name</key>
27+
<string>support.function.sparql</string>
28+
</dict>
29+
<dict>
30+
<key>comment</key>
31+
<string>URI</string>
32+
<key>match</key>
33+
<string>&lt;[^&lt;&gt;"{}|^`\]\\]*&gt;</string>
34+
<key>name</key>
35+
<string>string.uri.sparql</string>
36+
</dict>
37+
<dict>
38+
<key>captures</key>
39+
<dict>
40+
<key>1</key>
41+
<dict>
42+
<key>name</key>
43+
<string>constant.other.sparql</string>
44+
</dict>
45+
<key>2</key>
46+
<dict>
47+
<key>name</key>
48+
<string>entity.name.class.sparql</string>
49+
</dict>
50+
</dict>
51+
<key>comment</key>
52+
<string>Prefix / prefixed URI</string>
53+
<key>match</key>
54+
<string>(\w*:)([^\s]*)</string>
55+
<key>name</key>
56+
<string>constant.complex.sparql</string>
57+
</dict>
58+
<dict>
59+
<key>comment</key>
60+
<string>The special triple predicate 'a'</string>
61+
<key>match</key>
62+
<string>\sa\s</string>
63+
<key>name</key>
64+
<string>entity.name.class.rdfs-type.sparql</string>
65+
</dict>
66+
<dict>
67+
<key>match</key>
68+
<string>[?$]\w+</string>
69+
<key>name</key>
70+
<string>variable.other.sparql</string>
71+
</dict>
72+
<dict>
73+
<key>captures</key>
74+
<dict>
75+
<key>1</key>
76+
<dict>
77+
<key>name</key>
78+
<string>string.sparql</string>
79+
</dict>
80+
<key>2</key>
81+
<dict>
82+
<key>name</key>
83+
<string>keyword.operator.sparql</string>
84+
</dict>
85+
<key>3</key>
86+
<dict>
87+
<key>name</key>
88+
<string>support.type.sparql</string>
89+
</dict>
90+
</dict>
91+
<key>comment</key>
92+
<string>Typed literal</string>
93+
<key>match</key>
94+
<string>("[^"]*")(\^\^)(&lt;[^&lt;&gt;"{}|^`\]\\]*&gt;|\w*:[^\s]+)</string>
95+
<key>name</key>
96+
<string>literal.sparql</string>
97+
</dict>
98+
<dict>
99+
<key>captures</key>
100+
<dict>
101+
<key>1</key>
102+
<dict>
103+
<key>name</key>
104+
<string>string.sparql</string>
105+
</dict>
106+
<key>2</key>
107+
<dict>
108+
<key>name</key>
109+
<string>keyword.operator.sparql</string>
110+
</dict>
111+
<key>3</key>
112+
<dict>
113+
<key>name</key>
114+
<string>support.type.sparql</string>
115+
</dict>
116+
</dict>
117+
<key>comment</key>
118+
<string>String literal</string>
119+
<key>match</key>
120+
<string>('''(?:(?:'|'')?(?:[^'\\]|\\[tbnrf\"']))*'''|"""(?:(?:"|"")?([^"\\]|\\[tbnrf\"']))*"""|'(?:(?:[^\x22\x5C\xA\xD])|\\[tbnrf\"'])*'|"(?:(?:[^\x22\x5C\xA\xD])|\\[tbnrf\"'])*"|'''.*'''|'[^']*')(@[a-zA-Z-]+)?</string>
121+
<key>name</key>
122+
<string>string.sparql</string>
123+
</dict>
124+
<dict>
125+
<key>comment</key>
126+
<string>Numeric literal</string>
127+
<key>match</key>
128+
<string>[+-]?(?:\d+|[0-9]+\.[0-9]*|\.[0-9]+(?:[eE][+-]?\d+)?)</string>
129+
<key>name</key>
130+
<string>constant.numeric.sparql</string>
131+
</dict>
132+
<dict>
133+
<key>comment</key>
134+
<string>Boolean</string>
135+
<key>match</key>
136+
<string>\b(?i:true|false)\b</string>
137+
<key>name</key>
138+
<string>constant.language.sparql</string>
139+
</dict>
140+
<dict>
141+
<key>comment</key>
142+
<string>SPARQL operators</string>
143+
<key>match</key>
144+
<string>(?:\|\||&amp;&amp;|=|!=|&lt;|&gt;|&lt;=|&gt;=|\*|/|\+|-)</string>
145+
<key>name</key>
146+
<string>keyword.operator.sparql</string>
147+
</dict>
148+
<dict>
149+
<key>comment</key>
150+
<string>Comments</string>
151+
<key>match</key>
152+
<string>#.*$</string>
153+
<key>name</key>
154+
<string>comment.line.number-sign.sparql</string>
155+
</dict>
156+
</array>
157+
<key>scopeName</key>
158+
<string>source.sparql</string>
159+
<key>uuid</key>
160+
<string>5a91f9b9-c324-40e6-8bd2-ed959b3adda9</string>
161+
</dict>
162+
</plist>

sparql.tmLanguage.JSON

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
{
2+
"name": "SPARQL",
3+
"scopeName": "source.sparql",
4+
"fileTypes": ["rq"],
5+
"patterns": [
6+
{
7+
"name": "keyword.sparql",
8+
"comment": "Keywords",
9+
"match": "\\b(?i:base|prefix|select|distinct|reduced|from|named|construct|ask|describe|where|graph|bind|as|filter|optional|union|order|by|limit|offset|values)\\b",
10+
},
11+
{
12+
"name": "support.function.sparql",
13+
"comment": "SPARQL built-in functions",
14+
"match": "\\b(?i:concat|regex|asc|desc|bound|isiri|isuri|isblank|isliteral|str|lang|datatype|sameterm|langmatches)\\b"
15+
},
16+
{
17+
"name": "string.uri.sparql",
18+
"comment": "URI",
19+
// Best attempt to convert IRI_REF:
20+
// http://www.w3.org/TR/rdf-sparql-query/#rIRI_REF
21+
"match": "<[^<>\"{}|^`\\]\\\\]*>",
22+
},
23+
{
24+
"name": "constant.complex.sparql",
25+
"comment": "Prefix / prefixed URI",
26+
// PN_CHARS_BASE is insane
27+
// http://www.w3.org/TR/rdf-sparql-query/#rPN_CHARS_BASE
28+
"match": "(\\w*:)([^\\s]*)",
29+
"captures": {
30+
"1": { "name": "constant.other.sparql" },
31+
"2": { "name": "entity.name.class.sparql" }
32+
}
33+
},
34+
{
35+
"name": "entity.name.class.rdfs-type.sparql",
36+
"comment": "The special triple predicate 'a'",
37+
"match": "\\sa\\s"
38+
},
39+
{
40+
"name": "variable.other.sparql",
41+
"match": "[?$]\\w+"
42+
},
43+
{
44+
"name": "literal.sparql",
45+
"comment": "Typed literal",
46+
// Note duplication of IRI_REF
47+
"match": "(\"[^\"]*\")(\\^\\^)(<[^<>\"{}|^`\\]\\\\]*>|\\w*:[^\\s]+)",
48+
"captures": {
49+
"1": { "name": "string.sparql" },
50+
"2": { "name": "keyword.operator.sparql" },
51+
"3": { "name": "support.type.sparql" }
52+
}
53+
},
54+
{
55+
"name": "string.sparql",
56+
"comment": "String literal",
57+
// This is an attempt to implement the following BNF combinations:
58+
// STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 | STRING_LITERAL1 | STRING_LITERAL2
59+
// Creating an incorrectly highlighted example of a triple-quoted string
60+
// turned out to be really hard, so I can't promise the first two options
61+
// are correct!
62+
"match": "('''(?:(?:'|'')?(?:[^'\\\\]|\\\\[tbnrf\\\"']))*'''|\"\"\"(?:(?:\"|\"\")?([^\"\\\\]|\\\\[tbnrf\\\"']))*\"\"\"|'(?:(?:[^\\x22\\x5C\\xA\\xD])|\\\\[tbnrf\\\"'])*'|\"(?:(?:[^\\x22\\x5C\\xA\\xD])|\\\\[tbnrf\\\"'])*\"|'''.*'''|'[^']*')(@[a-zA-Z-]+)?",
63+
"captures": {
64+
"1": { "name": "string.sparql" },
65+
"2": { "name": "keyword.operator.sparql" },
66+
"3": { "name": "support.type.sparql" }
67+
}
68+
},
69+
{
70+
"name": "constant.numeric.sparql",
71+
"comment": "Numeric literal",
72+
"match": "[+-]?(?:\\d+|[0-9]+\\.[0-9]*|\\.[0-9]+(?:[eE][+-]?\\d+)?)"
73+
},
74+
{
75+
"name": "constant.language.sparql",
76+
"comment": "Boolean",
77+
"match": "\\b(?i:true|false)\\b"
78+
},
79+
{
80+
"name": "keyword.operator.sparql",
81+
"comment": "SPARQL operators",
82+
"match": "(?:\\|\\||&&|=|!=|<|>|<=|>=|\\*|/|\\+|-)"
83+
},
84+
{
85+
"name": "comment.line.number-sign.sparql",
86+
"comment": "Comments",
87+
"match": "#.*$"
88+
}
89+
],
90+
"uuid": "5a91f9b9-c324-40e6-8bd2-ed959b3adda9"
91+
}

test.rb

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# My goal is to have this syntax highlighted correctly without
2+
# changing the Ruby package, but I'm not sure that's possible…
3+
4+
puts <<-SPARQL
5+
PREFIX eg: <http://example.com/>
6+
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
7+
8+
SELECT ?name ?mbox
9+
WHERE {
10+
GRAPH <eg:my-graph> {
11+
?x foaf:name ?name .
12+
?x foaf:mbox ?mbox .
13+
?x eg:age ?age
14+
FILTER(?age > 20)
15+
}
16+
}
17+
ORDER BY ASC(?name)
18+
LIMIT 10
19+
SPARQL

0 commit comments

Comments
 (0)