liquid_cms 0.3.0.1 → 0.3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +5 -1
- data/Gemfile.lock +1 -1
- data/README.rdoc +5 -1
- data/app/helpers/cms/common_helper.rb +1 -0
- data/app/views/cms/pages/_page.html.erb +2 -1
- data/app/views/layouts/cms.html.erb +2 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +2 -2
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +12 -8
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +123 -29
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/csstest.html +1 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/htmltest.html +1 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/index.html +232 -179
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +211 -65
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +360 -194
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +1 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +11 -7
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +14 -5
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +1 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +140 -87
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +5 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +1 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +7 -7
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/manual.html +148 -52
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/story.html +631 -614
- data/lib/generators/liquid_cms/templates/public/cms/stylesheets/styles.css +7 -7
- data/lib/liquid_cms/version.rb +1 -1
- metadata +4 -26
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/LICENSE +0 -32
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/css/luacolors.css +0 -63
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/index.html +0 -68
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/js/parselua.js +0 -253
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/LICENSE +0 -37
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/css/phpcolors.css +0 -114
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/index.html +0 -292
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/parsephp.js +0 -371
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/parsephphtmlmixed.js +0 -90
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/tokenizephp.js +0 -1006
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/LICENSE +0 -22
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/css/plsqlcolors.css +0 -57
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/index.html +0 -67
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/js/parseplsql.js +0 -233
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/LICENSE +0 -32
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/css/pythoncolors.css +0 -58
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/index.html +0 -141
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/js/parsepython.js +0 -542
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/LICENSE +0 -22
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/css/sqlcolors.css +0 -57
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/index.html +0 -56
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/js/parsesql.js +0 -211
@@ -1,292 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
|
3
|
-
The copyrights embodied in the content of this file are licensed by
|
4
|
-
Yahoo! Inc. under the BSD (revised) open source license
|
5
|
-
|
6
|
-
@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
|
7
|
-
|
8
|
-
-->
|
9
|
-
|
10
|
-
|
11
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
12
|
-
<head>
|
13
|
-
<script src="../../js/codemirror.js" type="text/javascript"></script>
|
14
|
-
<title>CodeMirror: PHP+HTML+JavaScript+CSS mixed-mode demonstration</title>
|
15
|
-
<link rel="stylesheet" type="text/css" href="../../css/docs.css"/>
|
16
|
-
</head>
|
17
|
-
<body style="padding: 20px;">
|
18
|
-
|
19
|
-
<p>This is a complex demonstration of the <b>PHP+HTML+JavaScript+CSS mixed-mode
|
20
|
-
syntax highlight</b> capabilities of <a href="../../index.html">CodeMirror</a>.
|
21
|
-
<?php ... ?> tags use the PHP parser, <script> tags use the JavaScript
|
22
|
-
parser, and <style> tags use the CSS parser. The rest of the content is
|
23
|
-
parsed using the XML parser in HTML mode.</p>
|
24
|
-
|
25
|
-
<p>Features of the PHP parser:
|
26
|
-
<ul>
|
27
|
-
<li>special "deprecated" style for PHP4 keywords like 'var'
|
28
|
-
<li>support for PHP 5.3 keywords: 'namespace', 'use'
|
29
|
-
<li>911 predefined constants, 1301 predefined functions, 105 predeclared classes
|
30
|
-
from a typical PHP installation in a LAMP environment
|
31
|
-
<li>new feature: syntax error flagging, thus enabling strict parsing of:
|
32
|
-
<ol>
|
33
|
-
<li>function definitions with explicitly or implicitly typed arguments and default values
|
34
|
-
<li>modifiers (public, static etc.) applied to method and member definitions
|
35
|
-
<li>foreach(array_expression as $key [=> $value]) loops
|
36
|
-
</ol>
|
37
|
-
<li>differentiation between single-quoted strings and double-quoted interpolating strings
|
38
|
-
</ul>
|
39
|
-
</p>
|
40
|
-
|
41
|
-
<div style="border: 1px solid black; padding: 3px; background-color: #F8F8F8">
|
42
|
-
<textarea id="code" cols="120" rows="30">
|
43
|
-
The "root" parser is XML in HTML mode.
|
44
|
-
Next, we can switch into PHP mode, for example. This is
|
45
|
-
<?php echo 'text output by';
|
46
|
-
?>
|
47
|
-
PHP. </b>
|
48
|
-
On the line above, we just had an XML syntax error due to the </b> tag not being opened.
|
49
|
-
|
50
|
-
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> HTML text will follow
|
51
|
-
<html>
|
52
|
-
<head>
|
53
|
-
<title>Similarly, the 'script' tag will switch to the JavaScript parser:</title>
|
54
|
-
<script type="text/javascript">
|
55
|
-
// Press enter inside the object and your new line will be suitably
|
56
|
-
// indented.
|
57
|
-
var keyBindings = {
|
58
|
-
enter: "newline-and-indent",
|
59
|
-
tab: "reindent-selection",
|
60
|
-
ctrl_enter: "reparse-buffer",
|
61
|
-
ctrl_z: "undo",
|
62
|
-
ctrl_y: "redo",
|
63
|
-
ctrl_backspace: "undo-for-safari-which-stupidly-enough-blocks-ctrl-z"
|
64
|
-
};
|
65
|
-
|
66
|
-
// Press tab on the next line and the wrong indentation will be fixed.
|
67
|
-
var regex = /foo|bar/i;
|
68
|
-
|
69
|
-
function example(x) {
|
70
|
-
// Local variables get a different colour than global ones.
|
71
|
-
var y = 44.4;
|
72
|
-
return x + y - z;
|
73
|
-
}
|
74
|
-
</script>
|
75
|
-
<style>
|
76
|
-
/* Some example CSS */
|
77
|
-
|
78
|
-
@import url("something.css");
|
79
|
-
|
80
|
-
body {
|
81
|
-
margin: 0;
|
82
|
-
padding: 3em 6em;
|
83
|
-
font-family: tahoma, arial, sans-serif;
|
84
|
-
color: #000;
|
85
|
-
}
|
86
|
-
|
87
|
-
#navigation a {
|
88
|
-
font-weight: bold;
|
89
|
-
text-decoration: none !important;
|
90
|
-
}
|
91
|
-
|
92
|
-
h1 {
|
93
|
-
font-size: 2.5em;
|
94
|
-
}
|
95
|
-
|
96
|
-
h1:before, h2:before {
|
97
|
-
content: "::";
|
98
|
-
}
|
99
|
-
|
100
|
-
code {
|
101
|
-
font-family: courier, monospace;
|
102
|
-
font-size: 80%;
|
103
|
-
color: #418A8A;
|
104
|
-
}
|
105
|
-
</style>
|
106
|
-
</head>
|
107
|
-
|
108
|
-
<body>
|
109
|
-
|
110
|
-
The PHP code below contains some deliberate errors. Play with the editor by fixing them
|
111
|
-
and observing how the highlight changes.
|
112
|
-
|
113
|
-
<?php
|
114
|
-
namespace A;
|
115
|
-
namespace A::B::C;
|
116
|
-
namespace A::::B;
|
117
|
-
namespace A::B::C::;
|
118
|
-
namespace A::B::C::D x;
|
119
|
-
self::range($row['lft'], $row['rgt'])); // error: extra ')'
|
120
|
-
$a = (b() + 4) 5 foo; // error: missing operators
|
121
|
-
self::$var;
|
122
|
-
$parent = self::range($max + 1, $max + 1);
|
123
|
-
$row[attributes][$attribute_name] = $attribute_value;
|
124
|
-
$row[attributes()][$attribute_name] = $attribute_value;
|
125
|
-
$row[attributes(5)][$attribute_name] = $attribute_value;
|
126
|
-
$row[$attributes()][$attribute_name] = $attribute_value;
|
127
|
-
abstract class 5 extends foo implements echo {
|
128
|
-
private function domainObjectBuilder() {
|
129
|
-
return $this->use_domain_object_builder
|
130
|
-
? $this->domain()->objectBuilder()
|
131
|
-
: null;
|
132
|
-
}
|
133
|
-
|
134
|
-
const $myconst = 'some string';
|
135
|
-
$array[myconst] = 4;
|
136
|
-
// this is a single-line C++-style comment
|
137
|
-
# this is a single-line shell-style comment
|
138
|
-
private var $a = __FILE__;
|
139
|
-
protected static $b = timezone_transitions_get('some parameter here');
|
140
|
-
global $g = isset("string");
|
141
|
-
static $s = hash_update_file; // warning: predefined function non-call
|
142
|
-
function mike ($var) $foo;
|
143
|
-
mike(A::func(param));
|
144
|
-
func($b $c); // error: function parameters must be comma-separated
|
145
|
-
foo bar; // error: no operator
|
146
|
-
$baz $quux; // error: no operator
|
147
|
-
public abstract function loadPageXML(util_FilePath $filename, $merge=0+$foo, $x, $y=3) {
|
148
|
-
$newrow[$key] = $val;
|
149
|
-
$newresult[] = $row;
|
150
|
-
$state = $row['c'] == 1;
|
151
|
-
$attribute_values[$attribute_name] = null;
|
152
|
-
$row['attributes'][$attribute_name] = $attribute_value;
|
153
|
-
$result[$row['element']][$row['attribute']] = $row['value'];
|
154
|
-
$sql = "multiline string
|
155
|
-
line2 is special - it'll interpolate variables like $state and method calls
|
156
|
-
{$this->cache->add($key, 5)} and maybe \"more\"
|
157
|
-
|
158
|
-
line5";
|
159
|
-
$sql = 'multiline string
|
160
|
-
single quoting means no \'interpolation\' like "$start" or method call
|
161
|
-
{$this->cache->add($key, 5)} will happen
|
162
|
-
|
163
|
-
line5';
|
164
|
-
$bitpattern = 1 << 2;
|
165
|
-
$bitpattern <<= 3;
|
166
|
-
$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
|
167
|
-
error: the identifier must conform to the identifier rules
|
168
|
-
EOSTRING;
|
169
|
-
$sql = <<< EOSQL
|
170
|
-
SELECT attribute, element, value
|
171
|
-
FROM attribute_values
|
172
|
-
WHERE dimension = ?
|
173
|
-
EOSQL;
|
174
|
-
$this->lr_cache->add($key, self::range($row['lft'], $row['rgt']));
|
175
|
-
$composite_string = <<<EOSTRING
|
176
|
-
some lines here
|
177
|
-
EOSTRING
|
178
|
-
. 'something extra';
|
179
|
-
$page_lft = ($domain->name() == 'page') ? $start + 1 : $page_start + 1;
|
180
|
-
echo "This is class foo";
|
181
|
-
echo "a = ".$this ->a[2+3*$array["foo"]]."";
|
182
|
-
echo "b = {$this->b}"; // FIXME: highlight interpolation in strings
|
183
|
-
}
|
184
|
-
final function makecoffee error($types = array("cappuccino"), $coffeeMaker = NULL) {
|
185
|
-
$out_of_way_amount = $max - $child->left() + 1;
|
186
|
-
$absolute_pos = $child->left() - $move->width();
|
187
|
-
$varfunc(1, 'x');
|
188
|
-
$varfunc(1, 'x') + foo() - 5;
|
189
|
-
$funcarray[$i]('param1', $param2);
|
190
|
-
$lr[$domain_name] = $this->get_left_and_right($domain,
|
191
|
-
$dimension_name,
|
192
|
-
$element_name);
|
193
|
-
$domain_list = is_null($domain) ?
|
194
|
-
r3_Domain::names() :
|
195
|
-
array($domain->name());
|
196
|
-
foreach (r3_Domain::names() as $domain_name) {
|
197
|
-
$placeholders = 'distance LIKE '
|
198
|
-
. implode(array_fill(1, $num_distances, '?'),
|
199
|
-
' OR distance LIKE ');
|
200
|
-
|
201
|
-
}
|
202
|
-
return $this->target*$this->trans+myfunc(__METHOD__);
|
203
|
-
/*
|
204
|
-
echo 'This is a test'; /* This comment will cause a problem */
|
205
|
-
*/
|
206
|
-
}
|
207
|
-
switch( $type ) {
|
208
|
-
case "r3core_AddTemplateToTargetEvent":
|
209
|
-
$this->notifyAddTemplateToTarget( $genevent );
|
210
|
-
break;
|
211
|
-
case "r3core_GenerateTargetEvent" $this:
|
212
|
-
for($i=0; $i<=this->method(); $i++) {
|
213
|
-
echo 'Syntax "highlighting"';
|
214
|
-
}
|
215
|
-
try {
|
216
|
-
foreach($array xor $loader->parse_fn($filename) as $key => value) {
|
217
|
-
namespace r3;
|
218
|
-
}
|
219
|
-
} catch( Exception $e ) {
|
220
|
-
/** restore the backup
|
221
|
-
*/
|
222
|
-
$this->loadAll($tmp, $event, true);
|
223
|
-
// `php -l` doesn't complain at all at this (it assumes string constants):
|
224
|
-
this + makes * no - sense;
|
225
|
-
}
|
226
|
-
|
227
|
-
break;
|
228
|
-
|
229
|
-
default moo:
|
230
|
-
throw new r3_util_Exception( get_class( $genevent ) . " does not map" );
|
231
|
-
}
|
232
|
-
|
233
|
-
|
234
|
-
};
|
235
|
-
|
236
|
-
?>
|
237
|
-
|
238
|
-
<r3:cphp>
|
239
|
-
php("works", $here, 2);
|
240
|
-
</r3:cphp>
|
241
|
-
|
242
|
-
<r4:cphp>
|
243
|
-
class foo {
|
244
|
-
// a comment
|
245
|
-
var $a;
|
246
|
-
var $b;
|
247
|
-
};
|
248
|
-
</r4:cphp>
|
249
|
-
|
250
|
-
<h1>This is an <?php # echo 'simple';?> example.</h1>
|
251
|
-
<p>The header above will say 'This is an example'.</p>
|
252
|
-
<h1>This is an <?php // echo 'simple';?> example.</h1>
|
253
|
-
|
254
|
-
<?php echo; ?>
|
255
|
-
<body>
|
256
|
-
|
257
|
-
<?php echo "<html>
|
258
|
-
<head>
|
259
|
-
<script>
|
260
|
-
var foo = 'bar';
|
261
|
-
</script>
|
262
|
-
<style>
|
263
|
-
span.test {font-family: arial, 'lucida console', sans-serif}
|
264
|
-
</style>
|
265
|
-
</head>
|
266
|
-
<body>
|
267
|
-
<!-- comment -->
|
268
|
-
</body>
|
269
|
-
</html>"; ?>
|
270
|
-
|
271
|
-
</body>
|
272
|
-
</html>
|
273
|
-
|
274
|
-
|
275
|
-
</textarea>
|
276
|
-
</div>
|
277
|
-
|
278
|
-
<script type="text/javascript">
|
279
|
-
var editor = CodeMirror.fromTextArea('code', {
|
280
|
-
height: "350px",
|
281
|
-
parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js",
|
282
|
-
"../contrib/php/js/tokenizephp.js", "../contrib/php/js/parsephp.js",
|
283
|
-
"../contrib/php/js/parsephphtmlmixed.js"],
|
284
|
-
stylesheet: ["../../css/xmlcolors.css", "../../css/jscolors.css", "../../css/csscolors.css", "css/phpcolors.css"],
|
285
|
-
path: "../../js/",
|
286
|
-
continuousScanning: 500
|
287
|
-
});
|
288
|
-
</script>
|
289
|
-
|
290
|
-
|
291
|
-
</body>
|
292
|
-
</html>
|
@@ -1,371 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
|
3
|
-
The copyrights embodied in the content of this file are licensed by
|
4
|
-
Yahoo! Inc. under the BSD (revised) open source license
|
5
|
-
|
6
|
-
@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
|
7
|
-
|
8
|
-
|
9
|
-
Parse function for PHP. Makes use of the tokenizer from tokenizephp.js.
|
10
|
-
Based on parsejavascript.js by Marijn Haverbeke.
|
11
|
-
|
12
|
-
|
13
|
-
Features:
|
14
|
-
+ special "deprecated" style for PHP4 keywords like 'var'
|
15
|
-
+ support for PHP 5.3 keywords: 'namespace', 'use'
|
16
|
-
+ 911 predefined constants, 1301 predefined functions, 105 predeclared classes
|
17
|
-
from a typical PHP installation in a LAMP environment
|
18
|
-
+ new feature: syntax error flagging, thus enabling strict parsing of:
|
19
|
-
+ function definitions with explicitly or implicitly typed arguments and default values
|
20
|
-
+ modifiers (public, static etc.) applied to method and member definitions
|
21
|
-
+ foreach(array_expression as $key [=> $value]) loops
|
22
|
-
+ differentiation between single-quoted strings and double-quoted interpolating strings
|
23
|
-
|
24
|
-
*/
|
25
|
-
|
26
|
-
|
27
|
-
// add the Array.indexOf method for JS engines that don't support it (e.g. IE)
|
28
|
-
// code from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array/IndexOf
|
29
|
-
if (!Array.prototype.indexOf)
|
30
|
-
{
|
31
|
-
Array.prototype.indexOf = function(elt /*, from*/)
|
32
|
-
{
|
33
|
-
var len = this.length;
|
34
|
-
|
35
|
-
var from = Number(arguments[1]) || 0;
|
36
|
-
from = (from < 0)
|
37
|
-
? Math.ceil(from)
|
38
|
-
: Math.floor(from);
|
39
|
-
if (from < 0)
|
40
|
-
from += len;
|
41
|
-
|
42
|
-
for (; from < len; from++)
|
43
|
-
{
|
44
|
-
if (from in this &&
|
45
|
-
this[from] === elt)
|
46
|
-
return from;
|
47
|
-
}
|
48
|
-
return -1;
|
49
|
-
};
|
50
|
-
}
|
51
|
-
|
52
|
-
|
53
|
-
var PHPParser = Editor.Parser = (function() {
|
54
|
-
// Token types that can be considered to be atoms, part of operator expressions
|
55
|
-
var atomicTypes = {
|
56
|
-
"atom": true, "number": true, "variable": true, "string": true
|
57
|
-
};
|
58
|
-
// Constructor for the lexical context objects.
|
59
|
-
function PHPLexical(indented, column, type, align, prev, info) {
|
60
|
-
// indentation at start of this line
|
61
|
-
this.indented = indented;
|
62
|
-
// column at which this scope was opened
|
63
|
-
this.column = column;
|
64
|
-
// type of scope ('stat' (statement), 'form' (special form), '[', '{', or '(')
|
65
|
-
this.type = type;
|
66
|
-
// '[', '{', or '(' blocks that have any text after their opening
|
67
|
-
// character are said to be 'aligned' -- any lines below are
|
68
|
-
// indented all the way to the opening character.
|
69
|
-
if (align != null)
|
70
|
-
this.align = align;
|
71
|
-
// Parent scope, if any.
|
72
|
-
this.prev = prev;
|
73
|
-
this.info = info;
|
74
|
-
}
|
75
|
-
|
76
|
-
// PHP indentation rules
|
77
|
-
function indentPHP(lexical) {
|
78
|
-
return function(firstChars) {
|
79
|
-
var firstChar = firstChars && firstChars.charAt(0), type = lexical.type;
|
80
|
-
var closing = firstChar == type;
|
81
|
-
if (type == "form" && firstChar == "{")
|
82
|
-
return lexical.indented;
|
83
|
-
else if (type == "stat" || type == "form")
|
84
|
-
return lexical.indented + indentUnit;
|
85
|
-
else if (lexical.info == "switch" && !closing)
|
86
|
-
return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit);
|
87
|
-
else if (lexical.align)
|
88
|
-
return lexical.column - (closing ? 1 : 0);
|
89
|
-
else
|
90
|
-
return lexical.indented + (closing ? 0 : indentUnit);
|
91
|
-
};
|
92
|
-
}
|
93
|
-
|
94
|
-
// The parser-iterator-producing function itself.
|
95
|
-
function parsePHP(input, basecolumn) {
|
96
|
-
// Wrap the input in a token stream
|
97
|
-
var tokens = tokenizePHP(input);
|
98
|
-
// The parser state. cc is a stack of actions that have to be
|
99
|
-
// performed to finish the current statement. For example we might
|
100
|
-
// know that we still need to find a closing parenthesis and a
|
101
|
-
// semicolon. Actions at the end of the stack go first. It is
|
102
|
-
// initialized with an infinitely looping action that consumes
|
103
|
-
// whole statements.
|
104
|
-
var cc = [statements];
|
105
|
-
// The lexical scope, used mostly for indentation.
|
106
|
-
var lexical = new PHPLexical((basecolumn || 0) - indentUnit, 0, "block", false);
|
107
|
-
// Current column, and the indentation at the start of the current
|
108
|
-
// line. Used to create lexical scope objects.
|
109
|
-
var column = 0;
|
110
|
-
var indented = 0;
|
111
|
-
// Variables which are used by the mark, cont, and pass functions
|
112
|
-
// below to communicate with the driver loop in the 'next' function.
|
113
|
-
var consume, marked;
|
114
|
-
|
115
|
-
// The iterator object.
|
116
|
-
var parser = {next: next, copy: copy};
|
117
|
-
|
118
|
-
// parsing is accomplished by calling next() repeatedly
|
119
|
-
function next(){
|
120
|
-
// Start by performing any 'lexical' actions (adjusting the
|
121
|
-
// lexical variable), or the operations below will be working
|
122
|
-
// with the wrong lexical state.
|
123
|
-
while(cc[cc.length - 1].lex)
|
124
|
-
cc.pop()();
|
125
|
-
|
126
|
-
// Fetch the next token.
|
127
|
-
var token = tokens.next();
|
128
|
-
|
129
|
-
// Adjust column and indented.
|
130
|
-
if (token.type == "whitespace" && column == 0)
|
131
|
-
indented = token.value.length;
|
132
|
-
column += token.value.length;
|
133
|
-
if (token.content == "\n"){
|
134
|
-
indented = column = 0;
|
135
|
-
// If the lexical scope's align property is still undefined at
|
136
|
-
// the end of the line, it is an un-aligned scope.
|
137
|
-
if (!("align" in lexical))
|
138
|
-
lexical.align = false;
|
139
|
-
// Newline tokens get an indentation function associated with
|
140
|
-
// them.
|
141
|
-
token.indentation = indentPHP(lexical);
|
142
|
-
}
|
143
|
-
// No more processing for meaningless tokens.
|
144
|
-
if (token.type == "whitespace" || token.type == "comment"
|
145
|
-
|| token.type == "string_not_terminated" )
|
146
|
-
return token;
|
147
|
-
// When a meaningful token is found and the lexical scope's
|
148
|
-
// align is undefined, it is an aligned scope.
|
149
|
-
if (!("align" in lexical))
|
150
|
-
lexical.align = true;
|
151
|
-
|
152
|
-
// Execute actions until one 'consumes' the token and we can
|
153
|
-
// return it. 'marked' is used to change the style of the current token.
|
154
|
-
while(true) {
|
155
|
-
consume = marked = false;
|
156
|
-
// Take and execute the topmost action.
|
157
|
-
var action = cc.pop();
|
158
|
-
action(token);
|
159
|
-
|
160
|
-
if (consume){
|
161
|
-
if (marked)
|
162
|
-
token.style = marked;
|
163
|
-
// Here we differentiate between local and global variables.
|
164
|
-
return token;
|
165
|
-
}
|
166
|
-
}
|
167
|
-
return 1; // Firebug workaround for http://code.google.com/p/fbug/issues/detail?id=1239#c1
|
168
|
-
}
|
169
|
-
|
170
|
-
// This makes a copy of the parser state. It stores all the
|
171
|
-
// stateful variables in a closure, and returns a function that
|
172
|
-
// will restore them when called with a new input stream. Note
|
173
|
-
// that the cc array has to be copied, because it is contantly
|
174
|
-
// being modified. Lexical objects are not mutated, so they can
|
175
|
-
// be shared between runs of the parser.
|
176
|
-
function copy(){
|
177
|
-
var _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state;
|
178
|
-
|
179
|
-
return function copyParser(input){
|
180
|
-
lexical = _lexical;
|
181
|
-
cc = _cc.concat([]); // copies the array
|
182
|
-
column = indented = 0;
|
183
|
-
tokens = tokenizePHP(input, _tokenState);
|
184
|
-
return parser;
|
185
|
-
};
|
186
|
-
}
|
187
|
-
|
188
|
-
// Helper function for pushing a number of actions onto the cc
|
189
|
-
// stack in reverse order.
|
190
|
-
function push(fs){
|
191
|
-
for (var i = fs.length - 1; i >= 0; i--)
|
192
|
-
cc.push(fs[i]);
|
193
|
-
}
|
194
|
-
// cont and pass are used by the action functions to add other
|
195
|
-
// actions to the stack. cont will cause the current token to be
|
196
|
-
// consumed, pass will leave it for the next action.
|
197
|
-
function cont(){
|
198
|
-
push(arguments);
|
199
|
-
consume = true;
|
200
|
-
}
|
201
|
-
function pass(){
|
202
|
-
push(arguments);
|
203
|
-
consume = false;
|
204
|
-
}
|
205
|
-
// Used to change the style of the current token.
|
206
|
-
function mark(style){
|
207
|
-
marked = style;
|
208
|
-
}
|
209
|
-
// Add a lyer of style to the current token, for example syntax-error
|
210
|
-
function mark_add(style){
|
211
|
-
marked = marked + ' ' + style;
|
212
|
-
}
|
213
|
-
|
214
|
-
// Push a new lexical context of the given type.
|
215
|
-
function pushlex(type, info) {
|
216
|
-
var result = function pushlexing() {
|
217
|
-
lexical = new PHPLexical(indented, column, type, null, lexical, info)
|
218
|
-
};
|
219
|
-
result.lex = true;
|
220
|
-
return result;
|
221
|
-
}
|
222
|
-
// Pop off the current lexical context.
|
223
|
-
function poplex(){
|
224
|
-
lexical = lexical.prev;
|
225
|
-
}
|
226
|
-
poplex.lex = true;
|
227
|
-
// The 'lex' flag on these actions is used by the 'next' function
|
228
|
-
// to know they can (and have to) be ran before moving on to the
|
229
|
-
// next token.
|
230
|
-
|
231
|
-
// Creates an action that discards tokens until it finds one of
|
232
|
-
// the given type. This will ignore (and recover from) syntax errors.
|
233
|
-
function expect(wanted){
|
234
|
-
return function expecting(token){
|
235
|
-
if (token.type == wanted) cont(); // consume the token
|
236
|
-
else {
|
237
|
-
cont(arguments.callee); // continue expecting() - call itself
|
238
|
-
}
|
239
|
-
};
|
240
|
-
}
|
241
|
-
|
242
|
-
// Require a specific token type, or one of the tokens passed in the 'wanted' array
|
243
|
-
// Used to detect blatant syntax errors. 'execute' is used to pass extra code
|
244
|
-
// to be executed if the token is matched. For example, a '(' match could
|
245
|
-
// 'execute' a cont( compasep(funcarg), require(")") )
|
246
|
-
function require(wanted, execute){
|
247
|
-
return function requiring(token){
|
248
|
-
var ok;
|
249
|
-
var type = token.type;
|
250
|
-
if (typeof(wanted) == "string")
|
251
|
-
ok = (type == wanted) -1;
|
252
|
-
else
|
253
|
-
ok = wanted.indexOf(type);
|
254
|
-
if (ok >= 0) {
|
255
|
-
if (execute && typeof(execute[ok]) == "function")
|
256
|
-
execute[ok](token);
|
257
|
-
cont(); // just consume the token
|
258
|
-
}
|
259
|
-
else {
|
260
|
-
if (!marked) mark(token.style);
|
261
|
-
mark_add("syntax-error");
|
262
|
-
cont(arguments.callee);
|
263
|
-
}
|
264
|
-
};
|
265
|
-
}
|
266
|
-
|
267
|
-
// Looks for a statement, and then calls itself.
|
268
|
-
function statements(token){
|
269
|
-
return pass(statement, statements);
|
270
|
-
}
|
271
|
-
// Dispatches various types of statements based on the type of the current token.
|
272
|
-
function statement(token){
|
273
|
-
var type = token.type;
|
274
|
-
if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex);
|
275
|
-
else if (type == "keyword b") cont(pushlex("form"), statement, poplex);
|
276
|
-
else if (type == "{") cont(pushlex("}"), block, poplex);
|
277
|
-
else if (type == "function") funcdef();
|
278
|
-
// technically, "class implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function
|
279
|
-
else if (type == "class") cont(require("t_string"), expect("{"), pushlex("}"), block, poplex);
|
280
|
-
else if (type == "foreach") cont(pushlex("form"), require("("), pushlex(")"), expression, require("as"), require("variable"), /* => $value */ expect(")"), poplex, statement, poplex);
|
281
|
-
else if (type == "for") cont(pushlex("form"), require("("), pushlex(")"), expression, require(";"), expression, require(";"), expression, require(")"), poplex, statement, poplex);
|
282
|
-
// public final function foo(), protected static $bar;
|
283
|
-
else if (type == "modifier") cont(require(["modifier", "variable", "function"], [null, null, funcdef]));
|
284
|
-
else if (type == "switch") cont(pushlex("form"), require("("), expression, require(")"), pushlex("}", "switch"), require([":", "{"]), block, poplex, poplex);
|
285
|
-
else if (type == "case") cont(expression, require(":"));
|
286
|
-
else if (type == "default") cont(require(":"));
|
287
|
-
else if (type == "catch") cont(pushlex("form"), require("("), require("t_string"), require("variable"), require(")"), statement, poplex);
|
288
|
-
else if (type == "const") cont(require("t_string")); // 'const static x=5' is a syntax error
|
289
|
-
// technically, "namespace implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function
|
290
|
-
else if (type == "namespace") cont(namespacedef, require(";"));
|
291
|
-
// $variables may be followed by operators, () for variable function calls, or [] subscripts
|
292
|
-
else pass(pushlex("stat"), expression, require(";"), poplex);
|
293
|
-
}
|
294
|
-
// Dispatch expression types.
|
295
|
-
function expression(token){
|
296
|
-
var type = token.type;
|
297
|
-
if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator);
|
298
|
-
else if (type == "<<<") cont(require("string"), maybeoperator); // heredoc/nowdoc
|
299
|
-
else if (type == "t_string") cont(maybe_double_colon, maybeoperator);
|
300
|
-
else if (type == "keyword c") cont(expression);
|
301
|
-
// function call or parenthesized expression: $a = ($b + 1) * 2;
|
302
|
-
else if (type == "(") cont(pushlex(")"), commasep(expression), require(")"), poplex, maybeoperator);
|
303
|
-
else if (type == "operator") cont(expression);
|
304
|
-
}
|
305
|
-
// Called for places where operators, function calls, or subscripts are
|
306
|
-
// valid. Will skip on to the next action if none is found.
|
307
|
-
function maybeoperator(token){
|
308
|
-
var type = token.type;
|
309
|
-
if (type == "operator") {
|
310
|
-
if (token.content == "?") cont(expression, require(":"), expression); // ternary operator
|
311
|
-
else cont(expression);
|
312
|
-
}
|
313
|
-
else if (type == "(") cont(pushlex(")"), expression, commasep(expression), require(")"), poplex, maybeoperator /* $varfunc() + 3 */);
|
314
|
-
else if (type == "[") cont(pushlex("]"), expression, require("]"), maybeoperator /* for multidimensional arrays, or $func[$i]() */, poplex);
|
315
|
-
}
|
316
|
-
// A regular use of the double colon to specify a class, as in self::func() or myclass::$var;
|
317
|
-
// Differs from `namespace` or `use` in that only one class can be the parent; chains (A::B::$var) are a syntax error.
|
318
|
-
function maybe_double_colon(token) {
|
319
|
-
if (token.type == "t_double_colon")
|
320
|
-
// A::$var, A::func(), A::const
|
321
|
-
cont(require(["t_string", "variable"]), maybeoperator);
|
322
|
-
else {
|
323
|
-
// a t_string wasn't followed by ::, such as in a function call: foo()
|
324
|
-
pass(expression)
|
325
|
-
}
|
326
|
-
}
|
327
|
-
// the declaration or definition of a function
|
328
|
-
function funcdef() {
|
329
|
-
cont(require("t_string"), require("("), pushlex(")"), commasep(funcarg), require(")"), poplex, block);
|
330
|
-
}
|
331
|
-
// Parses a comma-separated list of the things that are recognized
|
332
|
-
// by the 'what' argument.
|
333
|
-
function commasep(what){
|
334
|
-
function proceed(token) {
|
335
|
-
if (token.type == ",") cont(what, proceed);
|
336
|
-
}
|
337
|
-
return function commaSeparated() {
|
338
|
-
pass(what, proceed);
|
339
|
-
};
|
340
|
-
}
|
341
|
-
// Look for statements until a closing brace is found.
|
342
|
-
function block(token) {
|
343
|
-
if (token.type == "}") cont();
|
344
|
-
else pass(statement, block);
|
345
|
-
}
|
346
|
-
function maybedefaultparameter(token){
|
347
|
-
if (token.content == "=") cont(expression);
|
348
|
-
}
|
349
|
-
// support for default arguments: http://us.php.net/manual/en/functions.arguments.php#functions.arguments.default
|
350
|
-
function funcarg(token){
|
351
|
-
// function foo(myclass $obj) {...}
|
352
|
-
if (token.type == "t_string") cont(require("variable"), maybedefaultparameter);
|
353
|
-
// function foo($string) {...}
|
354
|
-
else if (token.type == "variable") cont(maybedefaultparameter);
|
355
|
-
}
|
356
|
-
|
357
|
-
// A namespace definition or use
|
358
|
-
function maybe_double_colon_def(token) {
|
359
|
-
if (token.type == "t_double_colon")
|
360
|
-
cont(namespacedef);
|
361
|
-
}
|
362
|
-
function namespacedef(token) {
|
363
|
-
pass(require("t_string"), maybe_double_colon_def);
|
364
|
-
}
|
365
|
-
|
366
|
-
return parser;
|
367
|
-
}
|
368
|
-
|
369
|
-
return {make: parsePHP, electricChars: "{}:"};
|
370
|
-
|
371
|
-
})();
|