From fcd1dbb98d5ee96b8615577334e585645114f01a Mon Sep 17 00:00:00 2001 From: Conaclos Date: Sun, 20 Jul 2014 17:22:21 +0200 Subject: [PATCH] Adding Eiffel language mode. - Adding Eiffel highlight rules and Eiffel mode - Use Sudoku grid example of Eiffel Rosetta Code project as Eiffel example --- demo/kitchen-sink/docs/eiffel.e | 246 +++++++++++++++++++++++++ lib/ace/ext/modelist.js | 1 + lib/ace/mode/eiffel.js | 51 +++++ lib/ace/mode/eiffel_highlight_rules.js | 143 ++++++++++++++ 4 files changed, 441 insertions(+) create mode 100644 demo/kitchen-sink/docs/eiffel.e create mode 100644 lib/ace/mode/eiffel.js create mode 100644 lib/ace/mode/eiffel_highlight_rules.js diff --git a/demo/kitchen-sink/docs/eiffel.e b/demo/kitchen-sink/docs/eiffel.e new file mode 100644 index 00000000..4b349566 --- /dev/null +++ b/demo/kitchen-sink/docs/eiffel.e @@ -0,0 +1,246 @@ +note + description: "[ + Sudoku grid and simple resolution facilities. + ]" + author: "Victorien ELVINGER" + date: "22 August 2013" + revision: "3" + libraries: "Relies on ARRAY2 from EiffelBase" + +class + SUDOKU_GRID + +inherit + + ANY + redefine + default_create, + out + end + +create + default_create + +feature {NONE} -- Creation + + default_create + -- Create an empty grid. + do + create grid.make_filled (Default_value, 9, 9) + ensure then + unsolved: not solved + end + +feature -- Access + + item alias "[]" (a_row, a_column: INTEGER): INTEGER assign put + -- Value at coordinates (`a_row', `a_column'). + require + valid_row (a_row) + valid_column (a_column) + do + Result := grid [a_row, a_column] + end + + out: STRING + -- Printable representation. + do + Result := "" + across column_range as column_ic loop + across row_range as row_ic loop + Result := Result + grid [row_ic.item, column_ic.item].out + " " + end + Result := Result + "%N" + end + end + + column_range: INTEGER_INTERVAL + -- Column interval. + do + Result := 1 |..| grid.width + end + + row_range: INTEGER_INTERVAL + -- Row interval. + do + Result := 1 |..| grid.height + end + + subgrid_column_range (a_column: INTEGER): INTEGER_INTERVAL + -- Colum interval of the subgrids including `a_column'. + require + valid_column (a_column) + local + l_column: like a_column + do + l_column := ((a_column - 1) // 3)*3 + 1 + Result := l_column |..| (l_column + 2) + ensure + lower_bound: (<<1, 4, 7>>).has (Result.lower) + upper_bound: (<<3, 6, 9>>).has (Result.upper) + end + + subgrid_row_range (a_row: INTEGER): INTEGER_INTERVAL + -- Row interval of the subgrids including `a_row'. + require + valid_row (a_row) + local + l_row: like a_row + do + l_row := ((a_row - 1) // 3) * 3 + 1 + Result := l_row |..| (l_row + 2) + ensure + lower_bound: (<<1, 4, 7>>).has (Result.lower) + upper_bound: (<<3, 6, 9>>).has (Result.upper) + end + +feature -- Status report + + solved: BOOLEAN + -- Is completed? + + valid_column (a_column: INTEGER): BOOLEAN + -- Is `a_column' a valid coordinate? + do + Result := 1 <= a_column and a_column <= grid.width + end + + valid_row (a_row: INTEGER): BOOLEAN + -- Is `a_row' a valid coordinate? + do + Result := 1 <= a_row and a_row <= grid.height + end + + valid_value (a_value: INTEGER): BOOLEAN + -- Is `a_value' a valid item? + do + Result := 1 <= a_value and a_value <= 9 + end + + valid (a_value: INTEGER; a_row, a_column: INTEGER): BOOLEAN + -- Can `a_value' be inserted at coordinates (`a_row', `a_column')? + require + valid_value (a_value) + valid_row (a_row) + valid_column (a_column) + do + Result := not (subgrid_has (a_value, a_row, a_column) or row_has (a_value, a_row) or column_has (a_value, a_column)) + end + + subgrid_has (a_value: INTEGER; a_row, a_column: INTEGER): BOOLEAN + -- Is there `a_value' in the subgrid containing coordinates (`a_row', `a_column')? + require + valid_row (a_row) + valid_column (a_column) + do + across + subgrid_row_range (a_row) as row_ic + until + Result + loop + across + subgrid_column_range (a_column) as column_ic + until + Result + loop + Result := grid [row_ic.item, column_ic.item] = a_value + end + end + end + + row_has (a_value: INTEGER; a_row: INTEGER): BOOLEAN + -- Exist there an item `a_value' at coordinates (`a_row', ?)? + require + valid_row (a_row) + do + Result := across column_range as ic some grid [a_row, ic.item] = a_value end + end + + column_has (a_value: INTEGER; a_column: INTEGER): BOOLEAN + -- Exist there an item `a_value' at coordinates (?, `a_column')? + require + valid_column (a_column) + do + Result := across row_range as ic some grid [ic.item, a_column] = a_value end + end + +feature -- Extension + + put (a_value: INTEGER; a_row, a_column: INTEGER) + -- Assign item `a_value' at coordinates (`a_row', `a_column'). + require + valid_value (a_value) + valid_row (a_row) + valid_column (a_column) + valid (a_value, a_row, a_column) + do + grid [a_row, a_column] := a_value + ensure + item_inserted: grid [a_row, a_column] = a_value + end + +feature -- Change + + solve + -- Try to solve grid. + do + sub_solve (1, 1) + end + +feature {NONE} -- Implementation + + grid: ARRAY2 [INTEGER] + -- Board. + + Default_value: INTEGER = 0 + -- Empty cell content. + + sub_solve (a_row, a_column: INTEGER) + -- Solve grid from row `a_row' and column `a_column'. + require + valid_row (a_row) + valid_column (a_column) + do + if valid_value (grid [a_row, a_column]) then + solve_after (a_row, a_column) + else + across + 1 |..| 9 as ic + until + solved + loop + if valid (ic.item, a_row, a_column) then + put (ic.item, a_row, a_column) + solve_after (a_row, a_column) + + if not solved then + grid [a_row, a_column] := Default_value + end + end + end + end + end + + solve_after (a_row, a_column: INTEGER) + -- Solve the next cell. + require + valid_row (a_row) + valid_column (a_column) + do + if a_column = grid.width then + if a_row = grid.height then + solved := True + else + sub_solve (a_row + 1, 1) + end + else + sub_solve (a_row, a_column + 1) + end + end + +invariant + valid_numbers: solved implies across grid as ic all valid_value (ic.item) end + nine_columns: grid.width = 9 + nine_rows: grid.height = 9 + +end diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 2028386e..53b78f00 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -65,6 +65,7 @@ var supportedModes = { Diff: ["diff|patch"], Dockerfile: ["^Dockerfile"], Dot: ["dot"], + Eiffel: ["e"], Erlang: ["erl|hrl"], EJS: ["ejs"], Forth: ["frt|fs|ldr"], diff --git a/lib/ace/mode/eiffel.js b/lib/ace/mode/eiffel.js new file mode 100644 index 00000000..2ef84ff8 --- /dev/null +++ b/lib/ace/mode/eiffel.js @@ -0,0 +1,51 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2014, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var EiffelHighlightRules = require("./eiffel_highlight_rules").EiffelHighlightRules; +var Range = require("../range").Range; + +var Mode = function() { + this.HighlightRules = EiffelHighlightRules; +}; +oop.inherits(Mode, TextMode); + +(function() { + this.$id = "ace/mode/eiffel"; +}).call(Mode.prototype); + +exports.Mode = Mode; + +}); + diff --git a/lib/ace/mode/eiffel_highlight_rules.js b/lib/ace/mode/eiffel_highlight_rules.js new file mode 100644 index 00000000..f2cc8bd6 --- /dev/null +++ b/lib/ace/mode/eiffel_highlight_rules.js @@ -0,0 +1,143 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2014, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var EiffelHighlightRules = function() { + var keywords = "across|agent|alias|all|attached|as|assign|attribute|check|" + + "class|convert|create|debug|deferred|detachable|do|else|elseif|end|" + + "ensure|expanded|export|external|feature|from|frozen|if|inherit|" + + "inspect|invariant|like|local|loop|not|note|obsolete|old|once|" + + "Precursor|redefine|rename|require|rescue|retry|select|separate|" + + "some|then|undefine|until|variant|when"; + + var operatorKeywords = "and|implies|or|xor"; + + var languageConstants = "Void"; + + var booleanConstants = "True|False"; + + var languageVariables = "Current|Result"; + + var keywordMapper = this.createKeywordMapper({ + "constant.language": languageConstants, + "constant.language.boolean": booleanConstants, + "variable.language": languageVariables, + "keyword.operator": operatorKeywords, + "keyword": keywords + }, "identifier", true); + + this.$rules = { + "start": [{ + token : "comment.line.double-dash", + regex : /--.*$/ + }, { + token : "string.quoted.double", + regex : /"(?:%"|[^%])*?"/ + }, { + token : "string.quoted.other", // "[ ]" aligned verbatim string + regex : /"\[/, + next: "aligned_verbatim_string" + }, { + token : "string.quoted.other", // "{ }" non-aligned verbatim string + regex : /"\{/, + next: "non-aligned_verbatim_string" + }, { + token : "constant.character", + regex : /'(?:%%|%T|%R|%N|%F|%'|[^%])'/ + }, { + token : "constant.numeric", // real + regex : /(?:\d(?:_?\d)*\.|\.\d)(?:\d*[eE][+-]?\d+)?\b/ + }, { + token : "constant.numeric", // integer + regex : /\d(?:_?\d)*\b/ + }, { + token : "constant.numeric", // hex + regex : /0[xX][a-fA-F\d](?:_?[a-fA-F\d])*\b/ + }, { + token : "constant.numeric", // octal + regex : /0[cC][0-7](?:_?[0-7])*\b/ + },{ + token : "constant.numeric", // bin + regex : /0[bB][01](?:_?[01])*\b/ + }, { + token : "keyword.operator", + regex : /\+|\-|\*|\/|\\\\|\/\/|\^|~|\/~|<|>|<=|>=|\/=|=|:=|\|\.\.\||\.\./ + }, { + token : "keyword.operator", // punctuation + regex : /\.|:|,|;\b/ + }, { + token : function (v) { + var result = keywordMapper (v); + if (result === "identifier" && v === v.toUpperCase ()) { + result = "entity.name.type"; + } + return result; + }, + regex : /[a-zA-Z][a-zA-Z\d_]*\b/ + }, { + token : "paren.lparen", + regex : /[\[({]/ + }, { + token : "paren.rparen", + regex : /[\])}]/ + }, { + token : "text", + regex : /\s+/ + } + ], + "aligned_verbatim_string" : [{ + token : "string", // closing multi-line comment + regex : /]"/, + next : "start" + }, { + token : "string", // comment spanning whole line + regex : /[^(?:\]")]+/ + } + ], + "non-aligned_verbatim_string" : [{ + token : "string.quoted.other", // closing multi-line comment + regex : /}"/, + next : "start" + }, { + token : "string.quoted.other", // comment spanning whole line + regex : /[^(?:\}")]+/ + } + ]}; +}; + +oop.inherits(EiffelHighlightRules, TextHighlightRules); + +exports.EiffelHighlightRules = EiffelHighlightRules; +});