forked from expo/troggle
[svn] horrid .svns copied accidentally
This commit is contained in:
32
media/CodeMirror-0.62/contrib/lua/LICENSE
Normal file
32
media/CodeMirror-0.62/contrib/lua/LICENSE
Normal file
@@ -0,0 +1,32 @@
|
||||
Copyright (c) 2009, Franciszek Wawrzak
|
||||
All rights reserved.
|
||||
|
||||
This software is provided for use in connection with the
|
||||
CodeMirror suite of modules and utilities, hosted and maintained
|
||||
at http://marijn.haverbeke.nl/codemirror/.
|
||||
|
||||
Redistribution and use of this software 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.
|
||||
|
||||
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 THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||
59
media/CodeMirror-0.62/contrib/lua/css/luacolors.css
Normal file
59
media/CodeMirror-0.62/contrib/lua/css/luacolors.css
Normal file
@@ -0,0 +1,59 @@
|
||||
.editbox {
|
||||
margin: .4em;
|
||||
padding: 0;
|
||||
font-family: monospace;
|
||||
font-size: 10pt;
|
||||
color: black;
|
||||
}
|
||||
|
||||
pre.code, .editbox {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.editbox p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
span.lua-comment {
|
||||
color: #BB9977;
|
||||
}
|
||||
|
||||
span.lua-keyword {
|
||||
font-weight: bold;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
span.lua-string {
|
||||
color: #AA2222;
|
||||
}
|
||||
|
||||
span.lua-stdfunc {
|
||||
font-weight: bold;
|
||||
color: #077;
|
||||
}
|
||||
span.lua-customfunc {
|
||||
font-weight: bold;
|
||||
color: #0AA;
|
||||
}
|
||||
|
||||
|
||||
span.lua-identifier {
|
||||
color: black;
|
||||
}
|
||||
|
||||
span.lua-number {
|
||||
color: #3A3;
|
||||
}
|
||||
|
||||
span.lua-token {
|
||||
color: #151;
|
||||
}
|
||||
|
||||
span.lua-error {
|
||||
color: #FFF;
|
||||
background-color: #F00;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
68
media/CodeMirror-0.62/contrib/lua/index.html
Normal file
68
media/CodeMirror-0.62/contrib/lua/index.html
Normal file
@@ -0,0 +1,68 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script src="../../js/codemirror.js" type="text/javascript"></script>
|
||||
<title>CodeMirror: Lua demonstration</title>
|
||||
</head>
|
||||
<body style="padding: 20px;">
|
||||
|
||||
<p>This page demonstrates <a href="../../index.html">CodeMirror</a>'s
|
||||
Lua parser. Written by <a href="http://francio.pl/">Franciszek
|
||||
Wawrzak</a>, released under a BSD-style <a
|
||||
href="LICENSE">license</a>.</p>
|
||||
|
||||
<div style="border: 1px solid black; padding: 0px;">
|
||||
<textarea id="code" cols="120" rows="30">
|
||||
--[[
|
||||
example useless code to show lua syntax highlighting
|
||||
this is multiline comment
|
||||
]]
|
||||
|
||||
function blahblahblah(x)
|
||||
|
||||
local table = {
|
||||
"asd" = 123,
|
||||
"x" = 0.34,
|
||||
}
|
||||
if x ~= 3 then
|
||||
print( x )
|
||||
elseif x == "string"
|
||||
my_custom_function( 0x34 )
|
||||
else
|
||||
unknown_function( "some string" )
|
||||
end
|
||||
|
||||
--single line comment
|
||||
|
||||
end
|
||||
|
||||
function blablabla3()
|
||||
|
||||
for k,v in ipairs( table ) do
|
||||
--abcde..
|
||||
y=[=[
|
||||
x=[[
|
||||
x is a multi line string
|
||||
]]
|
||||
but its definition is iside a highest level string!
|
||||
]=]
|
||||
print(" \"\" ")
|
||||
--this marks a parser error:
|
||||
s = [== asdasdasd]]
|
||||
|
||||
s = math.sin( x )
|
||||
end
|
||||
|
||||
end
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var editor = CodeMirror.fromTextArea('code', {
|
||||
height: "350px",
|
||||
parserfile: "../contrib/lua/js/parselua.js",
|
||||
stylesheet: "css/luacolors.css",
|
||||
path: "../../js/"
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
253
media/CodeMirror-0.62/contrib/lua/js/parselua.js
Normal file
253
media/CodeMirror-0.62/contrib/lua/js/parselua.js
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
Simple parser for LUA
|
||||
Written for Lua 5.1, based on parsecss and other parsers.
|
||||
features: highlights keywords, strings, comments (no leveling supported! ("[==[")),tokens, basic indenting
|
||||
|
||||
to make this parser highlight your special functions pass table with this functions names to parserConfig argument of creator,
|
||||
|
||||
parserConfig: ["myfunction1","myfunction2"],
|
||||
*/
|
||||
|
||||
|
||||
function findFirstRegexp(words) {
|
||||
return new RegExp("^(?:" + words.join("|") + ")", "i");
|
||||
}
|
||||
|
||||
function matchRegexp(words) {
|
||||
return new RegExp("^(?:" + words.join("|") + ")$", "i");
|
||||
}
|
||||
|
||||
|
||||
|
||||
var luaCustomFunctions= matchRegexp([]);
|
||||
|
||||
function configureLUA(parserConfig){
|
||||
if(parserConfig)
|
||||
luaCustomFunctions= matchRegexp(parserConfig);
|
||||
}
|
||||
|
||||
|
||||
//long list of standard functions from lua manual
|
||||
var luaStdFunctions = matchRegexp([
|
||||
"_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load","loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require","select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall",
|
||||
|
||||
"coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield",
|
||||
|
||||
"debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable","debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable","debug.setupvalue","debug.traceback",
|
||||
|
||||
"close","flush","lines","read","seek","setvbuf","write",
|
||||
|
||||
"io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin","io.stdout","io.tmpfile","io.type","io.write",
|
||||
|
||||
"math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg","math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max","math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh","math.sqrt","math.tan","math.tanh",
|
||||
|
||||
"os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale","os.time","os.tmpname",
|
||||
|
||||
"package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload","package.seeall",
|
||||
|
||||
"string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub","string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper",
|
||||
|
||||
"table.concat","table.insert","table.maxn","table.remove","table.sort"
|
||||
]);
|
||||
|
||||
|
||||
|
||||
var luaKeywords = matchRegexp(["and","break","elseif","false","nil","not","or","return",
|
||||
"true","function", "end", "if", "then", "else", "do",
|
||||
"while", "repeat", "until", "for", "in", "local" ]);
|
||||
|
||||
var luaIndentKeys = matchRegexp(["function", "if","repeat","for","while", "[\(]", "{"]);
|
||||
var luaUnindentKeys = matchRegexp(["end", "until", "[\)]", "}"]);
|
||||
|
||||
var luaUnindentKeys2 = findFirstRegexp(["end", "until", "[\)]", "}"]);
|
||||
var luaMiddleKeys = findFirstRegexp(["else","elseif"]);
|
||||
|
||||
|
||||
|
||||
var LUAParser = Editor.Parser = (function() {
|
||||
var tokenizeLUA = (function() {
|
||||
function normal(source, setState) {
|
||||
var ch = source.next();
|
||||
|
||||
if (ch == "-" && source.equals("-")) {
|
||||
source.next();
|
||||
setState(inSLComment);
|
||||
return null;
|
||||
}
|
||||
else if (ch == "\"" || ch == "'") {
|
||||
setState(inString(ch));
|
||||
return null;
|
||||
}
|
||||
if (ch == "[" && (source.equals("[") || source.equals("="))) {
|
||||
var level = 0;
|
||||
while(source.equals("=")){
|
||||
level ++;
|
||||
source.next();
|
||||
}
|
||||
if(! source.equals("[") )
|
||||
return "lua-error";
|
||||
setState(inMLSomething(level,"lua-string"));
|
||||
return null;
|
||||
}
|
||||
|
||||
else if (ch == "=") {
|
||||
if (source.equals("="))
|
||||
source.next();
|
||||
return "lua-token";
|
||||
}
|
||||
|
||||
else if (ch == ".") {
|
||||
if (source.equals("."))
|
||||
source.next();
|
||||
if (source.equals("."))
|
||||
source.next();
|
||||
return "lua-token";
|
||||
}
|
||||
|
||||
else if (ch == "+" || ch == "-" || ch == "*" || ch == "/" || ch == "%" || ch == "^" || ch == "#" ) {
|
||||
return "lua-token";
|
||||
}
|
||||
else if (ch == ">" || ch == "<" || ch == "(" || ch == ")" || ch == "{" || ch == "}" || ch == "[" ) {
|
||||
return "lua-token";
|
||||
}
|
||||
else if (ch == "]" || ch == ";" || ch == ":" || ch == ",") {
|
||||
return "lua-token";
|
||||
}
|
||||
else if (source.equals("=") && (ch == "~" || ch == "<" || ch == ">")) {
|
||||
source.next();
|
||||
return "lua-token";
|
||||
}
|
||||
|
||||
else if (/\d/.test(ch)) {
|
||||
source.nextWhileMatches(/[\w.%]/);
|
||||
return "lua-number";
|
||||
}
|
||||
else {
|
||||
source.nextWhileMatches(/[\w\\\-_.]/);
|
||||
return "lua-identifier";
|
||||
}
|
||||
}
|
||||
|
||||
function inSLComment(source, setState) {
|
||||
var start = true;
|
||||
var count=0;
|
||||
while (!source.endOfLine()) {
|
||||
var ch = source.next();
|
||||
var level = 0;
|
||||
if ((ch =="[") && start)
|
||||
while(source.equals("=")){
|
||||
source.next();
|
||||
level++;
|
||||
}
|
||||
if (source.equals("[")){
|
||||
setState(inMLSomething(level,"lua-comment"));
|
||||
return null;
|
||||
}
|
||||
start = false;
|
||||
}
|
||||
setState(normal);
|
||||
return "lua-comment";
|
||||
|
||||
}
|
||||
|
||||
function inMLSomething(level,what) {
|
||||
//wat sholud be "lua-string" or "lua-comment", level is the number of "=" in opening mark.
|
||||
return function(source, setState){
|
||||
var dashes = 0;
|
||||
while (!source.endOfLine()) {
|
||||
var ch = source.next();
|
||||
if (dashes == level+1 && ch == "]" ) {
|
||||
setState(normal);
|
||||
break;
|
||||
}
|
||||
if (dashes == 0)
|
||||
dashes = (ch == "]") ? 1:0;
|
||||
else
|
||||
dashes = (ch == "=") ? dashes + 1 : 0;
|
||||
}
|
||||
return what;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function inString(quote) {
|
||||
return function(source, setState) {
|
||||
var escaped = false;
|
||||
while (!source.endOfLine()) {
|
||||
var ch = source.next();
|
||||
if (ch == quote && !escaped)
|
||||
break;
|
||||
escaped = !escaped && ch == "\\";
|
||||
}
|
||||
if (!escaped)
|
||||
setState(normal);
|
||||
return "lua-string";
|
||||
};
|
||||
}
|
||||
|
||||
return function(source, startState) {
|
||||
return tokenizer(source, startState || normal);
|
||||
};
|
||||
})();
|
||||
|
||||
function indentLUA(indentDepth, base) {
|
||||
return function(nextChars) {
|
||||
|
||||
var closing = (luaUnindentKeys2.test(nextChars) || luaMiddleKeys.test(nextChars));
|
||||
|
||||
|
||||
return base + ( indentUnit * (indentDepth - (closing?1:0)) );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function parseLUA(source,basecolumn) {
|
||||
basecolumn = basecolumn || 0;
|
||||
|
||||
var tokens = tokenizeLUA(source);
|
||||
var indentDepth = 0;
|
||||
|
||||
var iter = {
|
||||
next: function() {
|
||||
var token = tokens.next(), style = token.style, content = token.content;
|
||||
|
||||
|
||||
|
||||
if (style == "lua-identifier" && luaKeywords.test(content)){
|
||||
token.style = "lua-keyword";
|
||||
}
|
||||
if (style == "lua-identifier" && luaStdFunctions.test(content)){
|
||||
token.style = "lua-stdfunc";
|
||||
}
|
||||
if (style == "lua-identifier" && luaCustomFunctions.test(content)){
|
||||
token.style = "lua-customfunc";
|
||||
}
|
||||
|
||||
if (luaIndentKeys.test(content))
|
||||
indentDepth++;
|
||||
else if (luaUnindentKeys.test(content))
|
||||
indentDepth--;
|
||||
|
||||
|
||||
if (content == "\n")
|
||||
token.indentation = indentLUA( indentDepth, basecolumn);
|
||||
|
||||
return token;
|
||||
},
|
||||
|
||||
copy: function() {
|
||||
var _tokenState = tokens.state, _indentDepth = indentDepth;
|
||||
return function(source) {
|
||||
tokens = tokenizeLUA(source, _tokenState);
|
||||
|
||||
indentDepth = _indentDepth;
|
||||
return iter;
|
||||
};
|
||||
}
|
||||
};
|
||||
return iter;
|
||||
}
|
||||
|
||||
return {make: parseLUA, configure:configureLUA, electricChars: "delf})"}; //en[d] els[e] unti[l] elsei[f] // this should be taken from Keys keywords
|
||||
})();
|
||||
|
||||
37
media/CodeMirror-0.62/contrib/php/LICENSE
Normal file
37
media/CodeMirror-0.62/contrib/php/LICENSE
Normal file
@@ -0,0 +1,37 @@
|
||||
Copyright (c) 2008-2009, Yahoo! Inc.
|
||||
All rights reserved.
|
||||
|
||||
This software is provided for use in connection with the
|
||||
CodeMirror suite of modules and utilities, hosted and maintained
|
||||
at http://marijn.haverbeke.nl/codemirror/.
|
||||
|
||||
Redistribution and use of this software 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 Yahoo! Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of Yahoo! Inc.
|
||||
|
||||
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 THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||
110
media/CodeMirror-0.62/contrib/php/css/phpcolors.css
Normal file
110
media/CodeMirror-0.62/contrib/php/css/phpcolors.css
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed by
|
||||
Yahoo! Inc. under the BSD (revised) open source license
|
||||
|
||||
@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
|
||||
*/
|
||||
|
||||
.editbox {
|
||||
margin: .4em;
|
||||
padding: 0;
|
||||
font-family: monospace;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
/*We should define specific styles for every element of the syntax.
|
||||
the setting below will cause some annoying color to show through if we missed
|
||||
defining a style for a token. This is also the "color" of the whitespace and
|
||||
of the cursor.
|
||||
*/
|
||||
pre.code, .editbox {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.editbox p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
span.php-punctuation {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
span.php-keyword {
|
||||
color: #770088;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.php-operator {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
/* __FILE__ etc.; http://php.net/manual/en/reserved.php */
|
||||
span.php-compile-time-constant {
|
||||
color: #776088;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* output of get_defined_constants(). Differs from http://php.net/manual/en/reserved.constants.php */
|
||||
span.php-predefined-constant {
|
||||
color: darkgreen;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* PHP reserved "language constructs"... echo() etc.; http://php.net/manual/en/reserved.php */
|
||||
span.php-reserved-language-construct {
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* PHP built-in functions: glob(), chr() etc.; output of get_defined_functions()["internal"] */
|
||||
span.php-predefined-function {
|
||||
color: green;
|
||||
}
|
||||
|
||||
/* PHP predefined classes: PDO, Exception etc.; output of get_declared_classes() and different from http://php.net/manual/en/reserved.classes.php */
|
||||
span.php-predefined-class {
|
||||
color: green;
|
||||
}
|
||||
|
||||
span.php-atom {
|
||||
color: #228811;
|
||||
}
|
||||
|
||||
/* class, interface, namespace or function names, but not $variables */
|
||||
span.php-t_string {
|
||||
color: black;
|
||||
}
|
||||
|
||||
span.php-variable {
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
span.js-localvariable {
|
||||
color: #004499;
|
||||
}
|
||||
|
||||
span.php-comment {
|
||||
color: #AA7700;
|
||||
font-stretch: condensed;
|
||||
/* font-style: italic; This causes line height to slightly change, getting line numbers out of sync */
|
||||
}
|
||||
|
||||
span.php-string-single-quoted {
|
||||
color: #AA2222;
|
||||
}
|
||||
/* double quoted strings allow interpolation */
|
||||
span.php-string-double-quoted {
|
||||
color: #AA2222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.syntax-error {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
span.deprecated {
|
||||
font-size: smaller;
|
||||
}
|
||||
292
media/CodeMirror-0.62/contrib/php/index.html
Normal file
292
media/CodeMirror-0.62/contrib/php/index.html
Normal file
@@ -0,0 +1,292 @@
|
||||
<!--
|
||||
Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed by
|
||||
Yahoo! Inc. under the BSD (revised) open source license
|
||||
|
||||
@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script src="../../js/codemirror.js" type="text/javascript"></script>
|
||||
<title>CodeMirror: PHP+HTML+JavaScript+CSS mixed-mode demonstration</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../css/docs.css"/>
|
||||
</head>
|
||||
<body style="padding: 20px;">
|
||||
|
||||
<p>This is a complex demonstration of the <b>PHP+HTML+JavaScript+CSS mixed-mode
|
||||
syntax highlight</b> capabilities of <a href="../../index.html">CodeMirror</a>.
|
||||
<?php ... ?> tags use the PHP parser, <script> tags use the JavaScript
|
||||
parser, and <style> tags use the CSS parser. The rest of the content is
|
||||
parsed using the XML parser in HTML mode.</p>
|
||||
|
||||
<p>Features of the PHP parser:
|
||||
<ul>
|
||||
<li>special "deprecated" style for PHP4 keywords like 'var'
|
||||
<li>support for PHP 5.3 keywords: 'namespace', 'use'
|
||||
<li>911 predefined constants, 1301 predefined functions, 105 predeclared classes
|
||||
from a typical PHP installation in a LAMP environment
|
||||
<li>new feature: syntax error flagging, thus enabling strict parsing of:
|
||||
<ol>
|
||||
<li>function definitions with explicitly or implicitly typed arguments and default values
|
||||
<li>modifiers (public, static etc.) applied to method and member definitions
|
||||
<li>foreach(array_expression as $key [=> $value]) loops
|
||||
</ol>
|
||||
<li>differentiation between single-quoted strings and double-quoted interpolating strings
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<div style="border: 1px solid black; padding: 3px; background-color: #F8F8F8">
|
||||
<textarea id="code" cols="120" rows="30">
|
||||
The "root" parser is XML in HTML mode.
|
||||
Next, we can switch into PHP mode, for example. This is
|
||||
<?php echo 'text output by';
|
||||
?>
|
||||
PHP. </b>
|
||||
On the line above, we just had an XML syntax error due to the </b> tag not being opened.
|
||||
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> HTML text will follow
|
||||
<html>
|
||||
<head>
|
||||
<title>Similarly, the 'script' tag will switch to the JavaScript parser:</title>
|
||||
<script type="text/javascript">
|
||||
// Press enter inside the object and your new line will be suitably
|
||||
// indented.
|
||||
var keyBindings = {
|
||||
enter: "newline-and-indent",
|
||||
tab: "reindent-selection",
|
||||
ctrl_enter: "reparse-buffer",
|
||||
ctrl_z: "undo",
|
||||
ctrl_y: "redo",
|
||||
ctrl_backspace: "undo-for-safari-which-stupidly-enough-blocks-ctrl-z"
|
||||
};
|
||||
|
||||
// Press tab on the next line and the wrong indentation will be fixed.
|
||||
var regex = /foo|bar/i;
|
||||
|
||||
function example(x) {
|
||||
// Local variables get a different colour than global ones.
|
||||
var y = 44.4;
|
||||
return x + y - z;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
/* Some example CSS */
|
||||
|
||||
@import url("something.css");
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 3em 6em;
|
||||
font-family: tahoma, arial, sans-serif;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#navigation a {
|
||||
font-weight: bold;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h1:before, h2:before {
|
||||
content: "::";
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: courier, monospace;
|
||||
font-size: 80%;
|
||||
color: #418A8A;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
The PHP code below contains some deliberate errors. Play with the editor by fixing them
|
||||
and observing how the highlight changes.
|
||||
|
||||
<?php
|
||||
namespace A;
|
||||
namespace A::B::C;
|
||||
namespace A::::B;
|
||||
namespace A::B::C::;
|
||||
namespace A::B::C::D x;
|
||||
self::range($row['lft'], $row['rgt'])); // error: extra ')'
|
||||
$a = (b() + 4) 5 foo; // error: missing operators
|
||||
self::$var;
|
||||
$parent = self::range($max + 1, $max + 1);
|
||||
$row[attributes][$attribute_name] = $attribute_value;
|
||||
$row[attributes()][$attribute_name] = $attribute_value;
|
||||
$row[attributes(5)][$attribute_name] = $attribute_value;
|
||||
$row[$attributes()][$attribute_name] = $attribute_value;
|
||||
abstract class 5 extends foo implements echo {
|
||||
private function domainObjectBuilder() {
|
||||
return $this->use_domain_object_builder
|
||||
? $this->domain()->objectBuilder()
|
||||
: null;
|
||||
}
|
||||
|
||||
const $myconst = 'some string';
|
||||
$array[myconst] = 4;
|
||||
// this is a single-line C++-style comment
|
||||
# this is a single-line shell-style comment
|
||||
private var $a = __FILE__;
|
||||
protected static $b = timezone_transitions_get('some parameter here');
|
||||
global $g = isset("string");
|
||||
static $s = hash_update_file; // warning: predefined function non-call
|
||||
function mike ($var) $foo;
|
||||
mike(A::func(param));
|
||||
func($b $c); // error: function parameters must be comma-separated
|
||||
foo bar; // error: no operator
|
||||
$baz $quux; // error: no operator
|
||||
public abstract function loadPageXML(util_FilePath $filename, $merge=0+$foo, $x, $y=3) {
|
||||
$newrow[$key] = $val;
|
||||
$newresult[] = $row;
|
||||
$state = $row['c'] == 1;
|
||||
$attribute_values[$attribute_name] = null;
|
||||
$row['attributes'][$attribute_name] = $attribute_value;
|
||||
$result[$row['element']][$row['attribute']] = $row['value'];
|
||||
$sql = "multiline string
|
||||
line2 is special - it'll interpolate variables like $state and method calls
|
||||
{$this->cache->add($key, 5)} and maybe \"more\"
|
||||
|
||||
line5";
|
||||
$sql = 'multiline string
|
||||
single quoting means no \'interpolation\' like "$start" or method call
|
||||
{$this->cache->add($key, 5)} will happen
|
||||
|
||||
line5';
|
||||
$bitpattern = 1 << 2;
|
||||
$bitpattern <<= 3;
|
||||
$incorrect = <<< 5 EOSTRING // FIXME: CodeMirror update bug: add a letter before 5 and notice that syntax is not updated until EOF, even with continuousScanning: 500
|
||||
error: the identifier must conform to the identifier rules
|
||||
EOSTRING;
|
||||
$sql = <<< EOSQL
|
||||
SELECT attribute, element, value
|
||||
FROM attribute_values
|
||||
WHERE dimension = ?
|
||||
EOSQL;
|
||||
$this->lr_cache->add($key, self::range($row['lft'], $row['rgt']));
|
||||
$composite_string = <<<EOSTRING
|
||||
some lines here
|
||||
EOSTRING
|
||||
. 'something extra';
|
||||
$page_lft = ($domain->name() == 'page') ? $start + 1 : $page_start + 1;
|
||||
echo "This is class foo";
|
||||
echo "a = ".$this ->a[2+3*$array["foo"]]."";
|
||||
echo "b = {$this->b}"; // FIXME: highlight interpolation in strings
|
||||
}
|
||||
final function makecoffee error($types = array("cappuccino"), $coffeeMaker = NULL) {
|
||||
$out_of_way_amount = $max - $child->left() + 1;
|
||||
$absolute_pos = $child->left() - $move->width();
|
||||
$varfunc(1, 'x');
|
||||
$varfunc(1, 'x') + foo() - 5;
|
||||
$funcarray[$i]('param1', $param2);
|
||||
$lr[$domain_name] = $this->get_left_and_right($domain,
|
||||
$dimension_name,
|
||||
$element_name);
|
||||
$domain_list = is_null($domain) ?
|
||||
r3_Domain::names() :
|
||||
array($domain->name());
|
||||
foreach (r3_Domain::names() as $domain_name) {
|
||||
$placeholders = 'distance LIKE '
|
||||
. implode(array_fill(1, $num_distances, '?'),
|
||||
' OR distance LIKE ');
|
||||
|
||||
}
|
||||
return $this->target*$this->trans+myfunc(__METHOD__);
|
||||
/*
|
||||
echo 'This is a test'; /* This comment will cause a problem */
|
||||
*/
|
||||
}
|
||||
switch( $type ) {
|
||||
case "r3core_AddTemplateToTargetEvent":
|
||||
$this->notifyAddTemplateToTarget( $genevent );
|
||||
break;
|
||||
case "r3core_GenerateTargetEvent" $this:
|
||||
for($i=0; $i<=this->method(); $i++) {
|
||||
echo 'Syntax "highlighting"';
|
||||
}
|
||||
try {
|
||||
foreach($array xor $loader->parse_fn($filename) as $key => value) {
|
||||
namespace r3;
|
||||
}
|
||||
} catch( Exception $e ) {
|
||||
/** restore the backup
|
||||
*/
|
||||
$this->loadAll($tmp, $event, true);
|
||||
// `php -l` doesn't complain at all at this (it assumes string constants):
|
||||
this + makes * no - sense;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default moo:
|
||||
throw new r3_util_Exception( get_class( $genevent ) . " does not map" );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
?>
|
||||
|
||||
<r3:cphp>
|
||||
php("works", $here, 2);
|
||||
</r3:cphp>
|
||||
|
||||
<r4:cphp>
|
||||
class foo {
|
||||
// a comment
|
||||
var $a;
|
||||
var $b;
|
||||
};
|
||||
</r4:cphp>
|
||||
|
||||
<h1>This is an <?php # echo 'simple';?> example.</h1>
|
||||
<p>The header above will say 'This is an example'.</p>
|
||||
<h1>This is an <?php // echo 'simple';?> example.</h1>
|
||||
|
||||
<?php echo; ?>
|
||||
<body>
|
||||
|
||||
<?php echo "<html>
|
||||
<head>
|
||||
<script>
|
||||
var foo = 'bar';
|
||||
</script>
|
||||
<style>
|
||||
span.test {font-family: arial, 'lucida console', sans-serif}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- comment -->
|
||||
</body>
|
||||
</html>"; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var editor = CodeMirror.fromTextArea('code', {
|
||||
height: "350px",
|
||||
parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js",
|
||||
"../contrib/php/js/tokenizephp.js", "../contrib/php/js/parsephp.js",
|
||||
"../contrib/php/js/parsephphtmlmixed.js"],
|
||||
stylesheet: ["../../css/xmlcolors.css", "../../css/jscolors.css", "../../css/csscolors.css", "css/phpcolors.css"],
|
||||
path: "../../js/",
|
||||
continuousScanning: 500
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
371
media/CodeMirror-0.62/contrib/php/js/parsephp.js
Normal file
371
media/CodeMirror-0.62/contrib/php/js/parsephp.js
Normal file
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed by
|
||||
Yahoo! Inc. under the BSD (revised) open source license
|
||||
|
||||
@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
|
||||
|
||||
|
||||
Parse function for PHP. Makes use of the tokenizer from tokenizephp.js.
|
||||
Based on parsejavascript.js by Marijn Haverbeke.
|
||||
|
||||
|
||||
Features:
|
||||
+ special "deprecated" style for PHP4 keywords like 'var'
|
||||
+ support for PHP 5.3 keywords: 'namespace', 'use'
|
||||
+ 911 predefined constants, 1301 predefined functions, 105 predeclared classes
|
||||
from a typical PHP installation in a LAMP environment
|
||||
+ new feature: syntax error flagging, thus enabling strict parsing of:
|
||||
+ function definitions with explicitly or implicitly typed arguments and default values
|
||||
+ modifiers (public, static etc.) applied to method and member definitions
|
||||
+ foreach(array_expression as $key [=> $value]) loops
|
||||
+ differentiation between single-quoted strings and double-quoted interpolating strings
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// add the Array.indexOf method for JS engines that don't support it (e.g. IE)
|
||||
// code from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array/IndexOf
|
||||
if (!Array.prototype.indexOf)
|
||||
{
|
||||
Array.prototype.indexOf = function(elt /*, from*/)
|
||||
{
|
||||
var len = this.length;
|
||||
|
||||
var from = Number(arguments[1]) || 0;
|
||||
from = (from < 0)
|
||||
? Math.ceil(from)
|
||||
: Math.floor(from);
|
||||
if (from < 0)
|
||||
from += len;
|
||||
|
||||
for (; from < len; from++)
|
||||
{
|
||||
if (from in this &&
|
||||
this[from] === elt)
|
||||
return from;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var PHPParser = Editor.Parser = (function() {
|
||||
// Token types that can be considered to be atoms, part of operator expressions
|
||||
var atomicTypes = {
|
||||
"atom": true, "number": true, "variable": true, "string": true
|
||||
};
|
||||
// Constructor for the lexical context objects.
|
||||
function PHPLexical(indented, column, type, align, prev, info) {
|
||||
// indentation at start of this line
|
||||
this.indented = indented;
|
||||
// column at which this scope was opened
|
||||
this.column = column;
|
||||
// type of scope ('stat' (statement), 'form' (special form), '[', '{', or '(')
|
||||
this.type = type;
|
||||
// '[', '{', or '(' blocks that have any text after their opening
|
||||
// character are said to be 'aligned' -- any lines below are
|
||||
// indented all the way to the opening character.
|
||||
if (align != null)
|
||||
this.align = align;
|
||||
// Parent scope, if any.
|
||||
this.prev = prev;
|
||||
this.info = info;
|
||||
};
|
||||
|
||||
// PHP indentation rules
|
||||
function indentPHP(lexical) {
|
||||
return function(firstChars) {
|
||||
var firstChar = firstChars && firstChars.charAt(0), type = lexical.type;
|
||||
var closing = firstChar == type;
|
||||
if (type == "form" && firstChar == "{")
|
||||
return lexical.indented;
|
||||
else if (type == "stat" || type == "form")
|
||||
return lexical.indented + indentUnit;
|
||||
else if (lexical.info == "switch" && !closing)
|
||||
return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit);
|
||||
else if (lexical.align)
|
||||
return lexical.column - (closing ? 1 : 0);
|
||||
else
|
||||
return lexical.indented + (closing ? 0 : indentUnit);
|
||||
};
|
||||
};
|
||||
|
||||
// The parser-iterator-producing function itself.
|
||||
function parsePHP(input, basecolumn) {
|
||||
// Wrap the input in a token stream
|
||||
var tokens = tokenizePHP(input);
|
||||
// The parser state. cc is a stack of actions that have to be
|
||||
// performed to finish the current statement. For example we might
|
||||
// know that we still need to find a closing parenthesis and a
|
||||
// semicolon. Actions at the end of the stack go first. It is
|
||||
// initialized with an infinitely looping action that consumes
|
||||
// whole statements.
|
||||
var cc = [statements];
|
||||
// The lexical scope, used mostly for indentation.
|
||||
var lexical = new PHPLexical((basecolumn || 0) - indentUnit, 0, "block", false);
|
||||
// Current column, and the indentation at the start of the current
|
||||
// line. Used to create lexical scope objects.
|
||||
var column = 0;
|
||||
var indented = 0;
|
||||
// Variables which are used by the mark, cont, and pass functions
|
||||
// below to communicate with the driver loop in the 'next' function.
|
||||
var consume, marked;
|
||||
|
||||
// The iterator object.
|
||||
var parser = {next: next, copy: copy};
|
||||
|
||||
// parsing is accomplished by calling next() repeatedly
|
||||
function next(){
|
||||
// Start by performing any 'lexical' actions (adjusting the
|
||||
// lexical variable), or the operations below will be working
|
||||
// with the wrong lexical state.
|
||||
while(cc[cc.length - 1].lex)
|
||||
cc.pop()();
|
||||
|
||||
// Fetch the next token.
|
||||
var token = tokens.next();
|
||||
|
||||
// Adjust column and indented.
|
||||
if (token.type == "whitespace" && column == 0)
|
||||
indented = token.value.length;
|
||||
column += token.value.length;
|
||||
if (token.content == "\n"){
|
||||
indented = column = 0;
|
||||
// If the lexical scope's align property is still undefined at
|
||||
// the end of the line, it is an un-aligned scope.
|
||||
if (!("align" in lexical))
|
||||
lexical.align = false;
|
||||
// Newline tokens get an indentation function associated with
|
||||
// them.
|
||||
token.indentation = indentPHP(lexical);
|
||||
}
|
||||
// No more processing for meaningless tokens.
|
||||
if (token.type == "whitespace" || token.type == "comment"
|
||||
|| token.type == "string_not_terminated" )
|
||||
return token;
|
||||
// When a meaningful token is found and the lexical scope's
|
||||
// align is undefined, it is an aligned scope.
|
||||
if (!("align" in lexical))
|
||||
lexical.align = true;
|
||||
|
||||
// Execute actions until one 'consumes' the token and we can
|
||||
// return it. 'marked' is used to change the style of the current token.
|
||||
while(true) {
|
||||
consume = marked = false;
|
||||
// Take and execute the topmost action.
|
||||
var action = cc.pop();
|
||||
action(token);
|
||||
|
||||
if (consume){
|
||||
if (marked)
|
||||
token.style = marked;
|
||||
// Here we differentiate between local and global variables.
|
||||
return token;
|
||||
}
|
||||
}
|
||||
return 1; // Firebug workaround for http://code.google.com/p/fbug/issues/detail?id=1239#c1
|
||||
}
|
||||
|
||||
// This makes a copy of the parser state. It stores all the
|
||||
// stateful variables in a closure, and returns a function that
|
||||
// will restore them when called with a new input stream. Note
|
||||
// that the cc array has to be copied, because it is contantly
|
||||
// being modified. Lexical objects are not mutated, so they can
|
||||
// be shared between runs of the parser.
|
||||
function copy(){
|
||||
var _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state;
|
||||
|
||||
return function copyParser(input){
|
||||
lexical = _lexical;
|
||||
cc = _cc.concat([]); // copies the array
|
||||
column = indented = 0;
|
||||
tokens = tokenizePHP(input, _tokenState);
|
||||
return parser;
|
||||
};
|
||||
}
|
||||
|
||||
// Helper function for pushing a number of actions onto the cc
|
||||
// stack in reverse order.
|
||||
function push(fs){
|
||||
for (var i = fs.length - 1; i >= 0; i--)
|
||||
cc.push(fs[i]);
|
||||
}
|
||||
// cont and pass are used by the action functions to add other
|
||||
// actions to the stack. cont will cause the current token to be
|
||||
// consumed, pass will leave it for the next action.
|
||||
function cont(){
|
||||
push(arguments);
|
||||
consume = true;
|
||||
}
|
||||
function pass(){
|
||||
push(arguments);
|
||||
consume = false;
|
||||
}
|
||||
// Used to change the style of the current token.
|
||||
function mark(style){
|
||||
marked = style;
|
||||
}
|
||||
// Add a lyer of style to the current token, for example syntax-error
|
||||
function mark_add(style){
|
||||
marked = marked + ' ' + style;
|
||||
}
|
||||
|
||||
// Push a new lexical context of the given type.
|
||||
function pushlex(type, info) {
|
||||
var result = function pushlexing() {
|
||||
lexical = new PHPLexical(indented, column, type, null, lexical, info)
|
||||
};
|
||||
result.lex = true;
|
||||
return result;
|
||||
}
|
||||
// Pop off the current lexical context.
|
||||
function poplex(){
|
||||
lexical = lexical.prev;
|
||||
}
|
||||
poplex.lex = true;
|
||||
// The 'lex' flag on these actions is used by the 'next' function
|
||||
// to know they can (and have to) be ran before moving on to the
|
||||
// next token.
|
||||
|
||||
// Creates an action that discards tokens until it finds one of
|
||||
// the given type. This will ignore (and recover from) syntax errors.
|
||||
function expect(wanted){
|
||||
return function expecting(token){
|
||||
if (token.type == wanted) cont(); // consume the token
|
||||
else {
|
||||
cont(arguments.callee); // continue expecting() - call itself
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Require a specific token type, or one of the tokens passed in the 'wanted' array
|
||||
// Used to detect blatant syntax errors. 'execute' is used to pass extra code
|
||||
// to be executed if the token is matched. For example, a '(' match could
|
||||
// 'execute' a cont( compasep(funcarg), require(")") )
|
||||
function require(wanted, execute){
|
||||
return function requiring(token){
|
||||
var ok;
|
||||
var type = token.type;
|
||||
if (typeof(wanted) == "string")
|
||||
ok = (type == wanted) -1;
|
||||
else
|
||||
ok = wanted.indexOf(type);
|
||||
if (ok >= 0) {
|
||||
if (execute && typeof(execute[ok]) == "function")
|
||||
execute[ok](token);
|
||||
cont(); // just consume the token
|
||||
}
|
||||
else {
|
||||
if (!marked) mark(token.style);
|
||||
mark_add("syntax-error");
|
||||
cont(arguments.callee);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Looks for a statement, and then calls itself.
|
||||
function statements(token){
|
||||
return pass(statement, statements);
|
||||
}
|
||||
// Dispatches various types of statements based on the type of the current token.
|
||||
function statement(token){
|
||||
var type = token.type;
|
||||
if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex);
|
||||
else if (type == "keyword b") cont(pushlex("form"), statement, poplex);
|
||||
else if (type == "{") cont(pushlex("}"), block, poplex);
|
||||
else if (type == "function") funcdef();
|
||||
// technically, "class implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function
|
||||
else if (type == "class") cont(require("t_string"), expect("{"), pushlex("}"), block, poplex);
|
||||
else if (type == "foreach") cont(pushlex("form"), require("("), pushlex(")"), expression, require("as"), require("variable"), /* => $value */ expect(")"), poplex, statement, poplex);
|
||||
else if (type == "for") cont(pushlex("form"), require("("), pushlex(")"), expression, require(";"), expression, require(";"), expression, require(")"), poplex, statement, poplex);
|
||||
// public final function foo(), protected static $bar;
|
||||
else if (type == "modifier") cont(require(["modifier", "variable", "function"], [null, null, funcdef]));
|
||||
else if (type == "switch") cont(pushlex("form"), require("("), expression, require(")"), pushlex("}", "switch"), require([":", "{"]), block, poplex, poplex);
|
||||
else if (type == "case") cont(expression, require(":"));
|
||||
else if (type == "default") cont(require(":"));
|
||||
else if (type == "catch") cont(pushlex("form"), require("("), require("t_string"), require("variable"), require(")"), statement, poplex);
|
||||
else if (type == "const") cont(require("t_string")); // 'const static x=5' is a syntax error
|
||||
// technically, "namespace implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function
|
||||
else if (type == "namespace") cont(namespacedef, require(";"));
|
||||
// $variables may be followed by operators, () for variable function calls, or [] subscripts
|
||||
else pass(pushlex("stat"), expression, require(";"), poplex);
|
||||
}
|
||||
// Dispatch expression types.
|
||||
function expression(token){
|
||||
var type = token.type;
|
||||
if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator);
|
||||
else if (type == "<<<") cont(require("string"), maybeoperator); // heredoc/nowdoc
|
||||
else if (type == "t_string") cont(maybe_double_colon, maybeoperator);
|
||||
else if (type == "keyword c") cont(expression);
|
||||
// function call or parenthesized expression: $a = ($b + 1) * 2;
|
||||
else if (type == "(") cont(pushlex(")"), commasep(expression), require(")"), poplex, maybeoperator);
|
||||
else if (type == "operator") cont(expression);
|
||||
}
|
||||
// Called for places where operators, function calls, or subscripts are
|
||||
// valid. Will skip on to the next action if none is found.
|
||||
function maybeoperator(token){
|
||||
var type = token.type;
|
||||
if (type == "operator") {
|
||||
if (token.content == "?") cont(expression, require(":"), expression); // ternary operator
|
||||
else cont(expression);
|
||||
}
|
||||
else if (type == "(") cont(pushlex(")"), expression, commasep(expression), require(")"), poplex, maybeoperator /* $varfunc() + 3 */);
|
||||
else if (type == "[") cont(pushlex("]"), expression, require("]"), maybeoperator /* for multidimensional arrays, or $func[$i]() */, poplex);
|
||||
}
|
||||
// A regular use of the double colon to specify a class, as in self::func() or myclass::$var;
|
||||
// Differs from `namespace` or `use` in that only one class can be the parent; chains (A::B::$var) are a syntax error.
|
||||
function maybe_double_colon(token) {
|
||||
if (token.type == "t_double_colon")
|
||||
// A::$var, A::func(), A::const
|
||||
cont(require(["t_string", "variable"]), maybeoperator);
|
||||
else {
|
||||
// a t_string wasn't followed by ::, such as in a function call: foo()
|
||||
pass(expression)
|
||||
}
|
||||
}
|
||||
// the declaration or definition of a function
|
||||
function funcdef() {
|
||||
cont(require("t_string"), require("("), pushlex(")"), commasep(funcarg), require(")"), poplex, block);
|
||||
}
|
||||
// Parses a comma-separated list of the things that are recognized
|
||||
// by the 'what' argument.
|
||||
function commasep(what){
|
||||
function proceed(token) {
|
||||
if (token.type == ",") cont(what, proceed);
|
||||
};
|
||||
return function commaSeparated() {
|
||||
pass(what, proceed);
|
||||
};
|
||||
}
|
||||
// Look for statements until a closing brace is found.
|
||||
function block(token) {
|
||||
if (token.type == "}") cont();
|
||||
else pass(statement, block);
|
||||
}
|
||||
function maybedefaultparameter(token){
|
||||
if (token.content == "=") cont(expression);
|
||||
}
|
||||
// support for default arguments: http://us.php.net/manual/en/functions.arguments.php#functions.arguments.default
|
||||
function funcarg(token){
|
||||
// function foo(myclass $obj) {...}
|
||||
if (token.type == "t_string") cont(require("variable"), maybedefaultparameter);
|
||||
// function foo($string) {...}
|
||||
else if (token.type == "variable") cont(maybedefaultparameter);
|
||||
}
|
||||
|
||||
// A namespace definition or use
|
||||
function maybe_double_colon_def(token) {
|
||||
if (token.type == "t_double_colon")
|
||||
cont(namespacedef);
|
||||
}
|
||||
function namespacedef(token) {
|
||||
pass(require("t_string"), maybe_double_colon_def);
|
||||
}
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
return {make: parsePHP, electricChars: "{}:"};
|
||||
|
||||
})();
|
||||
90
media/CodeMirror-0.62/contrib/php/js/parsephphtmlmixed.js
Normal file
90
media/CodeMirror-0.62/contrib/php/js/parsephphtmlmixed.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed by
|
||||
Yahoo! Inc. under the BSD (revised) open source license
|
||||
|
||||
@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
|
||||
|
||||
Based on parsehtmlmixed.js by Marijn Haverbeke.
|
||||
*/
|
||||
|
||||
var PHPHTMLMixedParser = Editor.Parser = (function() {
|
||||
if (!(PHPParser && CSSParser && JSParser && XMLParser))
|
||||
throw new Error("PHP, CSS, JS, and XML parsers must be loaded for PHP+HTML mixed mode to work.");
|
||||
XMLParser.configure({useHTMLKludges: true});
|
||||
|
||||
function parseMixed(stream) {
|
||||
var htmlParser = XMLParser.make(stream), localParser = null, inTag = false;
|
||||
var iter = {next: top, copy: copy};
|
||||
|
||||
function top() {
|
||||
var token = htmlParser.next();
|
||||
if (token.content == "<")
|
||||
inTag = true;
|
||||
else if (token.style == "xml-tagname" && inTag === true)
|
||||
inTag = token.content.toLowerCase();
|
||||
else if (token.type == "xml-processing") {
|
||||
// dispatch on PHP
|
||||
if (token.content == "<?php")
|
||||
iter.next = local(PHPParser, "?>");
|
||||
}
|
||||
// "xml-processing" tokens are ignored, because they should be handled by a specific local parser
|
||||
else if (token.content == ">") {
|
||||
if (inTag == "script")
|
||||
iter.next = local(JSParser, "</script");
|
||||
else if (inTag == "style")
|
||||
iter.next = local(CSSParser, "</style");
|
||||
inTag = false;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
function local(parser, tag) {
|
||||
var baseIndent = htmlParser.indentation();
|
||||
localParser = parser.make(stream, baseIndent + indentUnit);
|
||||
return function() {
|
||||
if (stream.lookAhead(tag, false, false, true)) {
|
||||
localParser = null;
|
||||
iter.next = top;
|
||||
return top(); // pass the ending tag to the enclosing parser
|
||||
}
|
||||
|
||||
var token = localParser.next();
|
||||
var lt = token.value.lastIndexOf("<"), sz = Math.min(token.value.length - lt, tag.length);
|
||||
if (lt != -1 && token.value.slice(lt, lt + sz).toLowerCase() == tag.slice(0, sz) &&
|
||||
stream.lookAhead(tag.slice(sz), false, false, true)) {
|
||||
stream.push(token.value.slice(lt));
|
||||
token.value = token.value.slice(0, lt);
|
||||
}
|
||||
|
||||
if (token.indentation) {
|
||||
var oldIndent = token.indentation;
|
||||
token.indentation = function(chars) {
|
||||
if (chars == "</")
|
||||
return baseIndent;
|
||||
else
|
||||
return oldIndent(chars);
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
};
|
||||
}
|
||||
|
||||
function copy() {
|
||||
var _html = htmlParser.copy(), _local = localParser && localParser.copy(),
|
||||
_next = iter.next, _inTag = inTag;
|
||||
return function(_stream) {
|
||||
stream = _stream;
|
||||
htmlParser = _html(_stream);
|
||||
localParser = _local && _local(_stream);
|
||||
iter.next = _next;
|
||||
inTag = _inTag;
|
||||
return iter;
|
||||
};
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
return {make: parseMixed, electricChars: "{}/:"};
|
||||
|
||||
})();
|
||||
1007
media/CodeMirror-0.62/contrib/php/js/tokenizephp.js
Normal file
1007
media/CodeMirror-0.62/contrib/php/js/tokenizephp.js
Normal file
File diff suppressed because it is too large
Load Diff
32
media/CodeMirror-0.62/contrib/python/LICENSE
Normal file
32
media/CodeMirror-0.62/contrib/python/LICENSE
Normal file
@@ -0,0 +1,32 @@
|
||||
Copyright (c) 2009, Timothy Farrell
|
||||
All rights reserved.
|
||||
|
||||
This software is provided for use in connection with the
|
||||
CodeMirror suite of modules and utilities, hosted and maintained
|
||||
at http://marijn.haverbeke.nl/codemirror/.
|
||||
|
||||
Redistribution and use of this software 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.
|
||||
|
||||
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 THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||
54
media/CodeMirror-0.62/contrib/python/css/pythoncolors.css
Normal file
54
media/CodeMirror-0.62/contrib/python/css/pythoncolors.css
Normal file
@@ -0,0 +1,54 @@
|
||||
.editbox {
|
||||
padding: .4em;
|
||||
margin: 0;
|
||||
font-family: monospace;
|
||||
font-size: 10pt;
|
||||
line-height: 1.1em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
pre.code, .editbox {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.editbox p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
span.py-delimiter, span.py-special {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
span.py-operator {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
span.py-error {
|
||||
background-color: #660000;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
span.py-keyword {
|
||||
color: #770088;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.py-literal {
|
||||
color: #228811;
|
||||
}
|
||||
|
||||
span.py-identifier, span.py-func {
|
||||
color: black;
|
||||
}
|
||||
|
||||
span.py-type, span.py-decorator {
|
||||
color: #0000FF;
|
||||
}
|
||||
|
||||
span.py-comment {
|
||||
color: #AA7700;
|
||||
}
|
||||
|
||||
span.py-string, span.py-bytes, span.py-raw, span.py-unicode {
|
||||
color: #AA2222;
|
||||
}
|
||||
141
media/CodeMirror-0.62/contrib/python/index.html
Normal file
141
media/CodeMirror-0.62/contrib/python/index.html
Normal file
@@ -0,0 +1,141 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script src="../../js/codemirror.js" type="text/javascript"></script>
|
||||
<title>CodeMirror: Python demonstration</title>
|
||||
<style type="text/css">
|
||||
.CodeMirror-line-numbers {
|
||||
width: 2.2em;
|
||||
color: #aaa;
|
||||
background-color: #eee;
|
||||
text-align: right;
|
||||
padding: .4em;
|
||||
margin: 0;
|
||||
font-family: monospace;
|
||||
font-size: 10pt;
|
||||
line-height: 1.1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="padding: 20px;">
|
||||
<p>
|
||||
This is a simple demonstration of the Python syntax highlighting module
|
||||
for <a href="index.html">CodeMirror</a>.
|
||||
</p>
|
||||
<p>
|
||||
Features of this parser include:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Token-based syntax highlighting - currently very little lexical analysis happens. Few lexical errors will be detected.</li>
|
||||
<li>Use the normal indentation mode to enforce regular indentation, otherwise the "shift" indentation mode will give you more flexibility.</li>
|
||||
<li>Parser Options:
|
||||
<ul>
|
||||
<li>pythonVersion (Integer) - 2 or 3 to indicate which version of Python to parse. Default = 2</li>
|
||||
<li>strictErrors (Bool) - true to highlight errors that may not be Python errors but cause confusion for this parser. Default = true</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Written by Timothy Farrell (<a href="LICENSE">license</a>). Special
|
||||
thanks to Adam Brand and Marijn Haverbeke for their help in debugging
|
||||
and providing for this parser.</p>
|
||||
|
||||
<div style="border: 1px solid black; padding: 0px;">
|
||||
<textarea id="code" cols="100" rows="20" style="width:100%">
|
||||
# Literals
|
||||
1234
|
||||
0.0e101
|
||||
.123
|
||||
0b01010011100
|
||||
0o01234567
|
||||
0x0987654321abcdef
|
||||
# Error Literals
|
||||
.0b000
|
||||
0.0e
|
||||
0e
|
||||
|
||||
# String Literals
|
||||
'For\''
|
||||
"God\""
|
||||
"""so loved
|
||||
the world"""
|
||||
'''that he gave
|
||||
his only begotten\' '''
|
||||
'that whosoever believeth \
|
||||
in him'
|
||||
''
|
||||
|
||||
# Identifiers
|
||||
__a__
|
||||
a.b
|
||||
a.b.c
|
||||
# Error Identifiers
|
||||
a.
|
||||
|
||||
# Operators
|
||||
+ - * / % & | ^ ~ < >
|
||||
== != <= >= <> << >> // **
|
||||
and or not in is
|
||||
|
||||
# Delimiters
|
||||
() [] {} , : ` = ; @ . # At-signs and periods require context
|
||||
+= -= *= /= %= &= |= ^=
|
||||
//= >>= <<= **=
|
||||
|
||||
# Keywords
|
||||
as assert break class continue def del elif else except
|
||||
finally for from global if import lambda pass raise
|
||||
return try while with yield
|
||||
|
||||
# Python 2 Keywords (otherwise Identifiers)
|
||||
exec print
|
||||
|
||||
# Python 3 Keywords (otherwise Identifiers)
|
||||
nonlocal
|
||||
|
||||
# Types
|
||||
bool classmethod complex dict enumerate float frozenset int list object
|
||||
property reversed set slice staticmethod str super tuple type
|
||||
|
||||
# Python 2 Types (otherwise Identifiers)
|
||||
basestring buffer file long unicode xrange
|
||||
|
||||
# Python 3 Types (otherwise Identifiers)
|
||||
bytearray bytes filter map memoryview open range zip
|
||||
|
||||
# Example Strict Errors
|
||||
def doesNothing():
|
||||
pass # indentUnit is set to 4 but this line is indented 3
|
||||
|
||||
# Some Example code
|
||||
import os
|
||||
from package import ParentClass
|
||||
|
||||
@nonsenseDecorator
|
||||
def doesNothing():
|
||||
pass
|
||||
|
||||
class ExampleClass(ParentClass):
|
||||
@staticmethod
|
||||
def example(inputStr):
|
||||
a = list(inputStr)
|
||||
a.reverse()
|
||||
return ''.join(a)
|
||||
|
||||
def __init__(self, mixin = 'Hello'):
|
||||
self.mixin = mixin
|
||||
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var editor = CodeMirror.fromTextArea('code', {
|
||||
parserfile: ["../contrib/python/js/parsepython.js"],
|
||||
stylesheet: "css/pythoncolors.css",
|
||||
path: "../../js/",
|
||||
lineNumbers: true,
|
||||
textWrapping: false,
|
||||
indentUnit: 4,
|
||||
parserConfig: {'pythonVersion': 2, 'strictErrors': true}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
544
media/CodeMirror-0.62/contrib/python/js/parsepython.js
Normal file
544
media/CodeMirror-0.62/contrib/python/js/parsepython.js
Normal file
@@ -0,0 +1,544 @@
|
||||
var PythonParser = Editor.Parser = (function() {
|
||||
function wordRegexp(words) {
|
||||
return new RegExp("^(?:" + words.join("|") + ")$");
|
||||
}
|
||||
var DELIMITERCLASS = 'py-delimiter';
|
||||
var LITERALCLASS = 'py-literal';
|
||||
var ERRORCLASS = 'py-error';
|
||||
var OPERATORCLASS = 'py-operator';
|
||||
var IDENTIFIERCLASS = 'py-identifier';
|
||||
var STRINGCLASS = 'py-string';
|
||||
var BYTESCLASS = 'py-bytes';
|
||||
var UNICODECLASS = 'py-unicode';
|
||||
var RAWCLASS = 'py-raw';
|
||||
var NORMALCONTEXT = 'normal';
|
||||
var STRINGCONTEXT = 'string';
|
||||
var singleOperators = '+-*/%&|^~<>';
|
||||
var doubleOperators = wordRegexp(['==', '!=', '\\<=', '\\>=', '\\<\\>',
|
||||
'\\<\\<', '\\>\\>', '\\/\\/', '\\*\\*']);
|
||||
var singleDelimiters = '()[]{}@,:.`=;';
|
||||
var doubleDelimiters = ['\\+=', '\\-=', '\\*=', '/=', '%=', '&=', '\\|=',
|
||||
'\\^='];
|
||||
var tripleDelimiters = wordRegexp(['//=','\\>\\>=','\\<\\<=','\\*\\*=']);
|
||||
var singleStarters = singleOperators + singleDelimiters + '=!';
|
||||
var doubleStarters = '=<>*/';
|
||||
var identifierStarters = /[_A-Za-z]/;
|
||||
|
||||
var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);
|
||||
var commonkeywords = ['as', 'assert', 'break', 'class', 'continue',
|
||||
'def', 'del', 'elif', 'else', 'except', 'finally',
|
||||
'for', 'from', 'global', 'if', 'import',
|
||||
'lambda', 'pass', 'raise', 'return',
|
||||
'try', 'while', 'with', 'yield'];
|
||||
var commontypes = ['bool', 'classmethod', 'complex', 'dict', 'enumerate',
|
||||
'float', 'frozenset', 'int', 'list', 'object',
|
||||
'property', 'reversed', 'set', 'slice', 'staticmethod',
|
||||
'str', 'super', 'tuple', 'type'];
|
||||
var py2 = {'types': ['basestring', 'buffer', 'file', 'long', 'unicode',
|
||||
'xrange'],
|
||||
'keywords': ['exec', 'print'],
|
||||
'version': 2 };
|
||||
var py3 = {'types': ['bytearray', 'bytes', 'filter', 'map', 'memoryview',
|
||||
'open', 'range', 'zip'],
|
||||
'keywords': ['nonlocal'],
|
||||
'version': 3};
|
||||
|
||||
var py, keywords, types, stringStarters, stringTypes, config;
|
||||
|
||||
function configure(conf) {
|
||||
if (!conf.hasOwnProperty('pythonVersion')) {
|
||||
conf.pythonVersion = 2;
|
||||
}
|
||||
if (!conf.hasOwnProperty('strictErrors')) {
|
||||
conf.strictErrors = true;
|
||||
}
|
||||
if (conf.pythonVersion != 2 && conf.pythonVersion != 3) {
|
||||
alert('CodeMirror: Unknown Python Version "' +
|
||||
conf.pythonVersion +
|
||||
'", defaulting to Python 2.x.');
|
||||
conf.pythonVersion = 2;
|
||||
}
|
||||
if (conf.pythonVersion == 3) {
|
||||
py = py3;
|
||||
stringStarters = /[\'\"rbRB]/;
|
||||
stringTypes = /[rb]/;
|
||||
doubleDelimiters.push('\\-\\>');
|
||||
} else {
|
||||
py = py2;
|
||||
stringStarters = /['"RUru]/;
|
||||
stringTypes = /[ru]/;
|
||||
}
|
||||
config = conf;
|
||||
keywords = wordRegexp(commonkeywords.concat(py.keywords));
|
||||
types = wordRegexp(commontypes.concat(py.types));
|
||||
doubleDelimiters = wordRegexp(doubleDelimiters);
|
||||
}
|
||||
|
||||
var tokenizePython = (function() {
|
||||
function normal(source, setState) {
|
||||
var stringDelim, threeStr, temp, type, word, possible = {};
|
||||
var ch = source.next();
|
||||
|
||||
function filterPossible(token, styleIfPossible) {
|
||||
if (!possible.style && !possible.content) {
|
||||
return token;
|
||||
} else if (typeof(token) == STRINGCONTEXT) {
|
||||
token = {content: source.get(), style: token};
|
||||
}
|
||||
if (possible.style || styleIfPossible) {
|
||||
token.style = styleIfPossible ? styleIfPossible : possible.style;
|
||||
}
|
||||
if (possible.content) {
|
||||
token.content = possible.content + token.content;
|
||||
}
|
||||
possible = {};
|
||||
return token;
|
||||
}
|
||||
|
||||
// Handle comments
|
||||
if (ch == '#') {
|
||||
while (!source.endOfLine()) {
|
||||
source.next();
|
||||
}
|
||||
return 'py-comment';
|
||||
}
|
||||
// Handle special chars
|
||||
if (ch == '\\') {
|
||||
if (source.peek() != '\n') {
|
||||
var whitespace = true;
|
||||
while (!source.endOfLine()) {
|
||||
if(!(/\s/.test(source.next()))) {
|
||||
whitespace = false;
|
||||
}
|
||||
}
|
||||
if (!whitespace) {
|
||||
return ERRORCLASS;
|
||||
}
|
||||
}
|
||||
return 'py-special';
|
||||
}
|
||||
// Handle operators and delimiters
|
||||
if (singleStarters.indexOf(ch) != -1) {
|
||||
if (doubleStarters.indexOf(source.peek()) != -1) {
|
||||
temp = ch + source.peek();
|
||||
// It must be a double delimiter or operator or triple delimiter
|
||||
if (doubleOperators.test(temp)) {
|
||||
source.next();
|
||||
if (tripleDelimiters.test(temp + source.peek())) {
|
||||
source.next();
|
||||
return DELIMITERCLASS;
|
||||
} else {
|
||||
return OPERATORCLASS;
|
||||
}
|
||||
} else if (doubleDelimiters.test(temp)) {
|
||||
source.next();
|
||||
return DELIMITERCLASS;
|
||||
}
|
||||
}
|
||||
// It must be a single delimiter or operator
|
||||
if (singleOperators.indexOf(ch) != -1) {
|
||||
return OPERATORCLASS;
|
||||
} else if (singleDelimiters.indexOf(ch) != -1) {
|
||||
if (ch == '@' && /\w/.test(source.peek())) {
|
||||
possible = {style:'py-decorator',
|
||||
content: source.get()};
|
||||
ch = source.next();
|
||||
} else if (ch == '.' && /\d/.test(source.peek())) {
|
||||
possible = {style:LITERALCLASS,
|
||||
content: source.get()};
|
||||
ch = source.next();
|
||||
} else {
|
||||
return DELIMITERCLASS;
|
||||
}
|
||||
} else {
|
||||
return ERRORCLASS;
|
||||
}
|
||||
}
|
||||
// Handle number literals
|
||||
if (/\d/.test(ch)) {
|
||||
if (ch === '0' && !source.endOfLine()) {
|
||||
switch (source.peek()) {
|
||||
case 'o':
|
||||
case 'O':
|
||||
source.next();
|
||||
source.nextWhileMatches(/[0-7]/);
|
||||
return filterPossible(LITERALCLASS, ERRORCLASS);
|
||||
case 'x':
|
||||
case 'X':
|
||||
source.next();
|
||||
source.nextWhileMatches(/[0-9A-Fa-f]/);
|
||||
return filterPossible(LITERALCLASS, ERRORCLASS);
|
||||
case 'b':
|
||||
case 'B':
|
||||
source.next();
|
||||
source.nextWhileMatches(/[01]/);
|
||||
return filterPossible(LITERALCLASS, ERRORCLASS);
|
||||
}
|
||||
}
|
||||
source.nextWhileMatches(/\d/);
|
||||
if (source.peek() == '.') {
|
||||
source.next();
|
||||
source.nextWhileMatches(/\d/);
|
||||
}
|
||||
// Grab an exponent
|
||||
if (source.peek().toLowerCase() == 'e') {
|
||||
source.next();
|
||||
if (source.peek() == '+' || source.peek() == '-') {
|
||||
source.next();
|
||||
}
|
||||
if (/\d/.test(source.peek())) {
|
||||
source.nextWhileMatches(/\d/);
|
||||
} else {
|
||||
return filterPossible(ERRORCLASS);
|
||||
}
|
||||
}
|
||||
// Grab a complex number
|
||||
if (source.peek().toLowerCase() == 'j') {
|
||||
source.next();
|
||||
}
|
||||
|
||||
return filterPossible(LITERALCLASS);
|
||||
}
|
||||
// Handle strings
|
||||
if (stringStarters.test(ch)) {
|
||||
var peek = source.peek();
|
||||
var stringType = STRINGCLASS;
|
||||
if ((stringTypes.test(ch)) && (peek == '"' || peek == "'")) {
|
||||
switch (ch.toLowerCase()) {
|
||||
case 'b':
|
||||
stringType = BYTESCLASS;
|
||||
break;
|
||||
case 'r':
|
||||
stringType = RAWCLASS;
|
||||
break;
|
||||
case 'u':
|
||||
stringType = UNICODECLASS;
|
||||
break;
|
||||
}
|
||||
ch = source.next();
|
||||
stringDelim = ch;
|
||||
if (source.peek() != stringDelim) {
|
||||
setState(inString(stringType, stringDelim));
|
||||
return null;
|
||||
} else {
|
||||
source.next();
|
||||
if (source.peek() == stringDelim) {
|
||||
source.next();
|
||||
threeStr = stringDelim + stringDelim + stringDelim;
|
||||
setState(inString(stringType, threeStr));
|
||||
return null;
|
||||
} else {
|
||||
return stringType;
|
||||
}
|
||||
}
|
||||
} else if (ch == "'" || ch == '"') {
|
||||
stringDelim = ch;
|
||||
if (source.peek() != stringDelim) {
|
||||
setState(inString(stringType, stringDelim));
|
||||
return null;
|
||||
} else {
|
||||
source.next();
|
||||
if (source.peek() == stringDelim) {
|
||||
source.next();
|
||||
threeStr = stringDelim + stringDelim + stringDelim;
|
||||
setState(inString(stringType, threeStr));
|
||||
return null;
|
||||
} else {
|
||||
return stringType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle Identifier
|
||||
if (identifierStarters.test(ch)) {
|
||||
source.nextWhileMatches(/[\w\d]/);
|
||||
word = source.get();
|
||||
if (wordOperators.test(word)) {
|
||||
type = OPERATORCLASS;
|
||||
} else if (keywords.test(word)) {
|
||||
type = 'py-keyword';
|
||||
} else if (types.test(word)) {
|
||||
type = 'py-type';
|
||||
} else {
|
||||
type = IDENTIFIERCLASS;
|
||||
while (source.peek() == '.') {
|
||||
source.next();
|
||||
if (identifierStarters.test(source.peek())) {
|
||||
source.nextWhileMatches(/[\w\d]/);
|
||||
} else {
|
||||
type = ERRORCLASS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
word = word + source.get();
|
||||
}
|
||||
return filterPossible({style: type, content: word});
|
||||
}
|
||||
|
||||
// Register Dollar sign and Question mark as errors. Always!
|
||||
if (/\$\?/.test(ch)) {
|
||||
return filterPossible(ERRORCLASS);
|
||||
}
|
||||
|
||||
return filterPossible(ERRORCLASS);
|
||||
}
|
||||
|
||||
function inString(style, terminator) {
|
||||
return function(source, setState) {
|
||||
var matches = [];
|
||||
var found = false;
|
||||
while (!found && !source.endOfLine()) {
|
||||
var ch = source.next(), newMatches = [];
|
||||
// Skip escaped characters
|
||||
if (ch == '\\') {
|
||||
if (source.peek() == '\n') {
|
||||
break;
|
||||
}
|
||||
ch = source.next();
|
||||
ch = source.next();
|
||||
}
|
||||
if (ch == terminator.charAt(0)) {
|
||||
matches.push(terminator);
|
||||
}
|
||||
for (var i = 0; i < matches.length; i++) {
|
||||
var match = matches[i];
|
||||
if (match.charAt(0) == ch) {
|
||||
if (match.length == 1) {
|
||||
setState(normal);
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
newMatches.push(match.slice(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
matches = newMatches;
|
||||
}
|
||||
return style;
|
||||
};
|
||||
}
|
||||
|
||||
return function(source, startState) {
|
||||
return tokenizer(source, startState || normal);
|
||||
};
|
||||
})();
|
||||
|
||||
function parsePython(source) {
|
||||
if (!keywords) {
|
||||
configure({});
|
||||
}
|
||||
|
||||
var tokens = tokenizePython(source);
|
||||
var lastToken = null;
|
||||
var column = 0;
|
||||
var context = {prev: null,
|
||||
endOfScope: false,
|
||||
startNewScope: false,
|
||||
level: 0,
|
||||
next: null,
|
||||
type: NORMALCONTEXT
|
||||
};
|
||||
|
||||
function pushContext(level, type) {
|
||||
type = type ? type : NORMALCONTEXT;
|
||||
context = {prev: context,
|
||||
endOfScope: false,
|
||||
startNewScope: false,
|
||||
level: level,
|
||||
next: null,
|
||||
type: type
|
||||
};
|
||||
}
|
||||
|
||||
function popContext(remove) {
|
||||
remove = remove ? remove : false;
|
||||
if (context.prev) {
|
||||
if (remove) {
|
||||
context = context.prev;
|
||||
context.next = null;
|
||||
} else {
|
||||
context.prev.next = context;
|
||||
context = context.prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function indentPython(context) {
|
||||
var temp;
|
||||
return function(nextChars, currentLevel, direction) {
|
||||
if (direction === null || direction === undefined) {
|
||||
if (nextChars) {
|
||||
while (context.next) {
|
||||
context = context.next;
|
||||
}
|
||||
}
|
||||
return context.level;
|
||||
}
|
||||
else if (direction === true) {
|
||||
if (currentLevel == context.level) {
|
||||
if (context.next) {
|
||||
return context.next.level;
|
||||
} else {
|
||||
return context.level;
|
||||
}
|
||||
} else {
|
||||
temp = context;
|
||||
while (temp.prev && temp.prev.level > currentLevel) {
|
||||
temp = temp.prev;
|
||||
}
|
||||
return temp.level;
|
||||
}
|
||||
} else if (direction === false) {
|
||||
if (currentLevel > context.level) {
|
||||
return context.level;
|
||||
} else if (context.prev) {
|
||||
temp = context;
|
||||
while (temp.prev && temp.prev.level >= currentLevel) {
|
||||
temp = temp.prev;
|
||||
}
|
||||
if (temp.prev) {
|
||||
return temp.prev.level;
|
||||
} else {
|
||||
return temp.level;
|
||||
}
|
||||
}
|
||||
}
|
||||
return context.level;
|
||||
};
|
||||
}
|
||||
|
||||
var iter = {
|
||||
next: function() {
|
||||
var token = tokens.next();
|
||||
var type = token.style;
|
||||
var content = token.content;
|
||||
|
||||
if (lastToken) {
|
||||
if (lastToken.content == 'def' && type == IDENTIFIERCLASS) {
|
||||
token.style = 'py-func';
|
||||
}
|
||||
if (lastToken.content == '\n') {
|
||||
var tempCtx = context;
|
||||
// Check for a different scope
|
||||
if (type == 'whitespace' && context.type == NORMALCONTEXT) {
|
||||
if (token.value.length < context.level) {
|
||||
while (token.value.length < context.level) {
|
||||
popContext();
|
||||
}
|
||||
|
||||
if (token.value.length != context.level) {
|
||||
context = tempCtx;
|
||||
if (config.strictErrors) {
|
||||
token.style = ERRORCLASS;
|
||||
}
|
||||
} else {
|
||||
context.next = null;
|
||||
}
|
||||
}
|
||||
} else if (context.level !== 0 &&
|
||||
context.type == NORMALCONTEXT) {
|
||||
while (0 !== context.level) {
|
||||
popContext();
|
||||
}
|
||||
|
||||
if (context.level !== 0) {
|
||||
context = tempCtx;
|
||||
if (config.strictErrors) {
|
||||
token.style = ERRORCLASS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Scope Changes
|
||||
switch(type) {
|
||||
case STRINGCLASS:
|
||||
case BYTESCLASS:
|
||||
case RAWCLASS:
|
||||
case UNICODECLASS:
|
||||
if (context.type !== STRINGCONTEXT) {
|
||||
pushContext(context.level + 1, STRINGCONTEXT);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (context.type === STRINGCONTEXT) {
|
||||
popContext(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch(content) {
|
||||
case '.':
|
||||
case '@':
|
||||
// These delimiters don't appear by themselves
|
||||
if (content !== token.value) {
|
||||
token.style = ERRORCLASS;
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
// Colons only delimit scope inside a normal scope
|
||||
if (context.type === NORMALCONTEXT) {
|
||||
context.startNewScope = context.level+indentUnit;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
case '[':
|
||||
case '{':
|
||||
// These start a sequence scope
|
||||
pushContext(column + content.length, 'sequence');
|
||||
break;
|
||||
case ')':
|
||||
case ']':
|
||||
case '}':
|
||||
// These end a sequence scope
|
||||
popContext(true);
|
||||
break;
|
||||
case 'pass':
|
||||
case 'return':
|
||||
// These end a normal scope
|
||||
if (context.type === NORMALCONTEXT) {
|
||||
context.endOfScope = true;
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
// Reset our column
|
||||
column = 0;
|
||||
// Make any scope changes
|
||||
if (context.endOfScope) {
|
||||
context.endOfScope = false;
|
||||
popContext();
|
||||
} else if (context.startNewScope !== false) {
|
||||
var temp = context.startNewScope;
|
||||
context.startNewScope = false;
|
||||
pushContext(temp, NORMALCONTEXT);
|
||||
}
|
||||
// Newlines require an indentation function wrapped in a closure for proper context.
|
||||
token.indentation = indentPython(context);
|
||||
break;
|
||||
}
|
||||
|
||||
// Keep track of current column for certain scopes.
|
||||
if (content != '\n') {
|
||||
column += token.value.length;
|
||||
}
|
||||
|
||||
lastToken = token;
|
||||
return token;
|
||||
},
|
||||
|
||||
copy: function() {
|
||||
var _context = context, _tokenState = tokens.state;
|
||||
return function(source) {
|
||||
tokens = tokenizePython(source, _tokenState);
|
||||
context = _context;
|
||||
return iter;
|
||||
};
|
||||
}
|
||||
};
|
||||
return iter;
|
||||
}
|
||||
|
||||
return {make: parsePython,
|
||||
electricChars: "",
|
||||
configure: configure};
|
||||
})();
|
||||
Reference in New Issue
Block a user