openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

oz.js (6665B)


      1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
      2 // Distributed under an MIT license: http://codemirror.net/LICENSE
      3 
      4 (function(mod) {
      5   if (typeof exports == "object" && typeof module == "object") // CommonJS
      6     mod(require("../../lib/codemirror"));
      7   else if (typeof define == "function" && define.amd) // AMD
      8     define(["../../lib/codemirror"], mod);
      9   else // Plain browser env
     10     mod(CodeMirror);
     11 })(function(CodeMirror) {
     12 "use strict";
     13 
     14 CodeMirror.defineMode("oz", function (conf) {
     15 
     16   function wordRegexp(words) {
     17     return new RegExp("^((" + words.join(")|(") + "))\\b");
     18   }
     19 
     20   var singleOperators = /[\^@!\|<>#~\.\*\-\+\\/,=]/;
     21   var doubleOperators = /(<-)|(:=)|(=<)|(>=)|(<=)|(<:)|(>:)|(=:)|(\\=)|(\\=:)|(!!)|(==)|(::)/;
     22   var tripleOperators = /(:::)|(\.\.\.)|(=<:)|(>=:)/;
     23 
     24   var middle = ["in", "then", "else", "of", "elseof", "elsecase", "elseif", "catch",
     25     "finally", "with", "require", "prepare", "import", "export", "define", "do"];
     26   var end = ["end"];
     27 
     28   var atoms = wordRegexp(["true", "false", "nil", "unit"]);
     29   var commonKeywords = wordRegexp(["andthen", "at", "attr", "declare", "feat", "from", "lex",
     30     "mod", "div", "mode", "orelse", "parser", "prod", "prop", "scanner", "self", "syn", "token"]);
     31   var openingKeywords = wordRegexp(["local", "proc", "fun", "case", "class", "if", "cond", "or", "dis",
     32     "choice", "not", "thread", "try", "raise", "lock", "for", "suchthat", "meth", "functor"]);
     33   var middleKeywords = wordRegexp(middle);
     34   var endKeywords = wordRegexp(end);
     35 
     36   // Tokenizers
     37   function tokenBase(stream, state) {
     38     if (stream.eatSpace()) {
     39       return null;
     40     }
     41 
     42     // Brackets
     43     if(stream.match(/[{}]/)) {
     44       return "bracket";
     45     }
     46 
     47     // Special [] keyword
     48     if (stream.match(/(\[])/)) {
     49         return "keyword"
     50     }
     51 
     52     // Operators
     53     if (stream.match(tripleOperators) || stream.match(doubleOperators)) {
     54       return "operator";
     55     }
     56 
     57     // Atoms
     58     if(stream.match(atoms)) {
     59       return 'atom';
     60     }
     61 
     62     // Opening keywords
     63     var matched = stream.match(openingKeywords);
     64     if (matched) {
     65       if (!state.doInCurrentLine)
     66         state.currentIndent++;
     67       else
     68         state.doInCurrentLine = false;
     69 
     70       // Special matching for signatures
     71       if(matched[0] == "proc" || matched[0] == "fun")
     72         state.tokenize = tokenFunProc;
     73       else if(matched[0] == "class")
     74         state.tokenize = tokenClass;
     75       else if(matched[0] == "meth")
     76         state.tokenize = tokenMeth;
     77 
     78       return 'keyword';
     79     }
     80 
     81     // Middle and other keywords
     82     if (stream.match(middleKeywords) || stream.match(commonKeywords)) {
     83       return "keyword"
     84     }
     85 
     86     // End keywords
     87     if (stream.match(endKeywords)) {
     88       state.currentIndent--;
     89       return 'keyword';
     90     }
     91 
     92     // Eat the next char for next comparisons
     93     var ch = stream.next();
     94 
     95     // Strings
     96     if (ch == '"' || ch == "'") {
     97       state.tokenize = tokenString(ch);
     98       return state.tokenize(stream, state);
     99     }
    100 
    101     // Numbers
    102     if (/[~\d]/.test(ch)) {
    103       if (ch == "~") {
    104         if(! /^[0-9]/.test(stream.peek()))
    105           return null;
    106         else if (( stream.next() == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/))
    107           return "number";
    108       }
    109 
    110       if ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/))
    111         return "number";
    112 
    113       return null;
    114     }
    115 
    116     // Comments
    117     if (ch == "%") {
    118       stream.skipToEnd();
    119       return 'comment';
    120     }
    121     else if (ch == "/") {
    122       if (stream.eat("*")) {
    123         state.tokenize = tokenComment;
    124         return tokenComment(stream, state);
    125       }
    126     }
    127 
    128     // Single operators
    129     if(singleOperators.test(ch)) {
    130       return "operator";
    131     }
    132 
    133     // If nothing match, we skip the entire alphanumerical block
    134     stream.eatWhile(/\w/);
    135 
    136     return "variable";
    137   }
    138 
    139   function tokenClass(stream, state) {
    140     if (stream.eatSpace()) {
    141       return null;
    142     }
    143     stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)/);
    144     state.tokenize = tokenBase;
    145     return "variable-3"
    146   }
    147 
    148   function tokenMeth(stream, state) {
    149     if (stream.eatSpace()) {
    150       return null;
    151     }
    152     stream.match(/([a-zA-Z][A-Za-z0-9_]*)|(`.+`)/);
    153     state.tokenize = tokenBase;
    154     return "def"
    155   }
    156 
    157   function tokenFunProc(stream, state) {
    158     if (stream.eatSpace()) {
    159       return null;
    160     }
    161 
    162     if(!state.hasPassedFirstStage && stream.eat("{")) {
    163       state.hasPassedFirstStage = true;
    164       return "bracket";
    165     }
    166     else if(state.hasPassedFirstStage) {
    167       stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)|\$/);
    168       state.hasPassedFirstStage = false;
    169       state.tokenize = tokenBase;
    170       return "def"
    171     }
    172     else {
    173       state.tokenize = tokenBase;
    174       return null;
    175     }
    176   }
    177 
    178   function tokenComment(stream, state) {
    179     var maybeEnd = false, ch;
    180     while (ch = stream.next()) {
    181       if (ch == "/" && maybeEnd) {
    182         state.tokenize = tokenBase;
    183         break;
    184       }
    185       maybeEnd = (ch == "*");
    186     }
    187     return "comment";
    188   }
    189 
    190   function tokenString(quote) {
    191     return function (stream, state) {
    192       var escaped = false, next, end = false;
    193       while ((next = stream.next()) != null) {
    194         if (next == quote && !escaped) {
    195           end = true;
    196           break;
    197         }
    198         escaped = !escaped && next == "\\";
    199       }
    200       if (end || !escaped)
    201         state.tokenize = tokenBase;
    202       return "string";
    203     };
    204   }
    205 
    206   function buildElectricInputRegEx() {
    207     // Reindentation should occur on [] or on a match of any of
    208     // the block closing keywords, at the end of a line.
    209     var allClosings = middle.concat(end);
    210     return new RegExp("[\\[\\]]|(" + allClosings.join("|") + ")$");
    211   }
    212 
    213   return {
    214 
    215     startState: function () {
    216       return {
    217         tokenize: tokenBase,
    218         currentIndent: 0,
    219         doInCurrentLine: false,
    220         hasPassedFirstStage: false
    221       };
    222     },
    223 
    224     token: function (stream, state) {
    225       if (stream.sol())
    226         state.doInCurrentLine = 0;
    227 
    228       return state.tokenize(stream, state);
    229     },
    230 
    231     indent: function (state, textAfter) {
    232       var trueText = textAfter.replace(/^\s+|\s+$/g, '');
    233 
    234       if (trueText.match(endKeywords) || trueText.match(middleKeywords) || trueText.match(/(\[])/))
    235         return conf.indentUnit * (state.currentIndent - 1);
    236 
    237       if (state.currentIndent < 0)
    238         return 0;
    239 
    240       return state.currentIndent * conf.indentUnit;
    241     },
    242     fold: "indent",
    243     electricInput: buildElectricInputRegEx(),
    244     lineComment: "%",
    245     blockCommentStart: "/*",
    246     blockCommentEnd: "*/"
    247   };
    248 });
    249 
    250 CodeMirror.defineMIME("text/x-oz", "oz");
    251 
    252 });