X-Git-Url: http://git.phpeclipse.com 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 5848e7d..91620bc 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParser.java @@ -1,23 +1,36 @@ -package net.sourceforge.phpeclipse.phpeditor; - -import java.util.HashMap; - -import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords; - /********************************************************************** -Copyright (c) 2000, 2002 IBM Corp. and others. +Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de All rights reserved. This program and the accompanying materials are made available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html Contributors: - IBM Corporation - Initial implementation Klaus Hartlage - www.eclipseproject.de **********************************************************************/ +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; 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; @@ -62,13 +75,23 @@ public class PHPParser extends PHPKeywords { final static int TT_DDOT = 47; final static int TT_DOTASSIGN = 48; - final static int TT_SET = 49; + final static int TT_ASSIGN = 49; final static int TT_REF = 50; final static int TT_FOREACH = 51; 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_DDOT2 = 62; + final static int TT_AT = 63; + + final static int TT_DOLLAROPEN = 127; final static int TT_ARGOPEN = 128; final static int TT_ARGCLOSE = 129; final static int TT_LISTOPEN = 130; @@ -108,20 +131,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(); + } + + /** + * Create marker for the parse error + */ + private 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 { - getNextToken(); + 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) { @@ -146,7 +199,7 @@ public class PHPParser extends PHPKeywords { * *@see */ - void getChar() { + private void getChar() { if (str.length() > chIndx) { ch = str.charAt(chIndx++); @@ -155,13 +208,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() { + private void getNextToken() throws CoreException { + phpEnd = false; + while (str.length() > chIndx) { ch = str.charAt(chIndx++); token = TT_UNDEFINED; @@ -170,9 +226,22 @@ 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 == '@')) { + if (ch == '$') { + if (str.length() > chIndx) { + if (str.charAt(chIndx) == '{') { + chIndx++; + token = TT_DOLLAROPEN; + return; + } + } + getIdentifier(); + return; + } + if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) { getIdentifier(); return; } @@ -197,7 +266,11 @@ public class PHPParser extends PHPKeywords { chIndx += 2; break; } - chIndx++; + ch = str.charAt(chIndx++); + if (ch == '\n') { + rowCount++; + columnCount = chIndx; + } } continue; } @@ -220,11 +293,9 @@ public class PHPParser extends PHPKeywords { } else if (ch == '"') { openString = false; break; - } else { - if (ch == '\n') { - rowCount++; - columnCount = chIndx; - } + } else if (ch == '\n') { + rowCount++; + columnCount = chIndx; } } if (openString) { @@ -244,11 +315,9 @@ public class PHPParser extends PHPKeywords { } else if (ch == '\'') { openString = false; break; - } else { - if (ch == '\n') { - rowCount++; - columnCount = chIndx; - } + } else if (ch == '\n') { + rowCount++; + columnCount = chIndx; } } if (openString) { @@ -256,6 +325,29 @@ public class PHPParser extends PHPKeywords { } token = TT_STRING_CONSTANT; return; + } else if (ch == '`') { + // read string until end + boolean openString = true; + while (str.length() > chIndx) { + ch = str.charAt(chIndx++); + if (ch == '\\') { + if (str.length() > chIndx) { + ch = str.charAt(chIndx++); + } + } else if (ch == '`') { + openString = false; + break; + } else if (ch == '\n') { + rowCount++; + columnCount = chIndx; + } + } + if (openString) { + throwSyntaxError("Open string character \"`\" at end of file."); + } + setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO); + token = TT_STRING_CONSTANT; + return; } switch (ch) { @@ -288,9 +380,22 @@ public class PHPParser extends PHPKeywords { token = TT_COMMA; break; + case '?' : + token = TT_QUESTIONMARK; + break; + case '@' : + token = TT_AT; + 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 +415,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 +430,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; @@ -393,7 +512,7 @@ public class PHPParser extends PHPKeywords { break; case '=' : - token = TT_SET; + token = TT_ASSIGN; if (str.length() > chIndx) { ch = str.charAt(chIndx); @@ -447,13 +566,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 +596,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,23 +623,30 @@ 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; case ':' : token = TT_DDOT; - + if (str.length() > chIndx) { + if (str.charAt(chIndx) == ':') { + chIndx++; + token = TT_DDOT2; + } + } break; case '#' : token = TT_HASH; @@ -534,9 +671,27 @@ 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() { + private void getIdentifier() { StringBuffer ident = new StringBuffer(); ident.append(ch); @@ -559,7 +714,7 @@ public class PHPParser extends PHPKeywords { } } - void getNumber() { + private void getNumber() { StringBuffer inum = new StringBuffer(); char dFlag = ' '; int numFormat = 10; @@ -644,43 +799,245 @@ 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(); + public void htmlParse(String input) { + int lineNumber = 1; + int startLineNumber = 1; + int startIndex = 0; + char ch; + char ch2; + boolean phpMode = false; + boolean phpFound = false; - statementList(); - if (token != TT_EOF) { - if (token == TT_ARGCLOSE) { - throwSyntaxError("too many closing ')'; end-of-file not reached"); - } - if (token == TT_LISTCLOSE) { - throwSyntaxError("too many closing '}'; end-of-file not reached"); - } - if (token == TT_PARTCLOSE) { - throwSyntaxError("too many closing ']'; end-of-file not reached"); + phpList = new ArrayList(); + currentPHPString = 0; + + 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) { + if (ch == '/' && i < input.length()) { + ch2 = input.charAt(i++); + if (ch2 == '/') { + while (i < input.length()) { + ch = input.charAt(i++); + if (ch == '?' && i < input.length()) { + ch2 = input.charAt(i++); + if (ch2 == '>') { + // php end + phpMode = false; + phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber)); + continue; + } + i--; + } else if (ch == '\n') { + lineNumber++; + break; + } + } + continue; + } else if (ch2 == '*') { + // multi-line comment + while (i < input.length()) { + ch = input.charAt(i++); + if (ch == '\n') { + lineNumber++; + } else if (ch == '*' && i < input.length()) { + ch2 = input.charAt(i++); + if (ch2 == '/') { + break; + } + i--; + } + } + continue; + } else { + i--; + } + } else if (ch == '#') { + while (i < input.length()) { + ch = input.charAt(i++); + if (ch == '?' && i < input.length()) { + ch2 = input.charAt(i++); + if (ch2 == '>') { + // php end + phpMode = false; + phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber)); + continue; + } + i--; + } else if (ch == '\n') { + lineNumber++; + break; + } + } + continue; + } else if (ch == '"') { + ch = ' '; + while (i < input.length()) { + ch = input.charAt(i++); + if (ch == '\n') { + lineNumber++; + } else if (ch == '\\' && i < input.length()) { // escape + i++; + } else if (ch == '"') { + break; + } + } + continue; + } else if (ch == '\'') { + ch = ' '; + while (i < input.length()) { + ch = input.charAt(i++); + if (ch == '\n') { + lineNumber++; + } else if (ch == '\\' && i < input.length()) { // escape + i++; + } else if (ch == '\'') { + break; + } + } + continue; + } + + if (ch == '?' && i < input.length()) { + ch2 = input.charAt(i++); + if (ch2 == '>') { + // php end + phpMode = false; + phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber)); + continue; + } + i--; + } + } } - if (token == TT_ARGOPEN) { - throwSyntaxError("read character '('; end-of-file not reached"); + if (!phpFound) { + setMarker("No PHP source code found.", lineNumber, PHPParser.INFO); + } else { + if (phpMode) { + setMarker("Open PHP tag at end of file.", lineNumber, PHPParser.INFO); + phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber)); + } + // 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) { + private void statement() throws CoreException { + // if (token > TT_KEYWORD && token != TT_list && token != TT_new) { + String keyword = identifier; + if (token == TT_include || token == TT_include_once) { + getNextToken(); + expression(); + if (token == TT_SEMICOLON) { getNextToken(); - expression(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { + } else { + if (!phpEnd) { throwSyntaxError("';' character after 'include' or 'include_once' expected."); } - return; - } else if (token == TT_require || token == TT_require_once) { + } + return; + } else if (token == TT_require || token == TT_require_once) { + getNextToken(); + //constant(); + expression(); + if (token == TT_SEMICOLON) { getNextToken(); - //constant(); - expression(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { + } else { + if (!phpEnd) { throwSyntaxError("';' character after 'require' or 'require_once' expected."); } - return; - } else if (token == TT_if) { + } + return; + } else if (token == TT_if) { + getNextToken(); + if (token == TT_ARGOPEN) { getNextToken(); - if (token == TT_ARGOPEN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'if' keyword."); - } - expression(); - if (token == TT_ARGCLOSE) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'if' condition."); - } - ifStatement(); - return; + } else { + throwSyntaxError("'(' expected after 'if' keyword."); + } + expression(); + if (token == TT_ARGCLOSE) { + getNextToken(); + } else { + throwSyntaxError("')' expected after 'if' condition."); + } + ifStatement(); + return; - } else if (token == TT_switch) { + } else if (token == TT_switch) { + getNextToken(); + if (token == TT_ARGOPEN) { getNextToken(); - if (token == TT_ARGOPEN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'switch' keyword."); - } - expression(); - if (token == TT_ARGCLOSE) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'switch' condition."); - } - switchStatement(); - return; - } else if (token == TT_for) { + } else { + throwSyntaxError("'(' expected after 'switch' keyword."); + } + expression(); + if (token == TT_ARGCLOSE) { getNextToken(); - if (token == TT_ARGOPEN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'for' keyword."); - } + } else { + throwSyntaxError("')' expected after 'switch' condition."); + } + switchStatement(); + return; + } else if (token == TT_for) { + getNextToken(); + if (token == TT_ARGOPEN) { + getNextToken(); + } else { + throwSyntaxError("'(' expected after 'for' keyword."); + } + if (token == TT_SEMICOLON) { + getNextToken(); + } else { + expressionList(); if (token == TT_SEMICOLON) { getNextToken(); } else { - expression(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { - throwSyntaxError("';' character after 'for' expected."); - } + throwSyntaxError("';' expected after 'for'."); } + } + if (token == TT_SEMICOLON) { + getNextToken(); + } else { + expressionList(); if (token == TT_SEMICOLON) { getNextToken(); } else { - expression(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { - throwSyntaxError("';' character after 'for' expected."); - } + throwSyntaxError("';' expected after 'for'."); } + } + if (token == TT_ARGCLOSE) { + getNextToken(); + } else { + expressionList(); if (token == TT_ARGCLOSE) { getNextToken(); } else { - expression(); - if (token == TT_ARGCLOSE) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'for' condition."); - } + throwSyntaxError("')' expected after 'for'."); } - forStatement(); - return; - } else if (token == TT_while) { + } + forStatement(); + return; + } else if (token == TT_while) { + getNextToken(); + if (token == TT_ARGOPEN) { + getNextToken(); + } else { + throwSyntaxError("'(' expected after 'while' keyword."); + } + expression(); + if (token == TT_ARGCLOSE) { + getNextToken(); + } else { + throwSyntaxError("')' expected after 'while' condition."); + } + whileStatement(); + return; + } else if (token == TT_do) { + getNextToken(); + if (token == TT_LISTOPEN) { + getNextToken(); + } else { + throwSyntaxError("'{' expected after 'do' keyword."); + } + if (token != TT_LISTCLOSE) { + statementList(); + } + if (token == TT_LISTCLOSE) { + getNextToken(); + } else { + throwSyntaxError("'}' expected after 'do' keyword."); + } + if (token == TT_while) { getNextToken(); if (token == TT_ARGOPEN) { getNextToken(); @@ -820,143 +1212,172 @@ public class PHPParser extends PHPKeywords { } else { throwSyntaxError("')' expected after 'while' condition."); } - whileStatement(); - return; - } else if (token == TT_foreach) { + } else { + throwSyntaxError("'while' expected after 'do' keyword."); + } + if (token == TT_SEMICOLON) { getNextToken(); - if (token == TT_ARGOPEN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'foreach' keyword."); - } - expression(); - if (token == TT_as) { - getNextToken(); - } else { - throwSyntaxError("'as' expected after 'foreach' exxpression."); + } else { + if (!phpEnd) { + throwSyntaxError("';' expected after do-while statement."); } + } + return; + } else if (token == TT_foreach) { + getNextToken(); + if (token == TT_ARGOPEN) { + getNextToken(); + } else { + throwSyntaxError("'(' expected after 'foreach' keyword."); + } + expression(); + if (token == TT_as) { + getNextToken(); + } else { + throwSyntaxError("'as' expected after 'foreach' exxpression."); + } + variable(); + if (token == TT_FOREACH) { + getNextToken(); variable(); - if (token == TT_FOREACH) { - getNextToken(); - variable(); - } - if (token == TT_ARGCLOSE) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'foreach' expression."); - } - foreachStatement(); - return; + } + if (token == TT_ARGCLOSE) { + getNextToken(); + } else { + throwSyntaxError("')' expected after 'foreach' expression."); + } + foreachStatement(); + return; - } else if (token == TT_continue || token == TT_break || token == TT_return) { + } else if (token == TT_continue || token == TT_break || token == TT_return) { + getNextToken(); + if (token != TT_SEMICOLON) { + expression(); + } + if (token == TT_SEMICOLON) { getNextToken(); - if (token != TT_SEMICOLON) { - expression(); - } - if (token == TT_SEMICOLON) { - getNextToken(); - } else { + } else { + if (!phpEnd) { throwSyntaxError("';' expected after 'continue', 'break' or 'return'."); } - return; + } + return; - } else if (token == TT_echo) { + } else if (token == TT_echo) { + getNextToken(); + expressionList(); + if (token == TT_SEMICOLON) { getNextToken(); - expressionList(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { + } else { + if (!phpEnd) { throwSyntaxError("';' expected after 'echo' statement."); } - return; - - } else if (token == TT_print) { + } + return; + } else if (token == TT_print) { + getNextToken(); + expression(); + if (token == TT_SEMICOLON) { getNextToken(); - expression(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { + } else { + if (!phpEnd) { throwSyntaxError("';' expected after 'print' statement."); } - return; + } + return; - } else if (token == TT_global || token == TT_static) { + } else if (token == TT_global || token == TT_static) { + getNextToken(); + variableList(); + if (token == TT_SEMICOLON) { getNextToken(); - variableList(); - if (token == TT_SEMICOLON) { - getNextToken(); - } else { + } else { + if (!phpEnd) { throwSyntaxError("';' expected after 'global' or 'static' statement."); } - return; + } + return; - } else if (token == TT_unset) { + // } else if (token == TT_unset) { + // getNextToken(); + // if (token == TT_ARGOPEN) { + // getNextToken(); + // } else { + // throwSyntaxError("'(' expected after 'unset' keyword."); + // } + // variableList(); + // if (token == TT_ARGCLOSE) { + // getNextToken(); + // } else { + // throwSyntaxError("')' expected after 'unset' statement."); + // } + // if (token == TT_SEMICOLON) { + // getNextToken(); + // } else { + // 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 (!phpEnd) { + // throwSyntaxError("';' expected after 'exit' or 'die' statement."); + // } + // } + // return; + + } else if (token == TT_define) { + getNextToken(); + if (token == TT_ARGOPEN) { getNextToken(); - if (token == TT_ARGOPEN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'unset' keyword."); - } - variableList(); - if (token == TT_ARGCLOSE) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'unset' statement."); - } - if (token == TT_SEMICOLON) { - getNextToken(); - } else { - throwSyntaxError("';' expected after 'unset' statement."); - } - return; - - } else if (token == TT_exit || token == TT_die) { + } else { + throwSyntaxError("'(' expected after 'define' keyword."); + } + expression(); + if (token == TT_COMMA) { getNextToken(); - if (token != TT_SEMICOLON) { - exitStatus(); - } - if (token == TT_SEMICOLON) { - getNextToken(); - } else { - throwSyntaxError("';' expected after 'exit' or 'die' statement."); - } - return; - - } else if (token == TT_define) { + } else { + throwSyntaxError("',' expected after first 'define' constant."); + } + expression(); + if (token == TT_COMMA) { getNextToken(); - if (token == TT_ARGOPEN) { - getNextToken(); - } else { - throwSyntaxError("'(' expected after 'define' keyword."); - } - constant(); - if (token == TT_COMMA) { - getNextToken(); - } else { - throwSyntaxError("',' expected after first 'define' constant."); - } - constant(); - if (token == TT_ARGCLOSE) { - getNextToken(); - } else { - throwSyntaxError("')' expected after 'define' statement."); - } - if (token == TT_SEMICOLON) { - getNextToken(); - } else { - throwSyntaxError("';' expected after 'define' statement."); - } - return; - } else if (token == TT_function) { + expression(); + } + if (token == TT_ARGCLOSE) { getNextToken(); - functionDefinition(); - return; } else { - throwSyntaxError("Unexpected keyword '" + keyword + "'"); + throwSyntaxError("')' expected after 'define' statement."); } - + if (token == TT_SEMICOLON) { + getNextToken(); + } else { + if (!phpEnd) { + throwSyntaxError("';' expected after 'define' statement."); + } + } + return; + } else if (token == TT_function) { + getNextToken(); + functionDefinition(); + return; + } else if (token == TT_class) { + getNextToken(); + classDeclarator(); + classBody(); + return; + // } else { + // throwSyntaxError("Unexpected keyword '" + keyword + "'"); } else if (token == TT_LISTOPEN) { - // compundStatement + // compoundStatement getNextToken(); if (token != TT_LISTCLOSE) { statementList(); @@ -975,19 +1396,103 @@ public class PHPParser extends PHPKeywords { getNextToken(); return; } else { - throwSyntaxError("';' expected after expression."); + if (!phpEnd) { + throwSyntaxError("';' expected after expression."); + } } } + } + private void classDeclarator() throws CoreException { + //identifier + //identifier 'extends' identifier + if (token == TT_IDENTIFIER) { + getNextToken(); + if (token == TT_extends) { + getNextToken(); + if (token == TT_IDENTIFIER) { + getNextToken(); + } else { + throwSyntaxError("Class name expected after keyword 'extends'."); + } + } + } else { + throwSyntaxError("Class name expected after keyword 'class'."); + } } - public void functionDefinition() { + private void classBody() throws CoreException { + //'{' [class-element-list] '}' + if (token == TT_LISTOPEN) { + getNextToken(); + if (token != TT_LISTCLOSE) { + classElementList(); + } + if (token == TT_LISTCLOSE) { + getNextToken(); + } else { + throwSyntaxError("'}' expected at end of class body."); + } + } else { + throwSyntaxError("'{' expected at start of class body."); + } + } + + private void classElementList() throws CoreException { + do { + classElement(); + } while (token == TT_function || token == TT_var); + } + + private void classElement() throws CoreException { + //class-property + //function-definition + if (token == TT_function) { + getNextToken(); + functionDefinition(); + } else if (token == TT_var) { + getNextToken(); + classProperty(); + } else { + throwSyntaxError("'function' or 'var' expected."); + } + } + + private void classProperty() throws CoreException { + //'var' variable ';' + //'var' variable '=' constant ';' + do { + if (token == TT_VARIABLE) { + getNextToken(); + if (token == TT_ASSIGN) { + getNextToken(); + constant(); + } + } else { + throwSyntaxError("Variable expected after keyword 'var'."); + } + if (token != TT_COMMA) { + break; + } + getNextToken(); + } while (true); + if (token == TT_SEMICOLON) { + getNextToken(); + } else { + throwSyntaxError("';' expected after variable declaration."); + } + } + + private void functionDefinition() throws CoreException { functionDeclarator(); compoundStatement(); } - public void functionDeclarator() { + private void functionDeclarator() throws CoreException { //identifier '(' [parameter-list] ')' + if (token == TT_AMPERSAND) { + getNextToken(); + } if (token == TT_IDENTIFIER) { getNextToken(); if (token == TT_ARGOPEN) { @@ -1006,7 +1511,7 @@ public class PHPParser extends PHPKeywords { } } // - public void parameterList() { + private void parameterList() throws CoreException { //parameter-declaration //parameter-list ',' parameter-declaration do { @@ -1018,13 +1523,21 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void parameterDeclaration() { + private void parameterDeclaration() throws CoreException { //variable //variable-reference + if (token == TT_AMPERSAND) { + getNextToken(); + if (token == TT_VARIABLE) { + getNextToken(); + } else { + throwSyntaxError("Variable expected after reference operator '&'."); + } + } //variable '=' constant if (token == TT_VARIABLE) { getNextToken(); - if (token == TT_SET) { + if (token == TT_ASSIGN) { getNextToken(); constant(); } @@ -1032,7 +1545,7 @@ public class PHPParser extends PHPKeywords { } } - public void labeledStatementList() { + private void labeledStatementList() throws CoreException { if (token != TT_case && token != TT_default) { throwSyntaxError("'case' or 'default' expected."); } @@ -1042,6 +1555,16 @@ public class PHPParser extends PHPKeywords { constant(); if (token == TT_DDOT) { getNextToken(); + if (token == TT_case || token == TT_default) { // empty case statement ? + continue; + } + statementList(); + } else if (token == TT_SEMICOLON) { + setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO); + getNextToken(); + if (token == TT_case) { // empty case statement ? + continue; + } statementList(); } else { throwSyntaxError("':' character after 'case' constant expected."); @@ -1081,11 +1604,11 @@ public class PHPParser extends PHPKeywords { // } // } - public void expressionStatement() { - } + // public void expressionStatement() { + // } - public void inclusionStatement() { - } + // private void inclusionStatement() { + // } // public void compoundStatement() { // } @@ -1111,7 +1634,7 @@ public class PHPParser extends PHPKeywords { // public void definitionStatement() { // } - public void ifStatement() { + private void ifStatement() throws CoreException { // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';' if (token == TT_DDOT) { getNextToken(); @@ -1168,7 +1691,8 @@ public class PHPParser extends PHPKeywords { } } } - public void elseifStatementList() { + + private void elseifStatementList() throws CoreException { do { elseifStatement(); switch (token) { @@ -1195,7 +1719,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void elseifStatement() { + private void elseifStatement() throws CoreException { if (token == TT_ARGOPEN) { getNextToken(); expression(); @@ -1211,7 +1735,7 @@ public class PHPParser extends PHPKeywords { } } - public void switchStatement() { + private void switchStatement() throws CoreException { if (token == TT_DDOT) { // ':' [labeled-statement-list] 'endswitch' ';' getNextToken(); @@ -1241,7 +1765,7 @@ public class PHPParser extends PHPKeywords { } } - public void forStatement() { + private void forStatement() throws CoreException { if (token == TT_DDOT) { getNextToken(); statementList(); @@ -1258,7 +1782,7 @@ public class PHPParser extends PHPKeywords { } } - public void whileStatement() { + private void whileStatement() throws CoreException { // ':' statement-list 'endwhile' ';' if (token == TT_DDOT) { getNextToken(); @@ -1276,7 +1800,7 @@ public class PHPParser extends PHPKeywords { } } - public void foreachStatement() { + private void foreachStatement() throws CoreException { if (token == TT_DDOT) { getNextToken(); statementList(); @@ -1293,7 +1817,7 @@ public class PHPParser extends PHPKeywords { } } - public void exitStatus() { + private void exitStatus() throws CoreException { if (token == TT_ARGOPEN) { getNextToken(); } else { @@ -1309,7 +1833,7 @@ public class PHPParser extends PHPKeywords { } } - public void expressionList() { + private void expressionList() throws CoreException { do { expression(); if (token == TT_COMMA) { @@ -1320,7 +1844,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void expression() { + private void expression() throws CoreException { // if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) { // getNextToken(); // } else { @@ -1331,10 +1855,23 @@ public class PHPParser extends PHPKeywords { // } } - public void postfixExpression() { + private void postfixExpression() throws CoreException { String ident; boolean castFlag = false; switch (token) { + case TT_new : + getNextToken(); + expression(); + break; + case TT_null : + getNextToken(); + break; + case TT_false : + getNextToken(); + break; + case TT_true : + getNextToken(); + break; case TT_STRING_CONSTANT : getNextToken(); break; @@ -1377,6 +1914,14 @@ public class PHPParser extends PHPKeywords { case TT_INT_NUMBER : getNextToken(); break; + case TT_DOLLAROPEN : + getNextToken(); + expression(); + if (token != TT_LISTCLOSE) { + throwSyntaxError("'}' expected after indirect variable token '${'."); + } + getNextToken(); + break; case TT_VARIABLE : ident = identifier; getNextToken(); @@ -1387,6 +1932,15 @@ public class PHPParser extends PHPKeywords { throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression."); } getNextToken(); + } else if (token == TT_ARGOPEN) { + getNextToken(); + if (token != TT_ARGCLOSE) { + expressionList(); + if (token != TT_ARGCLOSE) { + throwSyntaxError("')' expected after variable '" + ident + "' in postfix-expression."); + } + } + getNextToken(); } break; case TT_IDENTIFIER : @@ -1423,6 +1977,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) { @@ -1455,25 +2036,61 @@ public class PHPParser extends PHPKeywords { } getNextToken(); break; + case TT_DDOT2 : // :: case TT_REF : // -> - switch (token) { - case TT_VARIABLE : - getNextToken(); - break; - case TT_IDENTIFIER : - getNextToken(); - break; - case TT_LISTOPEN : + getNextToken(); + if (token > TT_KEYWORD) { + ident = identifier; + setMarker("Avoid using keyword '" + ident + "' as variable name.", rowCount, PHPParser.INFO); + getNextToken(); + if (token == TT_ARGOPEN) { getNextToken(); - expression(); - if (token != TT_LISTCLOSE) { - throwSyntaxError("} expected in postfix-expression."); + expressionList(); + if (token != TT_ARGCLOSE) { + throwSyntaxError(") expected after identifier '" + ident + "'."); } getNextToken(); - break; - default : - throwSyntaxError("Syntax error after '->' token."); + } + break; + } else { + switch (token) { + case TT_VARIABLE : + ident = identifier; + getNextToken(); + // if (token == TT_ARGOPEN) { + // getNextToken(); + // expressionList(); + // if (token != TT_ARGCLOSE) { + // throwSyntaxError(") expected after variable '" + ident + "'."); + // } + // getNextToken(); + // } + break; + case TT_IDENTIFIER : + ident = identifier; + getNextToken(); + if (token == TT_ARGOPEN) { + getNextToken(); + expressionList(); + if (token != TT_ARGCLOSE) { + throwSyntaxError(") expected after identifier '" + ident + "'."); + } + getNextToken(); + } + break; + case TT_LISTOPEN : + getNextToken(); + expression(); + if (token != TT_LISTCLOSE) { + throwSyntaxError("} expected in postfix-expression."); + } + getNextToken(); + break; + default : + throwSyntaxError("Syntax error after '->' token."); + } } + break; case TT_INCREMENT : getNextToken(); break; @@ -1483,10 +2100,11 @@ public class PHPParser extends PHPKeywords { default : while_flag = false; } + } while (while_flag); } - public void unaryExpression() { + private void unaryExpression() throws CoreException { switch (token) { case TT_INCREMENT : getNextToken(); @@ -1496,7 +2114,11 @@ public class PHPParser extends PHPKeywords { getNextToken(); unaryExpression(); break; - //'&' '*' '+' '-' '~' '!' + // '@' '&' '*' '+' '-' '~' '!' + case TT_AT : + getNextToken(); + castExpression(); + break; case TT_AMPERSAND : getNextToken(); castExpression(); @@ -1526,7 +2148,7 @@ public class PHPParser extends PHPKeywords { } } - public void castExpression() { + private void castExpression() throws CoreException { // if (token == TT_ARGOPEN) { // getNextToken(); // typeName(); @@ -1538,7 +2160,7 @@ public class PHPParser extends PHPKeywords { unaryExpression(); } - public void typeName() { + private void typeName() throws CoreException { //'string' 'unset' 'array' 'object' //'bool' 'boolean' //'real' 'double' 'float' @@ -1557,9 +2179,9 @@ public class PHPParser extends PHPKeywords { throwSyntaxError("Expected type cast '( )'; Got '" + ident + "'."); } - public void assignExpression() { + private void assignExpression() throws CoreException { castExpression(); - if (token == TT_SET) { // = + if (token == TT_ASSIGN) { // = getNextToken(); logicalinclusiveorExpression(); } else if (token == TT_DOTASSIGN) { // .= @@ -1568,10 +2190,40 @@ public class PHPParser extends PHPKeywords { } else if (token == TT_FOREACH) { // => getNextToken(); logicalinclusiveorExpression(); + } else if (token == TT_ADDTO) { // += + getNextToken(); + logicalinclusiveorExpression(); + } else if (token == TT_SUBTRACTFROM) { // -= + getNextToken(); + logicalinclusiveorExpression(); + } else if (token == TT_TIMESBY) { // *= + getNextToken(); + logicalinclusiveorExpression(); + } 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(); } } - public void multiplicativeExpression() { + private void multiplicativeExpression() throws CoreException { do { assignExpression(); if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) { @@ -1581,7 +2233,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void concatenationExpression() { + private void concatenationExpression() throws CoreException { do { multiplicativeExpression(); if (token != TT_DOT) { @@ -1591,7 +2243,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void additiveExpression() { + private void additiveExpression() throws CoreException { do { concatenationExpression(); if (token != TT_ADD && token != TT_SUBTRACT) { @@ -1601,7 +2253,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void shiftExpression() { + private void shiftExpression() throws CoreException { do { additiveExpression(); if (token != TT_LSHIFT && token != TT_RSHIFT) { @@ -1611,7 +2263,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void relationalExpression() { + private void relationalExpression() throws CoreException { do { shiftExpression(); if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) { @@ -1621,7 +2273,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void identicalExpression() { + private void identicalExpression() throws CoreException { do { relationalExpression(); if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) { @@ -1631,7 +2283,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void equalityExpression() { + private void equalityExpression() throws CoreException { do { identicalExpression(); if (token != TT_EQUAL && token != TT_UNEQUAL) { @@ -1641,9 +2293,23 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void andExpression() { + private void ternaryExpression() throws CoreException { + equalityExpression(); + if (token == TT_QUESTIONMARK) { + getNextToken(); + expression(); + if (token == TT_DDOT) { + getNextToken(); + expression(); + } else { + throwSyntaxError("':' expected in ternary operator '? :'."); + } + } + } + + private void andExpression() throws CoreException { do { - equalityExpression(); + ternaryExpression(); if (token != TT_AMPERSAND) { return; } @@ -1651,7 +2317,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void exclusiveorExpression() { + private void exclusiveorExpression() throws CoreException { do { andExpression(); if (token != TT_POW) { @@ -1661,7 +2327,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void inclusiveorExpression() { + private void inclusiveorExpression() throws CoreException { do { exclusiveorExpression(); if (token != TT_LINE) { @@ -1671,7 +2337,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void booleanandExpression() { + private void booleanandExpression() throws CoreException { do { inclusiveorExpression(); if (token != TT_AND) { @@ -1681,7 +2347,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void booleanorExpression() { + private void booleanorExpression() throws CoreException { do { booleanandExpression(); if (token != TT_OR) { @@ -1691,7 +2357,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void logicalandExpression() { + private void logicalandExpression() throws CoreException { do { booleanorExpression(); if (token != TT_and) { @@ -1701,7 +2367,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void logicalexclusiveorExpression() { + private void logicalexclusiveorExpression() throws CoreException { do { logicalandExpression(); if (token != TT_xor) { @@ -1711,7 +2377,7 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void logicalinclusiveorExpression() { + private void logicalinclusiveorExpression() throws CoreException { do { logicalexclusiveorExpression(); if (token != TT_or) { @@ -1733,7 +2399,7 @@ public class PHPParser extends PHPKeywords { // } // } - public void variableList() { + private void variableList() throws CoreException { do { variable(); if (token == TT_COMMA) { @@ -1744,16 +2410,87 @@ public class PHPParser extends PHPKeywords { } while (true); } - public void variable() { - if (token == TT_VARIABLE) { + private void variable() throws CoreException { + if (token == TT_DOLLAROPEN) { + getNextToken(); + expression(); + ; + if (token != TT_LISTCLOSE) { + throwSyntaxError("'}' expected after indirect variable token '${'."); + } getNextToken(); } else { - throwSyntaxError("$-variable expected in variable-list."); + if (token == TT_VARIABLE) { + getNextToken(); + if (token == TT_PARTOPEN) { + getNextToken(); + expression(); + if (token != TT_PARTCLOSE) { + throwSyntaxError("']' expected in variable-list."); + } + getNextToken(); + } else if (token == TT_ASSIGN) { + getNextToken(); + constant(); + } + } else { + throwSyntaxError("$-variable expected in variable-list."); + } } } - public void constant() { + private void constant() throws CoreException { + String ident; 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; + case TT_false : + getNextToken(); + break; + case TT_true : + getNextToken(); + break; + case TT_IDENTIFIER : + ident = identifier; + getNextToken(); + if (token == TT_ARGOPEN) { + getNextToken(); + if (token != TT_ARGCLOSE) { + expressionList(); + if (token != TT_ARGCLOSE) { + throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression."); + } + } + getNextToken(); + } + break; case TT_STRING_CONSTANT : getNextToken(); break;