diff options
Diffstat (limited to 'imports/codemirror/mode/sparql/sparql.js')
-rwxr-xr-x | imports/codemirror/mode/sparql/sparql.js | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/imports/codemirror/mode/sparql/sparql.js b/imports/codemirror/mode/sparql/sparql.js new file mode 100755 index 00000000..ceb52942 --- /dev/null +++ b/imports/codemirror/mode/sparql/sparql.js | |||
@@ -0,0 +1,143 @@ | |||
1 | CodeMirror.defineMode("sparql", function(config) { | ||
2 | var indentUnit = config.indentUnit; | ||
3 | var curPunc; | ||
4 | |||
5 | function wordRegexp(words) { | ||
6 | return new RegExp("^(?:" + words.join("|") + ")$", "i"); | ||
7 | } | ||
8 | var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri", | ||
9 | "isblank", "isliteral", "union", "a"]); | ||
10 | var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe", | ||
11 | "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional", | ||
12 | "graph", "by", "asc", "desc"]); | ||
13 | var operatorChars = /[*+\-<>=&|]/; | ||
14 | |||
15 | function tokenBase(stream, state) { | ||
16 | var ch = stream.next(); | ||
17 | curPunc = null; | ||
18 | if (ch == "$" || ch == "?") { | ||
19 | stream.match(/^[\w\d]*/); | ||
20 | return "variable-2"; | ||
21 | } | ||
22 | else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { | ||
23 | stream.match(/^[^\s\u00a0>]*>?/); | ||
24 | return "atom"; | ||
25 | } | ||
26 | else if (ch == "\"" || ch == "'") { | ||
27 | state.tokenize = tokenLiteral(ch); | ||
28 | return state.tokenize(stream, state); | ||
29 | } | ||
30 | else if (/[{}\(\),\.;\[\]]/.test(ch)) { | ||
31 | curPunc = ch; | ||
32 | return null; | ||
33 | } | ||
34 | else if (ch == "#") { | ||
35 | stream.skipToEnd(); | ||
36 | return "comment"; | ||
37 | } | ||
38 | else if (operatorChars.test(ch)) { | ||
39 | stream.eatWhile(operatorChars); | ||
40 | return null; | ||
41 | } | ||
42 | else if (ch == ":") { | ||
43 | stream.eatWhile(/[\w\d\._\-]/); | ||
44 | return "atom"; | ||
45 | } | ||
46 | else { | ||
47 | stream.eatWhile(/[_\w\d]/); | ||
48 | if (stream.eat(":")) { | ||
49 | stream.eatWhile(/[\w\d_\-]/); | ||
50 | return "atom"; | ||
51 | } | ||
52 | var word = stream.current(), type; | ||
53 | if (ops.test(word)) | ||
54 | return null; | ||
55 | else if (keywords.test(word)) | ||
56 | return "keyword"; | ||
57 | else | ||
58 | return "variable"; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | function tokenLiteral(quote) { | ||
63 | return function(stream, state) { | ||
64 | var escaped = false, ch; | ||
65 | while ((ch = stream.next()) != null) { | ||
66 | if (ch == quote && !escaped) { | ||
67 | state.tokenize = tokenBase; | ||
68 | break; | ||
69 | } | ||
70 | escaped = !escaped && ch == "\\"; | ||
71 | } | ||
72 | return "string"; | ||
73 | }; | ||
74 | } | ||
75 | |||
76 | function pushContext(state, type, col) { | ||
77 | state.context = {prev: state.context, indent: state.indent, col: col, type: type}; | ||
78 | } | ||
79 | function popContext(state) { | ||
80 | state.indent = state.context.indent; | ||
81 | state.context = state.context.prev; | ||
82 | } | ||
83 | |||
84 | return { | ||
85 | startState: function(base) { | ||
86 | return {tokenize: tokenBase, | ||
87 | context: null, | ||
88 | indent: 0, | ||
89 | col: 0}; | ||
90 | }, | ||
91 | |||
92 | token: function(stream, state) { | ||
93 | if (stream.sol()) { | ||
94 | if (state.context && state.context.align == null) state.context.align = false; | ||
95 | state.indent = stream.indentation(); | ||
96 | } | ||
97 | if (stream.eatSpace()) return null; | ||
98 | var style = state.tokenize(stream, state); | ||
99 | |||
100 | if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { | ||
101 | state.context.align = true; | ||
102 | } | ||
103 | |||
104 | if (curPunc == "(") pushContext(state, ")", stream.column()); | ||
105 | else if (curPunc == "[") pushContext(state, "]", stream.column()); | ||
106 | else if (curPunc == "{") pushContext(state, "}", stream.column()); | ||
107 | else if (/[\]\}\)]/.test(curPunc)) { | ||
108 | while (state.context && state.context.type == "pattern") popContext(state); | ||
109 | if (state.context && curPunc == state.context.type) popContext(state); | ||
110 | } | ||
111 | else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); | ||
112 | else if (/atom|string|variable/.test(style) && state.context) { | ||
113 | if (/[\}\]]/.test(state.context.type)) | ||
114 | pushContext(state, "pattern", stream.column()); | ||
115 | else if (state.context.type == "pattern" && !state.context.align) { | ||
116 | state.context.align = true; | ||
117 | state.context.col = stream.column(); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | return style; | ||
122 | }, | ||
123 | |||
124 | indent: function(state, textAfter) { | ||
125 | var firstChar = textAfter && textAfter.charAt(0); | ||
126 | var context = state.context; | ||
127 | if (/[\]\}]/.test(firstChar)) | ||
128 | while (context && context.type == "pattern") context = context.prev; | ||
129 | |||
130 | var closing = context && firstChar == context.type; | ||
131 | if (!context) | ||
132 | return 0; | ||
133 | else if (context.type == "pattern") | ||
134 | return context.col; | ||
135 | else if (context.align) | ||
136 | return context.col + (closing ? 0 : 1); | ||
137 | else | ||
138 | return context.indent + (closing ? 0 : indentUnit); | ||
139 | } | ||
140 | }; | ||
141 | }); | ||
142 | |||
143 | CodeMirror.defineMIME("application/x-sparql-query", "sparql"); | ||