[svn] horrid .svns copied accidentally

This commit is contained in:
goatchurch
2009-06-28 21:26:35 +01:00
parent db5e315db0
commit 16b7404d9b
45 changed files with 8750 additions and 0 deletions

View 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.

View 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;
}

View 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>.
&lt;?php ... ?> tags use the PHP parser, &lt;script> tags use the JavaScript
parser, and &lt;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>

View 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: "{}:"};
})();

View 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: "{}/:"};
})();

File diff suppressed because it is too large Load Diff