|
@@ -0,0 +1,322 @@
|
|
|
|
+(function (mod) {
|
|
|
|
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
|
|
+ mod(require("codemirror/lib/codemirror"));
|
|
|
|
+ else if (typeof define == "function" && define.amd) // AMD
|
|
|
|
+ define(["codemirror/lib/codemirror"], mod);
|
|
|
|
+ else // Plain browser env
|
|
|
|
+ mod(CodeMirror);
|
|
|
|
+})(function (CodeMirror) {
|
|
|
|
+ "use strict";
|
|
|
|
+
|
|
|
|
+ function Context(indented, column, type, info, align, prev) {
|
|
|
|
+ this.indented = indented;
|
|
|
|
+ this.column = column;
|
|
|
|
+ this.type = type;
|
|
|
|
+ this.info = info;
|
|
|
|
+ this.align = align;
|
|
|
|
+ this.prev = prev;
|
|
|
|
+ }
|
|
|
|
+ function pushContext(state, col, type, info) {
|
|
|
|
+ var indent = state.indented;
|
|
|
|
+ if (state.context && state.context.type == "statement" && type != "statement")
|
|
|
|
+ indent = state.context.indented;
|
|
|
|
+ return state.context = new Context(indent, col, type, info, null, state.context);
|
|
|
|
+ }
|
|
|
|
+ function popContext(state) {
|
|
|
|
+ var t = state.context.type;
|
|
|
|
+ if (t == ")" || t == "]" || t == "}")
|
|
|
|
+ state.indented = state.context.indented;
|
|
|
|
+ return state.context = state.context.prev;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function typeBefore(stream, state, pos) {
|
|
|
|
+ if (state.prevToken == "variable" || state.prevToken == "type") return true;
|
|
|
|
+ if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
|
|
|
|
+ if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function isTopScope(context) {
|
|
|
|
+ for (; ;) {
|
|
|
|
+ if (!context || context.type == "top") return true;
|
|
|
|
+ if (context.type == "}" && context.prev.info != "namespace") return false;
|
|
|
|
+ context = context.prev;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ CodeMirror.defineMode("ivprog", function (config, parserConfig) {
|
|
|
|
+ var indentUnit = config.indentUnit,
|
|
|
|
+ statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
|
|
|
|
+ dontAlignCalls = parserConfig.dontAlignCalls,
|
|
|
|
+ keywords = parserConfig.keywords || {},
|
|
|
|
+ switchKeyword = parserConfig.switchKeyword,
|
|
|
|
+ caseKeyword = parserConfig.caseKeyword,
|
|
|
|
+ defaultKeyword = parserConfig.defaultKeyword,
|
|
|
|
+ caseRegex = new RegExp(`^\s*(?:${caseKeyword} .*?:|${defaultKeyword}:|\{\}?|\})$`),////,
|
|
|
|
+ types = parserConfig.types || {},
|
|
|
|
+ builtin = parserConfig.builtin || {},
|
|
|
|
+ blockKeywords = parserConfig.blockKeywords || {},
|
|
|
|
+ defKeywords = parserConfig.defKeywords || {},
|
|
|
|
+ atoms = parserConfig.atoms || {},
|
|
|
|
+ hooks = parserConfig.hooks || {},
|
|
|
|
+ multiLineStrings = parserConfig.multiLineStrings,
|
|
|
|
+ indentStatements = false,
|
|
|
|
+ namespaceSeparator = /\./,
|
|
|
|
+ isPunctuationChar = /[\[\]{}\(\),;\:\n]/,
|
|
|
|
+ numberStart = /[\d\.]/,
|
|
|
|
+ number = /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)/i,
|
|
|
|
+ isOperatorChar = /[+\-*%=<>!\/]/,
|
|
|
|
+ isIdentifierChar = /[a-zA-Z_][a-zA-Z0-9_]*/,
|
|
|
|
+ // An optional function that takes a {string} token and returns true if it
|
|
|
|
+ // should be treated as a builtin.
|
|
|
|
+ isReservedIdentifier = parserConfig.isReservedIdentifier || false;
|
|
|
|
+
|
|
|
|
+ var curPunc, isDefKeyword;
|
|
|
|
+
|
|
|
|
+ function tokenBase(stream, state) {
|
|
|
|
+ var ch = stream.next();
|
|
|
|
+ if (hooks[ch]) {
|
|
|
|
+ var result = hooks[ch](stream, state);
|
|
|
|
+ if (result !== false) return result;
|
|
|
|
+ }
|
|
|
|
+ if (ch == '"') {
|
|
|
|
+ state.tokenize = tokenString(ch);
|
|
|
|
+ return state.tokenize(stream, state);
|
|
|
|
+ }
|
|
|
|
+ if (isPunctuationChar.test(ch)) {
|
|
|
|
+ curPunc = ch;
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ if (numberStart.test(ch)) {
|
|
|
|
+ stream.backUp(1)
|
|
|
|
+ if (stream.match(number)) return "number"
|
|
|
|
+ stream.next()
|
|
|
|
+ }
|
|
|
|
+ if (ch == "/") {
|
|
|
|
+ if (stream.eat("*")) {
|
|
|
|
+ state.tokenize = tokenComment;
|
|
|
|
+ return tokenComment(stream, state);
|
|
|
|
+ }
|
|
|
|
+ if (stream.eat("/")) {
|
|
|
|
+ stream.skipToEnd();
|
|
|
|
+ return "comment";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (isOperatorChar.test(ch)) {
|
|
|
|
+ while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) { }
|
|
|
|
+ return "operator";
|
|
|
|
+ }
|
|
|
|
+ stream.eatWhile(isIdentifierChar);
|
|
|
|
+ if (namespaceSeparator) while (stream.match(namespaceSeparator))
|
|
|
|
+ stream.eatWhile(isIdentifierChar);
|
|
|
|
+
|
|
|
|
+ var cur = stream.current();
|
|
|
|
+ if (contains(keywords, cur)) {
|
|
|
|
+ if (contains(blockKeywords, cur)) curPunc = "newstatement";
|
|
|
|
+ if (contains(defKeywords, cur)) isDefKeyword = true;
|
|
|
|
+ return "keyword";
|
|
|
|
+ }
|
|
|
|
+ if (contains(types, cur)) return "type";
|
|
|
|
+ if (contains(builtin, cur)
|
|
|
|
+ || (isReservedIdentifier && isReservedIdentifier(cur))) {
|
|
|
|
+ if (contains(blockKeywords, cur)) curPunc = "newstatement";
|
|
|
|
+ return "builtin";
|
|
|
|
+ }
|
|
|
|
+ if (contains(atoms, cur)) return "atom";
|
|
|
|
+ return "variable";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function tokenString(quote) {
|
|
|
|
+ return function (stream, state) {
|
|
|
|
+ var escaped = false, next, end = false;
|
|
|
|
+ while ((next = stream.next()) != null) {
|
|
|
|
+ if (next == quote && !escaped) { end = true; break; }
|
|
|
|
+ escaped = !escaped && next == "\\";
|
|
|
|
+ }
|
|
|
|
+ if (end || !(escaped || multiLineStrings))
|
|
|
|
+ state.tokenize = null;
|
|
|
|
+ return "string";
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function tokenComment(stream, state) {
|
|
|
|
+ var maybeEnd = false, ch;
|
|
|
|
+ while (ch = stream.next()) {
|
|
|
|
+ if (ch == "/" && maybeEnd) {
|
|
|
|
+ state.tokenize = null;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ maybeEnd = (ch == "*");
|
|
|
|
+ }
|
|
|
|
+ return "comment";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function maybeEOL(stream, state) {
|
|
|
|
+ if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
|
|
|
|
+ state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Interface
|
|
|
|
+
|
|
|
|
+ return {
|
|
|
|
+ startState: function (basecolumn) {
|
|
|
|
+ return {
|
|
|
|
+ tokenize: null,
|
|
|
|
+ context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
|
|
|
|
+ indented: 0,
|
|
|
|
+ startOfLine: true,
|
|
|
|
+ prevToken: null
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ token: function (stream, state) {
|
|
|
|
+ var ctx = state.context;
|
|
|
|
+ if (stream.sol()) {
|
|
|
|
+ if (ctx.align == null) ctx.align = false;
|
|
|
|
+ state.indented = stream.indentation();
|
|
|
|
+ state.startOfLine = true;
|
|
|
|
+ }
|
|
|
|
+ if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
|
|
|
|
+ curPunc = isDefKeyword = null;
|
|
|
|
+ var style = (state.tokenize || tokenBase)(stream, state);
|
|
|
|
+ if (style == "comment" || style == "meta") return style;
|
|
|
|
+ if (ctx.align == null) ctx.align = true;
|
|
|
|
+
|
|
|
|
+ if (curPunc == ";" || curPunc == ":" || (curPunc == "," && stream.match(/^\s*(?:\/\/.*)?$/, false)))
|
|
|
|
+ while (state.context.type == "statement") popContext(state);
|
|
|
|
+ else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
|
|
|
+ else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
|
|
|
+ else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
|
|
|
+ else if (curPunc == "}") {
|
|
|
|
+ while (ctx.type == "statement") ctx = popContext(state);
|
|
|
|
+ if (ctx.type == "}") ctx = popContext(state);
|
|
|
|
+ while (ctx.type == "statement") ctx = popContext(state);
|
|
|
|
+ }
|
|
|
|
+ else if (curPunc == ctx.type) popContext(state);
|
|
|
|
+ else if (indentStatements &&
|
|
|
|
+ (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
|
|
|
|
+ (ctx.type == "statement" && curPunc == "newstatement"))) {
|
|
|
|
+ pushContext(state, stream.column(), "statement", stream.current());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (style == "variable" &&
|
|
|
|
+ ((state.prevToken == "def" ||
|
|
|
|
+ (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
|
|
|
|
+ isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
|
|
|
|
+ style = "def";
|
|
|
|
+
|
|
|
|
+ if (hooks.token) {
|
|
|
|
+ var result = hooks.token(stream, state, style);
|
|
|
|
+ if (result !== undefined) style = result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (style == "def" && parserConfig.styleDefs === false) style = "variable";
|
|
|
|
+
|
|
|
|
+ state.startOfLine = false;
|
|
|
|
+ state.prevToken = isDefKeyword ? "def" : style || curPunc;
|
|
|
|
+ maybeEOL(stream, state);
|
|
|
|
+ return style;
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ indent: function (state, textAfter) {
|
|
|
|
+ if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
|
|
|
|
+ var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
|
|
|
|
+ var closing = firstChar == ctx.type;
|
|
|
|
+ if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
|
|
|
|
+ if (parserConfig.dontIndentStatements)
|
|
|
|
+ while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
|
|
|
|
+ ctx = ctx.prev
|
|
|
|
+ if (hooks.indent) {
|
|
|
|
+ var hook = hooks.indent(state, ctx, textAfter, indentUnit);
|
|
|
|
+ if (typeof hook == "number") return hook
|
|
|
|
+ }
|
|
|
|
+ var switchBlock = ctx.prev && ctx.prev.info == switchKeyword;
|
|
|
|
+ if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
|
|
|
|
+ while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
|
|
|
|
+ return ctx.indented
|
|
|
|
+ }
|
|
|
|
+ if (ctx.type == "statement")
|
|
|
|
+ return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
|
|
|
|
+ if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
|
|
|
|
+ return ctx.column + (closing ? 0 : 1);
|
|
|
|
+ if (ctx.type == ")" && !closing)
|
|
|
|
+ return ctx.indented + statementIndentUnit;
|
|
|
|
+ var caseTestRegex = new RegExp(`^(?:${caseKeyword}|${defaultKeyword})\b`)
|
|
|
|
+ return ctx.indented + (closing ? 0 : indentUnit) +
|
|
|
|
+ (!closing && switchBlock && !caseTestRegex.test(textAfter) ? indentUnit : 0);
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ electricInput: caseRegex,
|
|
|
|
+ blockCommentStart: "/*",
|
|
|
|
+ blockCommentEnd: "*/",
|
|
|
|
+ blockCommentContinue: " * ",
|
|
|
|
+ lineComment: "//",
|
|
|
|
+ fold: "brace"
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ function words(str) {
|
|
|
|
+ var obj = {}, words = str.split(" ");
|
|
|
|
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
|
|
|
+ return obj;
|
|
|
|
+ }
|
|
|
|
+ function contains(words, word) {
|
|
|
|
+ if (typeof words === "function") {
|
|
|
|
+ return words(word);
|
|
|
|
+ } else {
|
|
|
|
+ return words.propertyIsEnumerable(word);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var ivprogKeywords = "programa E OU nao senao se " +
|
|
|
|
+ "enquanto faca pare para retorne funcao const " +
|
|
|
|
+ "contrario caso escolha";
|
|
|
|
+
|
|
|
|
+ // Do not use this. Use the cTypes function below. This is global just to avoid
|
|
|
|
+ // excessive calls when cTypes is being called multiple times during a parse.
|
|
|
|
+ var basicTypes = words("inteiro logico cadeia real vazio");
|
|
|
|
+
|
|
|
|
+ // Returns true if identifier is a "C" type.
|
|
|
|
+ // C type is defined as those that are reserved by the compiler (basicTypes),
|
|
|
|
+ // and those that end in _t (Reserved by POSIX for types)
|
|
|
|
+ // http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html
|
|
|
|
+ function ivprogTypes(identifier) {
|
|
|
|
+ return contains(basicTypes, identifier);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var ivprogBlockKeywords = "programa caso escolha contrario faca enquanto para se senao";
|
|
|
|
+ var ivprogDefKeywords = "funcao const";
|
|
|
|
+
|
|
|
|
+ function def(mimes, mode) {
|
|
|
|
+ if (typeof mimes == "string") mimes = [mimes];
|
|
|
|
+ var words = [];
|
|
|
|
+ function add(obj) {
|
|
|
|
+ if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
|
|
|
|
+ words.push(prop);
|
|
|
|
+ }
|
|
|
|
+ add(mode.keywords);
|
|
|
|
+ add(mode.types);
|
|
|
|
+ add(mode.builtin);
|
|
|
|
+ add(mode.atoms);
|
|
|
|
+ if (words.length) {
|
|
|
|
+ mode.helperType = mimes[0];
|
|
|
|
+ CodeMirror.registerHelper("hintWords", mimes[0], words);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (var i = 0; i < mimes.length; ++i)
|
|
|
|
+ CodeMirror.defineMIME(mimes[i], mode);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ def(["text/x-ivprog"], {
|
|
|
|
+ name: "ivprog",
|
|
|
|
+ keywords: words(ivprogKeywords),
|
|
|
|
+ types: ivprogTypes,
|
|
|
|
+ blockKeywords: words(ivprogBlockKeywords),
|
|
|
|
+ defKeywords: words(ivprogDefKeywords),
|
|
|
|
+ typeFirstDefinitions: true,
|
|
|
|
+ atoms: words("verdadeiro falso"),
|
|
|
|
+ switchKeyword: "escolha",
|
|
|
|
+ caseKeyword: "caso",
|
|
|
|
+ defaultKeyword: "contrario",
|
|
|
|
+ modeProps: { fold: ["brace"] }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+});
|