liquid_cms 0.3.0.1 → 0.3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/CHANGELOG.rdoc +5 -1
  2. data/Gemfile.lock +1 -1
  3. data/README.rdoc +5 -1
  4. data/app/helpers/cms/common_helper.rb +1 -0
  5. data/app/views/cms/pages/_page.html.erb +2 -1
  6. data/app/views/layouts/cms.html.erb +2 -1
  7. data/lib/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +2 -2
  8. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +12 -8
  9. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +123 -29
  10. data/lib/generators/liquid_cms/templates/public/cms/codemirror/csstest.html +1 -1
  11. data/lib/generators/liquid_cms/templates/public/cms/codemirror/htmltest.html +1 -1
  12. data/lib/generators/liquid_cms/templates/public/cms/codemirror/index.html +232 -179
  13. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +211 -65
  14. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +360 -194
  15. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +1 -1
  16. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +11 -7
  17. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +14 -5
  18. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +1 -1
  19. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +140 -87
  20. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +5 -0
  21. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +1 -1
  22. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +7 -7
  23. data/lib/generators/liquid_cms/templates/public/cms/codemirror/manual.html +148 -52
  24. data/lib/generators/liquid_cms/templates/public/cms/codemirror/story.html +631 -614
  25. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/styles.css +7 -7
  26. data/lib/liquid_cms/version.rb +1 -1
  27. metadata +4 -26
  28. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/LICENSE +0 -32
  29. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/css/luacolors.css +0 -63
  30. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/index.html +0 -68
  31. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/lua/js/parselua.js +0 -253
  32. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/LICENSE +0 -37
  33. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/css/phpcolors.css +0 -114
  34. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/index.html +0 -292
  35. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/parsephp.js +0 -371
  36. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/parsephphtmlmixed.js +0 -90
  37. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/php/js/tokenizephp.js +0 -1006
  38. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/LICENSE +0 -22
  39. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/css/plsqlcolors.css +0 -57
  40. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/index.html +0 -67
  41. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/plsql/js/parseplsql.js +0 -233
  42. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/LICENSE +0 -32
  43. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/css/pythoncolors.css +0 -58
  44. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/index.html +0 -141
  45. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/python/js/parsepython.js +0 -542
  46. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/LICENSE +0 -22
  47. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/css/sqlcolors.css +0 -57
  48. data/lib/generators/liquid_cms/templates/public/cms/codemirror/contrib/sql/index.html +0 -56
  49. 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
- &lt;?php ... ?> tags use the PHP parser, &lt;script> tags use the JavaScript
22
- parser, and &lt;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
- })();