scripts/CodeMirror/mode/pig/pig.js (view raw)
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: https://codemirror.net/LICENSE
3
4/*
5 * Pig Latin Mode for CodeMirror 2
6 * @author Prasanth Jayachandran
7 * @link https://github.com/prasanthj/pig-codemirror-2
8 * This implementation is adapted from PL/SQL mode in CodeMirror 2.
9 */
10(function(mod) {
11 if (typeof exports == "object" && typeof module == "object") // CommonJS
12 mod(require("../../lib/codemirror"));
13 else if (typeof define == "function" && define.amd) // AMD
14 define(["../../lib/codemirror"], mod);
15 else // Plain browser env
16 mod(CodeMirror);
17})(function(CodeMirror) {
18"use strict";
19
20CodeMirror.defineMode("pig", function(_config, parserConfig) {
21 var keywords = parserConfig.keywords,
22 builtins = parserConfig.builtins,
23 types = parserConfig.types,
24 multiLineStrings = parserConfig.multiLineStrings;
25
26 var isOperatorChar = /[*+\-%<>=&?:\/!|]/;
27
28 function chain(stream, state, f) {
29 state.tokenize = f;
30 return f(stream, state);
31 }
32
33 function tokenComment(stream, state) {
34 var isEnd = false;
35 var ch;
36 while(ch = stream.next()) {
37 if(ch == "/" && isEnd) {
38 state.tokenize = tokenBase;
39 break;
40 }
41 isEnd = (ch == "*");
42 }
43 return "comment";
44 }
45
46 function tokenString(quote) {
47 return function(stream, state) {
48 var escaped = false, next, end = false;
49 while((next = stream.next()) != null) {
50 if (next == quote && !escaped) {
51 end = true; break;
52 }
53 escaped = !escaped && next == "\\";
54 }
55 if (end || !(escaped || multiLineStrings))
56 state.tokenize = tokenBase;
57 return "error";
58 };
59 }
60
61
62 function tokenBase(stream, state) {
63 var ch = stream.next();
64
65 // is a start of string?
66 if (ch == '"' || ch == "'")
67 return chain(stream, state, tokenString(ch));
68 // is it one of the special chars
69 else if(/[\[\]{}\(\),;\.]/.test(ch))
70 return null;
71 // is it a number?
72 else if(/\d/.test(ch)) {
73 stream.eatWhile(/[\w\.]/);
74 return "number";
75 }
76 // multi line comment or operator
77 else if (ch == "/") {
78 if (stream.eat("*")) {
79 return chain(stream, state, tokenComment);
80 }
81 else {
82 stream.eatWhile(isOperatorChar);
83 return "operator";
84 }
85 }
86 // single line comment or operator
87 else if (ch=="-") {
88 if(stream.eat("-")){
89 stream.skipToEnd();
90 return "comment";
91 }
92 else {
93 stream.eatWhile(isOperatorChar);
94 return "operator";
95 }
96 }
97 // is it an operator
98 else if (isOperatorChar.test(ch)) {
99 stream.eatWhile(isOperatorChar);
100 return "operator";
101 }
102 else {
103 // get the while word
104 stream.eatWhile(/[\w\$_]/);
105 // is it one of the listed keywords?
106 if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
107 //keywords can be used as variables like flatten(group), group.$0 etc..
108 if (!stream.eat(")") && !stream.eat("."))
109 return "keyword";
110 }
111 // is it one of the builtin functions?
112 if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase()))
113 return "variable-2";
114 // is it one of the listed types?
115 if (types && types.propertyIsEnumerable(stream.current().toUpperCase()))
116 return "variable-3";
117 // default is a 'variable'
118 return "variable";
119 }
120 }
121
122 // Interface
123 return {
124 startState: function() {
125 return {
126 tokenize: tokenBase,
127 startOfLine: true
128 };
129 },
130
131 token: function(stream, state) {
132 if(stream.eatSpace()) return null;
133 var style = state.tokenize(stream, state);
134 return style;
135 }
136 };
137});
138
139(function() {
140 function keywords(str) {
141 var obj = {}, words = str.split(" ");
142 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
143 return obj;
144 }
145
146 // builtin funcs taken from trunk revision 1303237
147 var pBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL "
148 + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "
149 + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "
150 + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "
151 + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "
152 + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "
153 + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA "
154 + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "
155 + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "
156 + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER ";
157
158 // taken from QueryLexer.g
159 var pKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
160 + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
161 + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
162 + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE "
163 + "NEQ MATCHES TRUE FALSE DUMP";
164
165 // data types
166 var pTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP ";
167
168 CodeMirror.defineMIME("text/x-pig", {
169 name: "pig",
170 builtins: keywords(pBuiltins),
171 keywords: keywords(pKeywords),
172 types: keywords(pTypes)
173 });
174
175 CodeMirror.registerHelper("hintWords", "pig", (pBuiltins + pTypes + pKeywords).split(" "));
176}());
177
178});