/media/editors/codemirror/js/parsesparql.js
JavaScript | 162 lines | 160 code | 2 blank | 0 comment | 36 complexity | 425eb2da0b2eecfbda0b5374ed4958cc MD5 | raw file
Possible License(s): LGPL-2.1
1var SparqlParser = Editor.Parser = (function() { 2 function wordRegexp(words) { 3 return new RegExp("^(?:" + words.join("|") + ")$", "i"); 4 } 5 var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri", 6 "isblank", "isliteral", "union", "a"]); 7 var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe", 8 "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional", 9 "graph", "by", "asc", "desc"]); 10 var operatorChars = /[*+\-<>=&|]/; 11 12 var tokenizeSparql = (function() { 13 function normal(source, setState) { 14 var ch = source.next(); 15 if (ch == "$" || ch == "?") { 16 source.nextWhileMatches(/[\w\d]/); 17 return "sp-var"; 18 } 19 else if (ch == "<" && !source.matches(/[\s\u00a0=]/)) { 20 source.nextWhileMatches(/[^\s\u00a0>]/); 21 if (source.equals(">")) source.next(); 22 return "sp-uri"; 23 } 24 else if (ch == "\"" || ch == "'") { 25 setState(inLiteral(ch)); 26 return null; 27 } 28 else if (/[{}\(\),\.;\[\]]/.test(ch)) { 29 return "sp-punc"; 30 } 31 else if (ch == "#") { 32 while (!source.endOfLine()) source.next(); 33 return "sp-comment"; 34 } 35 else if (operatorChars.test(ch)) { 36 source.nextWhileMatches(operatorChars); 37 return "sp-operator"; 38 } 39 else if (ch == ":") { 40 source.nextWhileMatches(/[\w\d\._\-]/); 41 return "sp-prefixed"; 42 } 43 else { 44 source.nextWhileMatches(/[_\w\d]/); 45 if (source.equals(":")) { 46 source.next(); 47 source.nextWhileMatches(/[\w\d_\-]/); 48 return "sp-prefixed"; 49 } 50 var word = source.get(), type; 51 if (ops.test(word)) 52 type = "sp-operator"; 53 else if (keywords.test(word)) 54 type = "sp-keyword"; 55 else 56 type = "sp-word"; 57 return {style: type, content: word}; 58 } 59 } 60 61 function inLiteral(quote) { 62 return function(source, setState) { 63 var escaped = false; 64 while (!source.endOfLine()) { 65 var ch = source.next(); 66 if (ch == quote && !escaped) { 67 setState(normal); 68 break; 69 } 70 escaped = !escaped && ch == "\\"; 71 } 72 return "sp-literal"; 73 }; 74 } 75 76 return function(source, startState) { 77 return tokenizer(source, startState || normal); 78 }; 79 })(); 80 81 function indentSparql(context) { 82 return function(nextChars) { 83 var firstChar = nextChars && nextChars.charAt(0); 84 if (/[\]\}]/.test(firstChar)) 85 while (context && context.type == "pattern") context = context.prev; 86 87 var closing = context && firstChar == matching[context.type]; 88 if (!context) 89 return 0; 90 else if (context.type == "pattern") 91 return context.col; 92 else if (context.align) 93 return context.col - (closing ? context.width : 0); 94 else 95 return context.indent + (closing ? 0 : indentUnit); 96 } 97 } 98 99 function parseSparql(source) { 100 var tokens = tokenizeSparql(source); 101 var context = null, indent = 0, col = 0; 102 function pushContext(type, width) { 103 context = {prev: context, indent: indent, col: col, type: type, width: width}; 104 } 105 function popContext() { 106 context = context.prev; 107 } 108 109 var iter = { 110 next: function() { 111 var token = tokens.next(), type = token.style, content = token.content, width = token.value.length; 112 113 if (content == "\n") { 114 token.indentation = indentSparql(context); 115 indent = col = 0; 116 if (context && context.align == null) context.align = false; 117 } 118 else if (type == "whitespace" && col == 0) { 119 indent = width; 120 } 121 else if (type != "sp-comment" && context && context.align == null) { 122 context.align = true; 123 } 124 125 if (content != "\n") col += width; 126 127 if (/[\[\{\(]/.test(content)) { 128 pushContext(content, width); 129 } 130 else if (/[\]\}\)]/.test(content)) { 131 while (context && context.type == "pattern") 132 popContext(); 133 if (context && content == matching[context.type]) 134 popContext(); 135 } 136 else if (content == "." && context && context.type == "pattern") { 137 popContext(); 138 } 139 else if ((type == "sp-word" || type == "sp-prefixed" || type == "sp-uri" || type == "sp-var" || type == "sp-literal") && 140 context && /[\{\[]/.test(context.type)) { 141 pushContext("pattern", width); 142 } 143 144 return token; 145 }, 146 147 copy: function() { 148 var _context = context, _indent = indent, _col = col, _tokenState = tokens.state; 149 return function(source) { 150 tokens = tokenizeSparql(source, _tokenState); 151 context = _context; 152 indent = _indent; 153 col = _col; 154 return iter; 155 }; 156 } 157 }; 158 return iter; 159 } 160 161 return {make: parseSparql, electricChars: "}]"}; 162})();