From: khartlage Date: Sun, 24 Nov 2002 14:49:22 +0000 (+0000) Subject: improved php parser X-Git-Url: http://git.phpeclipse.com improved php parser --- diff --git a/net.sourceforge.phpeclipse/src/junit/sourceforge/phpeclipse/PHPParserTestCase.java b/net.sourceforge.phpeclipse/src/junit/sourceforge/phpeclipse/PHPParserTestCase.java index 26589fc..400365a 100644 --- a/net.sourceforge.phpeclipse/src/junit/sourceforge/phpeclipse/PHPParserTestCase.java +++ b/net.sourceforge.phpeclipse/src/junit/sourceforge/phpeclipse/PHPParserTestCase.java @@ -7,6 +7,8 @@ which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html **********************************************************************/ +import org.eclipse.core.runtime.CoreException; + import junit.framework.TestCase; import net.sourceforge.phpeclipse.phpeditor.PHPParser; @@ -26,51 +28,63 @@ public class PHPParserTestCase extends TestCase { * Test the PHP Parser with different PHP snippets */ public void testPHPParser() { - check("if (isset($test)) { } elseif (isset($lang)) { }"); - check("require_once(\"mainfile.php\"); "); - check("if (eregi(\"footer.php\",$PHP_SELF)) {\n" + "Header(\"Location: index.php\");\n" + "die();\n" + "}\n"); - check("while (eregi(\"footer.php\",$PHP_SELF)) {\n" + "Header(\"Location: index.php\");\n" + "die();\n" + "}\n"); - check("while (eregi(\"footer.php\",$PHP_SELF)) :\n" + "Header(\"Location: index.php\");\n" + "die();\n" + "endwhile;\n"); - check("$tipath = \"images/topics/\";"); - check("$reasons = array(\"1\", \"2\",\"test\");"); - check("if ($home == 1) { message_box(); blocks(Center);}"); - check("$bresult = sql_query(\"select * from \".$prefix.\"_banner WHERE type='0' AND active='1'\", $dbi);"); - check("switch($func) {\n case \"f1\":\n f1();\n break; \n default: \n f0(); \n break;\n }"); - check("list ($catid) = sql_fetch_row($result, $dbi);"); - check("if (!$name) { \n }"); - check("mt_srand((double)microtime()*1000000);"); - check("\"\\\"\";"); - check("$v->read();"); - check("$alttext = ereg_replace(\"\\\"\", \"\", $alttext);"); - check("$message .= \"\"._THISISAUTOMATED.\"\\n\\n\";"); - check("if (!empty($pass) AND $pass==$passwd) { }"); - check("$AllowableHTML = array(\"b\"=>1,\n \"i\"=>1);"); - check("if ($term{0}!=$firstChar) {}"); - check("echo \"
\"._NOADMINYET.\"


\"\n" - + ".\"
\"\n" - + ".\"\"._NICKNAME.\":\"\n" - +";"); - check("/* \n overLib is from Eric Bosrup (http://www.bosrup.com/web/overlib/) \n */"); - check("if ($arrAtchCookie[1]==0 && $IdAtchPostId!=null){ } "); - check("$arrAtchCookie[1] -= filesize(realpath($AtchTempDir).\"/\".$xattachlist)/ 1024; "); - check("if (!isset($message)){ \n" - + "$message = $myrow[post_text];\n" - + "$message = eregi_replace(\"\\[addsig]\", \"\\n-----------------\\n\" . $myrow[user_sig], $message); \n" - +"$message = str_replace(\"
\", \"\\n\", $message); \n" - +"$message = str_replace(\"
\", \"\\n\", $message); \n } "); - check("do {$array[] = array(\"$myrow[uid]\" => \"$myrow[uname]\"); } while($myrow = mysql_fetch_array($result));"); - check("$ol = new Overlib();"); + checkHTML(""); + + checkPHP("if (isset($test)) { } elseif (isset($lang)) { }"); + checkPHP("require_once(\"mainfile.php\"); "); + checkPHP("if (eregi(\"footer.php\",$PHP_SELF)) {\n" + "Header(\"Location: index.php\");\n" + "die();\n" + "}\n"); + checkPHP("while (eregi(\"footer.php\",$PHP_SELF)) {\n" + "Header(\"Location: index.php\");\n" + "die();\n" + "}\n"); + checkPHP("while (eregi(\"footer.php\",$PHP_SELF)) :\n" + "Header(\"Location: index.php\");\n" + "die();\n" + "endwhile;\n"); + checkPHP("$tipath = \"images/topics/\";"); + checkPHP("$reasons = array(\"1\", \"2\",\"test\");"); + checkPHP("if ($home == 1) { message_box(); blocks(Center);}"); + checkPHP("$bresult = sql_query(\"select * from \".$prefix.\"_banner WHERE type='0' AND active='1'\", $dbi);"); + checkPHP("switch($func) {\n case \"f1\":\n f1();\n break; \n default: \n f0(); \n break;\n }"); + checkPHP("list ($catid) = sql_fetch_row($result, $dbi);"); + checkPHP("if (!$name) { \n }"); + checkPHP("mt_srand((double)microtime()*1000000);"); + checkPHP("\"\\\"\";"); + checkPHP("$v->read();"); + checkPHP("$alttext = ereg_replace(\"\\\"\", \"\", $alttext);"); + checkPHP("$message .= \"\"._THISISAUTOMATED.\"\\n\\n\";"); + checkPHP("if (!empty($pass) AND $pass==$passwd) { }"); + checkPHP("$AllowableHTML = array(\"b\"=>1,\n \"i\"=>1);"); + checkPHP("if ($term{0}!=$firstChar) {}"); + checkPHP( + "echo \"
\"._NOADMINYET.\"


\"\n" + + ".\"\"\n" + + ".\"\"._NICKNAME.\":\"\n" + + ";"); + checkPHP("/* \n overLib is from Eric Bosrup (http://www.bosrup.com/web/overlib/) \n */"); + checkPHP("if ($arrAtchCookie[1]==0 && $IdAtchPostId!=null){ } "); + checkPHP("$arrAtchCookie[1] -= filesize(realpath($AtchTempDir).\"/\".$xattachlist)/ 1024; "); + checkPHP( + "if (!isset($message)){ \n" + + "$message = $myrow[post_text];\n" + + "$message = eregi_replace(\"\\[addsig]\", \"\\n-----------------\\n\" . $myrow[user_sig], $message); \n" + + "$message = str_replace(\"
\", \"\\n\", $message); \n" + + "$message = str_replace(\"
\", \"\\n\", $message); \n } "); + checkPHP("do {$array[] = array(\"$myrow[uid]\" => \"$myrow[uname]\"); } while($myrow = mysql_fetch_array($result));"); + checkPHP("$ol = new Overlib();"); + checkPHP("$risultato = mysql_query($sql) or\n die(mysql_error());"); + } + + private void checkPHP(String strEval) { + try { + parser.phpParse(strEval, 1); + } catch (CoreException e) { + } } - public void check(String strEval) { - parser.start(strEval, 1); + private void checkHTML(String strEval) { + parser.htmlParse(strEval); } /** * The JUnit setup method */ protected void setUp() { - parser = new PHPParser(); + parser = new PHPParser(null); } } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java index 3bbd368..a6f236e 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java @@ -1,8 +1,14 @@ package net.sourceforge.phpeclipse.phpeditor; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Hashtable; import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.ui.texteditor.MarkerUtilities; /********************************************************************** Copyright (c) 2000, 2002 IBM Corp. and others. @@ -18,6 +24,15 @@ Contributors: public class PHPParser extends PHPKeywords { + public static final int ERROR = 2; + public static final int WARNING = 1; + public static final int INFO = 0; + private IFile fileToParse; + private ArrayList phpList; + + private int currentPHPString; + private boolean phpEnd; + private static HashMap keywordMap = null; private String str; @@ -68,6 +83,13 @@ public class PHPParser extends PHPKeywords { final static int TT_AMPERSAND = 52; final static int TT_DOLLARLISTOPEN = 53; final static int TT_TILDE = 54; + final static int TT_TILDEASSIGN = 55; + final static int TT_MODASSIGN = 56; + final static int TT_POWASSIGN = 57; + final static int TT_RSHIFTASSIGN = 58; + final static int TT_LSHIFTASSIGN = 59; + final static int TT_ANDASSIGN = 60; + final static int TT_QUESTIONMARK = 61; final static int TT_ARGOPEN = 128; final static int TT_ARGCLOSE = 129; @@ -108,20 +130,50 @@ public class PHPParser extends PHPKeywords { *@param sess Description of Parameter *@see */ - public PHPParser() { + public PHPParser(IFile fileToParse) { if (keywordMap == null) { keywordMap = new HashMap(); for (int i = 0; i < PHP_KEYWORS.length; i++) { keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i])); } } + this.currentPHPString = 0; + this.fileToParse = fileToParse; + this.phpList = null; this.str = ""; this.token = TT_EOF; this.chIndx = 0; this.rowCount = 1; this.columnCount = 0; + this.phpEnd = false; + + // getNextToken(); + } - getNextToken(); + /** + * Create marker for the parse error + */ + protected void setMarker(String message, int lineNumber, int errorLevel) throws CoreException { + setMarker(fileToParse, message, lineNumber, errorLevel); + } + + public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException { + + Hashtable attributes = new Hashtable(); + MarkerUtilities.setMessage(attributes, message); + switch (errorLevel) { + case ERROR : + attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR)); + break; + case WARNING : + attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING)); + break; + case INFO : + attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO)); + break; + } + MarkerUtilities.setLineNumber(attributes, lineNumber); + MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM); } private void throwSyntaxError(String error) { @@ -155,13 +207,16 @@ public class PHPParser extends PHPKeywords { chIndx = str.length() + 1; ch = ' '; - token = TT_EOF; + // token = TT_EOF; + phpEnd = true; } /** * gets the next token from input */ void getNextToken() { + phpEnd = false; + while (str.length() > chIndx) { ch = str.charAt(chIndx++); token = TT_UNDEFINED; @@ -170,7 +225,9 @@ public class PHPParser extends PHPKeywords { columnCount = chIndx; continue; // while loop } - + if (str.length() == chIndx) { + phpEnd = true; + } if (!Character.isWhitespace(ch)) { if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$') || (ch == '@')) { getIdentifier(); @@ -288,9 +345,19 @@ public class PHPParser extends PHPKeywords { token = TT_COMMA; break; + case '?' : + token = TT_QUESTIONMARK; + break; case '~' : token = TT_TILDE; + if (str.length() > chIndx) { + if (str.charAt(chIndx) == '=') { + chIndx++; + token = TT_TILDEASSIGN; + break; + } + } break; case '.' : token = TT_DOT; @@ -310,7 +377,14 @@ public class PHPParser extends PHPKeywords { break; case '%' : token = TT_MOD; + if (str.length() > chIndx) { + if (str.charAt(chIndx) == '=') { + chIndx++; + token = TT_MODASSIGN; + break; + } + } break; case ';' : token = TT_SEMICOLON; @@ -318,7 +392,14 @@ public class PHPParser extends PHPKeywords { break; case '^' : token = TT_POW; + if (str.length() > chIndx) { + if (str.charAt(chIndx) == '=') { + chIndx++; + token = TT_POWASSIGN; + break; + } + } break; case '/' : token = TT_DIV; @@ -447,13 +528,18 @@ public class PHPParser extends PHPKeywords { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_GREATEREQUAL; - break; } if (str.charAt(chIndx) == '>') { chIndx++; token = TT_RSHIFT; - + if (str.length() > chIndx) { + if (str.charAt(chIndx) == '=') { + chIndx++; + token = TT_RSHIFTASSIGN; + break; + } + } break; } } @@ -472,7 +558,13 @@ public class PHPParser extends PHPKeywords { if (str.charAt(chIndx) == '<') { chIndx++; token = TT_LSHIFT; - + if (str.length() > chIndx) { + if (str.charAt(chIndx) == '=') { + chIndx++; + token = TT_LSHIFTASSIGN; + break; + } + } break; } } @@ -493,17 +585,19 @@ public class PHPParser extends PHPKeywords { break; case '&' : + token = TT_AMPERSAND; if (str.length() > chIndx) { if (str.charAt(chIndx) == '&') { chIndx++; token = TT_AND; - break; - } else { - token = TT_AMPERSAND; - + } + if (str.charAt(chIndx) == '=') { + chIndx++; + token = TT_ANDASSIGN; break; } + break; } break; @@ -534,6 +628,24 @@ public class PHPParser extends PHPKeywords { chIndx = str.length() + 1; ch = ' '; token = TT_EOF; + phpEnd = true; + PHPString temp; + if (phpList != null) { + if (currentPHPString < phpList.size()) { + token = TT_UNDEFINED; + temp = (PHPString) phpList.get(currentPHPString++); + this.str = temp.getPHPString(); + this.token = TT_EOF; + this.chIndx = 0; + this.rowCount = temp.getLineNumber(); + this.columnCount = 0; + getNextToken(); + phpEnd = true; + } else { + token = TT_UNDEFINED; + return; + } + } } void getIdentifier() { @@ -644,44 +756,207 @@ public class PHPParser extends PHPKeywords { } } - public void start(String s, int rowCount) throws SyntaxError { - // start up - this.str = s; - this.token = TT_EOF; - this.chIndx = 0; - this.rowCount = rowCount; - this.columnCount = 0; - getNextToken(); - if (token != TT_EOF) { - statementList(); - } - if (token != TT_EOF) { - if (token == TT_ARGCLOSE) { - throwSyntaxError("too many closing ')'; end-of-file not reached"); + public void htmlParse(String input) { + boolean lineCommentMode = false; + boolean multiLineCommentMode = false; + boolean stringMode = false; + + StringBuffer buf = new StringBuffer(); + int lineNumber = 1; + int startLineNumber = 1; + int startIndex = 0; + char ch; + char ch2; + boolean phpMode = false; + boolean phpFound = false; + + phpList = new ArrayList(); + + try { + int i = 0; + while (i < input.length()) { + ch = input.charAt(i++); + if (ch == '\n') { + lineNumber++; + } + if ((!phpMode) && ch == '<') { + ch2 = input.charAt(i++); + if (ch2 == '?') { + ch2 = input.charAt(i++); + if (Character.isWhitespace(ch2)) { + // php start + phpMode = true; + phpFound = true; + startIndex = i; + startLineNumber = lineNumber; + continue; + } else if (ch2 == 'p') { + ch2 = input.charAt(i++); + if (ch2 == 'h') { + ch2 = input.charAt(i++); + if (ch2 == 'p') { + phpMode = true; + phpFound = true; + startIndex = i; + startLineNumber = lineNumber; + continue; + } + i--; + } + i--; + } else if (ch2 == 'P') { + ch2 = input.charAt(i++); + if (ch2 == 'H') { + ch2 = input.charAt(i++); + if (ch2 == 'P') { + phpMode = true; + phpFound = true; + startIndex = i; + startLineNumber = lineNumber; + continue; + } + i--; + } + i--; + } + i--; + } + i--; + } + + if (phpMode) { + buf.append(ch); + if (lineCommentMode && (ch == '\n')) { + lineCommentMode = false; + // read until end of line + } else if ((!stringMode) && (ch == '#')) { + // read until end of line + lineCommentMode = true; + continue; + } else if ((!stringMode) && (!multiLineCommentMode) && (ch == '/')) { + ch2 = input.charAt(i++); + if (ch2 == '/') { + lineCommentMode = true; + continue; + } else if (ch2 == '*') { + multiLineCommentMode = true; + continue; + } else { + i--; + } + } else if (ch == '*' && multiLineCommentMode) { + ch2 = input.charAt(i++); + if (ch2 == '/') { + multiLineCommentMode = false; + continue; + } else { + i--; + } + } else if (ch == '\\' && stringMode) { + ch2 = input.charAt(i++); + if (ch2 == '"') { + continue; + } else { + i--; + } + } else if ((!lineCommentMode) && (!multiLineCommentMode) && (ch == '"')) { + if (stringMode) { + stringMode = false; + } else { + stringMode = true; + } + continue; + } + if (lineCommentMode || multiLineCommentMode || stringMode) { + continue; + } + + if (ch == '?') { + ch2 = input.charAt(i++); + if (ch2 == '>') { + // php end + phpMode = false; + phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber)); + continue; + } + i--; + } + } else { + } } - if (token == TT_LISTCLOSE) { - throwSyntaxError("too many closing '}'; end-of-file not reached"); + if (!phpFound) { + setMarker("No PHP source code found.", lineNumber, PHPParser.INFO); + } else { + // for (int j=0;j"); + // } + phpParse(null, 1); + // PHPString temp; + // for(int j=0;j TT_KEYWORD && token != TT_list) { String keyword = identifier; if (token == TT_include || token == TT_include_once) { @@ -725,7 +1001,7 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' character after 'include' or 'include_once' expected."); } } @@ -737,7 +1013,7 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' character after 'require' or 'require_once' expected."); } } @@ -861,7 +1137,7 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after do-while statement."); } } @@ -900,7 +1176,7 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after 'continue', 'break' or 'return'."); } } @@ -912,19 +1188,18 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after 'echo' statement."); } } return; - } else if (token == TT_print) { getNextToken(); expression(); if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after 'print' statement."); } } @@ -936,7 +1211,7 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after 'global' or 'static' statement."); } } @@ -958,25 +1233,25 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after 'unset' statement."); } } return; - } else if (token == TT_exit || token == TT_die) { - getNextToken(); - if (token != TT_SEMICOLON) { - exitStatus(); - } - if (token == TT_SEMICOLON) { - getNextToken(); - } else { - if (token != TT_EOF) { - throwSyntaxError("';' expected after 'exit' or 'die' statement."); - } - } - return; + // } else if (token == TT_exit || token == TT_die) { + // getNextToken(); + // if (token != TT_SEMICOLON) { + // exitStatus(); + // } + // if (token == TT_SEMICOLON) { + // getNextToken(); + // } else { + // if (!phpEnd) { + // throwSyntaxError("';' expected after 'exit' or 'die' statement."); + // } + // } + // return; } else if (token == TT_define) { getNextToken(); @@ -1000,7 +1275,7 @@ public class PHPParser extends PHPKeywords { if (token == TT_SEMICOLON) { getNextToken(); } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after 'define' statement."); } } @@ -1038,7 +1313,7 @@ public class PHPParser extends PHPKeywords { getNextToken(); return; } else { - if (token != TT_EOF) { + if (!phpEnd) { throwSyntaxError("';' expected after expression."); } } @@ -1064,7 +1339,7 @@ public class PHPParser extends PHPKeywords { } } - public void classBody() { + public void classBody() throws CoreException { //'{' [class-element-list] '}' if (token == TT_LISTOPEN) { getNextToken(); @@ -1081,13 +1356,13 @@ public class PHPParser extends PHPKeywords { } } - public void classElementList() { + public void classElementList() throws CoreException { do { classElement(); - } while (token != TT_function || token != TT_var); + } while (token == TT_function || token == TT_var); } - public void classElement() { + public void classElement() throws CoreException { //class-property //function-definition if (token == TT_function) { @@ -1124,7 +1399,7 @@ public class PHPParser extends PHPKeywords { } } - public void functionDefinition() { + public void functionDefinition() throws CoreException { functionDeclarator(); compoundStatement(); } @@ -1175,7 +1450,7 @@ public class PHPParser extends PHPKeywords { } } - public void labeledStatementList() { + public void labeledStatementList() throws CoreException { if (token != TT_case && token != TT_default) { throwSyntaxError("'case' or 'default' expected."); } @@ -1186,6 +1461,10 @@ public class PHPParser extends PHPKeywords { if (token == TT_DDOT) { getNextToken(); statementList(); + } else if (token == TT_SEMICOLON) { + setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO); + getNextToken(); + statementList(); } else { throwSyntaxError("':' character after 'case' constant expected."); } @@ -1254,7 +1533,7 @@ public class PHPParser extends PHPKeywords { // public void definitionStatement() { // } - public void ifStatement() { + public void ifStatement() throws CoreException { // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';' if (token == TT_DDOT) { getNextToken(); @@ -1311,7 +1590,7 @@ public class PHPParser extends PHPKeywords { } } } - public void elseifStatementList() { + public void elseifStatementList() throws CoreException { do { elseifStatement(); switch (token) { @@ -1338,7 +1617,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void elseifStatement() { + public void elseifStatement() throws CoreException { if (token == TT_ARGOPEN) { getNextToken(); expression(); @@ -1354,7 +1633,7 @@ public class PHPParser extends PHPKeywords { } } - public void switchStatement() { + public void switchStatement() throws CoreException { if (token == TT_DDOT) { // ':' [labeled-statement-list] 'endswitch' ';' getNextToken(); @@ -1384,7 +1663,7 @@ public class PHPParser extends PHPKeywords { } } - public void forStatement() { + public void forStatement() throws CoreException { if (token == TT_DDOT) { getNextToken(); statementList(); @@ -1401,7 +1680,7 @@ public class PHPParser extends PHPKeywords { } } - public void whileStatement() { + public void whileStatement() throws CoreException { // ':' statement-list 'endwhile' ';' if (token == TT_DDOT) { getNextToken(); @@ -1419,7 +1698,7 @@ public class PHPParser extends PHPKeywords { } } - public void foreachStatement() { + public void foreachStatement() throws CoreException { if (token == TT_DDOT) { getNextToken(); statementList(); @@ -1579,6 +1858,33 @@ public class PHPParser extends PHPKeywords { throwSyntaxError("'(' expected after 'list' keyword."); } break; + // case TT_exit : + // getNextToken(); + // if (token != TT_SEMICOLON) { + // exitStatus(); + // } + // if (token == TT_SEMICOLON) { + // getNextToken(); + // } else { + // if (!phpEnd) { + // throwSyntaxError("';' expected after 'exit' expression."); + // } + // } + // break; + // case TT_die : + // getNextToken(); + // if (token != TT_SEMICOLON) { + // exitStatus(); + // } + // if (token == TT_SEMICOLON) { + // getNextToken(); + // } else { + // if (!phpEnd) { + // throwSyntaxError("';' expected after 'die' expression."); + // } + // } + // break; + // case TT_array : // getNextToken(); // if (token == TT_ARGOPEN) { @@ -1756,6 +2062,24 @@ public class PHPParser extends PHPKeywords { } else if (token == TT_DIVIDEBY) { // *= getNextToken(); logicalinclusiveorExpression(); + } else if (token == TT_MODASSIGN) { // %= + getNextToken(); + logicalinclusiveorExpression(); + } else if (token == TT_ANDASSIGN) { // &= + getNextToken(); + logicalinclusiveorExpression(); + } else if (token == TT_POWASSIGN) { // ^= + getNextToken(); + logicalinclusiveorExpression(); + } else if (token == TT_LSHIFTASSIGN) { // <<= + getNextToken(); + logicalinclusiveorExpression(); + } else if (token == TT_RSHIFTASSIGN) { // >>= + getNextToken(); + logicalinclusiveorExpression(); + } else if (token == TT_TILDEASSIGN) { // ~= + getNextToken(); + logicalinclusiveorExpression(); } } @@ -1829,9 +2153,23 @@ public class PHPParser extends PHPKeywords { } while (true); } + public void ternaryExpression() { + equalityExpression(); + if (token == TT_QUESTIONMARK) { + getNextToken(); + expression(); + if (token == TT_DDOT) { + getNextToken(); + expression(); + } else { + throwSyntaxError("':' expected in ternary operator '? :'."); + } + } + } + public void andExpression() { do { - equalityExpression(); + ternaryExpression(); if (token != TT_AMPERSAND) { return; } @@ -1942,6 +2280,32 @@ public class PHPParser extends PHPKeywords { public void constant() { switch (token) { + case TT_ADD : + getNextToken(); + switch (token) { + case TT_DOUBLE_NUMBER : + getNextToken(); + break; + case TT_INT_NUMBER : + getNextToken(); + break; + default : + throwSyntaxError("Constant expected after '+' presign."); + } + break; + case TT_SUBTRACT : + getNextToken(); + switch (token) { + case TT_DOUBLE_NUMBER : + getNextToken(); + break; + case TT_INT_NUMBER : + getNextToken(); + break; + default : + throwSyntaxError("Constant expected after '-' presign."); + } + break; case TT_null : getNextToken(); break;