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. 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 **********************************************************************/ 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; // current character char ch; // current token int token; // row counter for syntax errors: int rowCount; // column counter for syntax errors: int columnCount; int chIndx; // current identifier String identifier; Long longNumber; Double doubleNumber; final static int TT_EOF = 0; final static int TT_UNDEFINED = 1; final static int TT_MOD = 30; final static int TT_NOT = 31; final static int TT_DOT = 32; final static int TT_POW = 33; final static int TT_DIV = 34; final static int TT_MULTIPLY = 35; final static int TT_SUBTRACT = 36; final static int TT_ADD = 37; final static int TT_EQUAL = 38; final static int TT_UNEQUAL = 39; final static int TT_GREATER = 40; final static int TT_GREATEREQUAL = 41; final static int TT_LESS = 42; final static int TT_LESSEQUAL = 43; final static int TT_AND = 44; final static int TT_OR = 45; final static int TT_HASH = 46; final static int TT_DDOT = 47; final static int TT_DOTASSIGN = 48; 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_ARGOPEN = 128; final static int TT_ARGCLOSE = 129; final static int TT_LISTOPEN = 130; final static int TT_LISTCLOSE = 131; final static int TT_PARTOPEN = 132; final static int TT_PARTCLOSE = 133; final static int TT_COMMA = 134; final static int TT_STRING = 136; final static int TT_IDENTIFIER = 138; final static int TT_DIGIT = 139; final static int TT_SEMICOLON = 140; final static int TT_SLOT = 141; final static int TT_SLOTSEQUENCE = 142; final static int TT_DECREMENT = 144; final static int TT_INCREMENT = 145; final static int TT_ADDTO = 146; final static int TT_DIVIDEBY = 147; final static int TT_SUBTRACTFROM = 148; final static int TT_TIMESBY = 149; final static int TT_VARIABLE = 150; final static int TT_INT_NUMBER = 151; final static int TT_DOUBLE_NUMBER = 152; final static int TT_INTERPOLATED_STRING = 153; final static int TT_STRING_CONSTANT = 154; final static int TT_LSHIFT = 155; final static int TT_RSHIFT = 156; final static int TT_EX_EQUAL = 157; final static int TT_EX_UNEQUAL = 158; final static int TT_LINE = 159; // final static int TT_AT = 153; // @ /** * Class Constructor. * *@param s *@param sess Description of Parameter *@see */ 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 */ 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) { if (str.length() < chIndx) { chIndx--; } // read until end-of-line int eol = chIndx; while (str.length() > eol) { ch = str.charAt(eol++); if (ch == '\n') { eol--; break; } } throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error); } /** * Method Declaration. * *@see */ void getChar() { if (str.length() > chIndx) { ch = str.charAt(chIndx++); return; } chIndx = str.length() + 1; ch = ' '; // 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; if (ch == '\n') { rowCount++; 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(); return; } if (ch >= '0' && ch <= '9') { getNumber(); return; } if (ch == '/') { if (str.length() > chIndx) { if (str.charAt(chIndx) == '/') { chIndx++; // read comment until end of line: while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) { chIndx++; } continue; } else if (str.charAt(chIndx) == '*') { chIndx++; // multi line comment: while (str.length() > chIndx) { if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') { chIndx += 2; break; } ch = str.charAt(chIndx++); if (ch == '\n') { rowCount++; columnCount = chIndx; } } continue; } } } else if (ch == '#') { // read comment until end of line: while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) { chIndx++; } continue; } 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."); } token = TT_INTERPOLATED_STRING; 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."); } token = TT_STRING_CONSTANT; return; } switch (ch) { case '(' : token = TT_ARGOPEN; break; case ')' : token = TT_ARGCLOSE; break; case '{' : token = TT_LISTOPEN; break; case '}' : token = TT_LISTCLOSE; break; case '[' : token = TT_PARTOPEN; break; case ']' : token = TT_PARTCLOSE; break; case ',' : 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; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_DOTASSIGN; break; } } break; case '"' : token = TT_STRING; break; case '%' : token = TT_MOD; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_MODASSIGN; break; } } break; case ';' : token = TT_SEMICOLON; break; case '^' : token = TT_POW; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_POWASSIGN; break; } } break; case '/' : token = TT_DIV; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_DIVIDEBY; break; } } break; case '*' : token = TT_MULTIPLY; if (str.length() > chIndx) { if (str.charAt(chIndx) == '*') { chIndx++; token = TT_POW; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TT_TIMESBY; break; } } break; case '+' : token = TT_ADD; if (str.length() > chIndx) { if (str.charAt(chIndx) == '+') { chIndx++; token = TT_INCREMENT; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TT_ADDTO; break; } } break; case '-' : token = TT_SUBTRACT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '-') { chIndx++; token = TT_DECREMENT; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TT_SUBTRACTFROM; break; } if (str.charAt(chIndx) == '>') { chIndx++; token = TT_REF; break; } } break; case '=' : token = TT_ASSIGN; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TT_EQUAL; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TT_EX_EQUAL; } } break; } if (ch == '>') { chIndx++; token = TT_FOREACH; break; } } break; case '!' : token = TT_NOT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_UNEQUAL; if (str.length() > chIndx) { ch = str.charAt(chIndx); if (ch == '=') { chIndx++; token = TT_EX_UNEQUAL; } } break; } } break; case '>' : token = TT_GREATER; if (str.length() > chIndx) { 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; } } break; case '<' : token = TT_LESS; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_LESSEQUAL; break; } if (str.charAt(chIndx) == '<') { chIndx++; token = TT_LSHIFT; if (str.length() > chIndx) { if (str.charAt(chIndx) == '=') { chIndx++; token = TT_LSHIFTASSIGN; break; } } break; } } break; case '|' : token = TT_LINE; if (str.length() > chIndx) { if (str.charAt(chIndx) == '|') { chIndx++; token = TT_OR; break; } } break; case '&' : token = TT_AMPERSAND; if (str.length() > chIndx) { if (str.charAt(chIndx) == '&') { chIndx++; token = TT_AND; break; } if (str.charAt(chIndx) == '=') { chIndx++; token = TT_ANDASSIGN; break; } break; } break; case ':' : token = TT_DDOT; break; case '#' : token = TT_HASH; break; // case '@' : // token = TT_AT; // // break; default : throwSyntaxError("unexpected character: '" + ch + "'"); } if (token == TT_UNDEFINED) { throwSyntaxError("token not found"); } return; } } 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() { StringBuffer ident = new StringBuffer(); ident.append(ch); if (ch == '$') { token = TT_VARIABLE; } else { token = TT_IDENTIFIER; } getChar(); while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) { ident.append(ch); getChar(); } identifier = ident.toString(); chIndx--; Integer i = (Integer) keywordMap.get(identifier.toLowerCase()); if (i != null) { token = i.intValue(); } } void getNumber() { StringBuffer inum = new StringBuffer(); char dFlag = ' '; int numFormat = 10; // save first digit char firstCh = ch; inum.append(ch); getChar(); // determine number conversions: if (firstCh == '0') { switch (ch) { case 'b' : numFormat = 2; getChar(); break; case 'B' : numFormat = 2; getChar(); break; case 'o' : numFormat = 8; getChar(); break; case 'O' : numFormat = 8; getChar(); break; case 'x' : numFormat = 16; getChar(); break; case 'X' : numFormat = 16; getChar(); break; } } if (numFormat == 16) { while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) { inum.append(ch); getChar(); } } else { while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) { if ((ch == '.') || (ch == 'E') || (ch == 'e')) { if (ch == '.' && dFlag != ' ') { break; } if ((dFlag == 'E') || (dFlag == 'e')) { break; } dFlag = ch; inum.append(ch); getChar(); if ((ch == '-') || (ch == '+')) { inum.append(ch); getChar(); } } else { inum.append(ch); getChar(); } } } chIndx--; try { if (dFlag != ' ') { doubleNumber = new Double(inum.toString()); token = TT_DOUBLE_NUMBER; return; } else { longNumber = Long.valueOf(inum.toString(), numFormat); token = TT_INT_NUMBER; return; } } catch (Throwable e) { throwSyntaxError("Number format error: " + inum.toString()); } } 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 (!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) { getNextToken(); expression(); if (token == TT_SEMICOLON) { getNextToken(); } else { if (!phpEnd) { throwSyntaxError("';' character after 'include' or 'include_once' expected."); } } return; } else if (token == TT_require || token == TT_require_once) { getNextToken(); //constant(); expression(); if (token == TT_SEMICOLON) { getNextToken(); } else { if (!phpEnd) { throwSyntaxError("';' character after 'require' or 'require_once' expected."); } } return; } else if (token == TT_if) { 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 if (token == TT_switch) { 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) { getNextToken(); if (token == TT_ARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'for' keyword."); } if (token == TT_SEMICOLON) { getNextToken(); } else { expression(); if (token == TT_SEMICOLON) { getNextToken(); } else { throwSyntaxError("';' character after 'for' expected."); } } if (token == TT_SEMICOLON) { getNextToken(); } else { expression(); if (token == TT_SEMICOLON) { getNextToken(); } else { throwSyntaxError("';' character after 'for' expected."); } } if (token == TT_ARGCLOSE) { getNextToken(); } else { expression(); if (token == TT_ARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'for' condition."); } } 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(); } else { throwSyntaxError("'(' expected after 'while' keyword."); } expression(); if (token == TT_ARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'while' condition."); } } else { throwSyntaxError("'while' expected after 'do' keyword."); } if (token == TT_SEMICOLON) { getNextToken(); } 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_ARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'foreach' expression."); } foreachStatement(); return; } else if (token == TT_continue || token == TT_break || token == TT_return) { getNextToken(); if (token != TT_SEMICOLON) { expression(); } if (token == TT_SEMICOLON) { getNextToken(); } else { if (!phpEnd) { throwSyntaxError("';' expected after 'continue', 'break' or 'return'."); } } return; } else if (token == TT_echo) { getNextToken(); expressionList(); if (token == TT_SEMICOLON) { getNextToken(); } else { if (!phpEnd) { throwSyntaxError("';' expected after 'echo' statement."); } } return; } else if (token == TT_print) { getNextToken(); expression(); if (token == TT_SEMICOLON) { getNextToken(); } else { if (!phpEnd) { throwSyntaxError("';' expected after 'print' statement."); } } return; } else if (token == TT_global || token == TT_static) { getNextToken(); variableList(); if (token == TT_SEMICOLON) { getNextToken(); } else { if (!phpEnd) { throwSyntaxError("';' expected after 'global' or 'static' statement."); } } return; } 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(); } 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 { 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) { // compoundStatement getNextToken(); if (token != TT_LISTCLOSE) { statementList(); } if (token == TT_LISTCLOSE) { getNextToken(); return; } else { throwSyntaxError("'}' expected."); } } else { if (token != TT_SEMICOLON) { expression(); } if (token == TT_SEMICOLON) { getNextToken(); return; } else { if (!phpEnd) { throwSyntaxError("';' expected after expression."); } } } } public void classDeclarator() { //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 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."); } } public void classElementList() throws CoreException { do { classElement(); } while (token == TT_function || token == TT_var); } public 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."); } } public void classProperty() { //'var' variable ';' //'var' variable '=' constant ';' if (token == TT_VARIABLE) { getNextToken(); if (token == TT_ASSIGN) { getNextToken(); constant(); if (token == TT_SEMICOLON) { getNextToken(); } else { throwSyntaxError("';' expected after variable declaration."); } } else if (token == TT_SEMICOLON) { getNextToken(); } else { throwSyntaxError("';' or '=' expected after variable declaration."); } } else { throwSyntaxError("Variable expected after keyword 'var'."); } } public void functionDefinition() throws CoreException { functionDeclarator(); compoundStatement(); } public void functionDeclarator() { //identifier '(' [parameter-list] ')' if (token == TT_IDENTIFIER) { getNextToken(); if (token == TT_ARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected in function declaration."); } if (token != TT_ARGCLOSE) { parameterList(); } if (token != TT_ARGCLOSE) { throwSyntaxError("')' expected in function declaration."); } else { getNextToken(); } } } // public void parameterList() { //parameter-declaration //parameter-list ',' parameter-declaration do { parameterDeclaration(); if (token != TT_COMMA) { break; } getNextToken(); } while (true); } public void parameterDeclaration() { //variable //variable-reference //variable '=' constant if (token == TT_VARIABLE) { getNextToken(); if (token == TT_ASSIGN) { getNextToken(); constant(); } return; } } public void labeledStatementList() throws CoreException { if (token != TT_case && token != TT_default) { throwSyntaxError("'case' or 'default' expected."); } do { if (token == TT_case) { getNextToken(); constant(); 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."); } } else { // TT_default getNextToken(); if (token == TT_DDOT) { getNextToken(); statementList(); } else { throwSyntaxError("':' character after 'default' expected."); } } } while (token == TT_case || token == TT_default); } // public void labeledStatement() { // if (token == TT_case) { // getNextToken(); // constant(); // if (token == TT_DDOT) { // getNextToken(); // statement(); // } else { // throwSyntaxError("':' character after 'case' constant expected."); // } // return; // } else if (token == TT_default) { // getNextToken(); // if (token == TT_DDOT) { // getNextToken(); // statement(); // } else { // throwSyntaxError("':' character after 'default' expected."); // } // return; // } // } public void expressionStatement() { } public void inclusionStatement() { } // public void compoundStatement() { // } // public void selectionStatement() { // } // // public void iterationStatement() { // } // // public void jumpStatement() { // } // // public void outputStatement() { // } // // public void scopeStatement() { // } // // public void flowStatement() { // } // // public void definitionStatement() { // } public void ifStatement() throws CoreException { // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';' if (token == TT_DDOT) { getNextToken(); statementList(); switch (token) { case TT_else : getNextToken(); if (token == TT_DDOT) { getNextToken(); statementList(); } else { if (token == TT_if) { //'else if' getNextToken(); elseifStatementList(); } else { throwSyntaxError("':' expected after 'else'."); } } break; case TT_elseif : getNextToken(); elseifStatementList(); break; } if (token != TT_endif) { throwSyntaxError("'endif' expected."); } getNextToken(); if (token != TT_SEMICOLON) { throwSyntaxError("';' expected after if-statement."); } getNextToken(); } else { // statement [else-statement] statement(); if (token == TT_elseif) { getNextToken(); if (token == TT_ARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected after 'elseif' keyword."); } expression(); if (token == TT_ARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'elseif' condition."); } ifStatement(); } else if (token == TT_else) { getNextToken(); statement(); } } } public void elseifStatementList() throws CoreException { do { elseifStatement(); switch (token) { case TT_else : getNextToken(); if (token == TT_DDOT) { getNextToken(); statementList(); return; } else { if (token == TT_if) { //'else if' getNextToken(); } else { throwSyntaxError("':' expected after 'else'."); } } break; case TT_elseif : getNextToken(); break; default : return; } } while (true); } public void elseifStatement() throws CoreException { if (token == TT_ARGOPEN) { getNextToken(); expression(); if (token != TT_ARGOPEN) { throwSyntaxError("')' expected in else-if-statement."); } getNextToken(); if (token != TT_DDOT) { throwSyntaxError("':' expected in else-if-statement."); } getNextToken(); statementList(); } } public void switchStatement() throws CoreException { if (token == TT_DDOT) { // ':' [labeled-statement-list] 'endswitch' ';' getNextToken(); labeledStatementList(); if (token != TT_endswitch) { throwSyntaxError("'endswitch' expected."); } getNextToken(); if (token != TT_SEMICOLON) { throwSyntaxError("';' expected after switch-statement."); } getNextToken(); } else { // '{' [labeled-statement-list] '}' if (token != TT_LISTOPEN) { throwSyntaxError("'{' expected in switch statement."); } getNextToken(); if (token != TT_LISTCLOSE) { labeledStatementList(); } if (token != TT_LISTCLOSE) { throwSyntaxError("'}' expected in switch statement."); } getNextToken(); } } public void forStatement() throws CoreException { if (token == TT_DDOT) { getNextToken(); statementList(); if (token != TT_endfor) { throwSyntaxError("'endfor' expected."); } getNextToken(); if (token != TT_SEMICOLON) { throwSyntaxError("';' expected after for-statement."); } getNextToken(); } else { statement(); } } public void whileStatement() throws CoreException { // ':' statement-list 'endwhile' ';' if (token == TT_DDOT) { getNextToken(); statementList(); if (token != TT_endwhile) { throwSyntaxError("'endwhile' expected."); } getNextToken(); if (token != TT_SEMICOLON) { throwSyntaxError("';' expected after while-statement."); } getNextToken(); } else { statement(); } } public void foreachStatement() throws CoreException { if (token == TT_DDOT) { getNextToken(); statementList(); if (token != TT_endforeach) { throwSyntaxError("'endforeach' expected."); } getNextToken(); if (token != TT_SEMICOLON) { throwSyntaxError("';' expected after foreach-statement."); } getNextToken(); } else { statement(); } } public void exitStatus() { if (token == TT_ARGOPEN) { getNextToken(); } else { throwSyntaxError("'(' expected in 'exit-status'."); } if (token != TT_ARGCLOSE) { expression(); } if (token == TT_ARGCLOSE) { getNextToken(); } else { throwSyntaxError("')' expected after 'exit-status'."); } } public void expressionList() { do { expression(); if (token == TT_COMMA) { getNextToken(); } else { break; } } while (true); } public void expression() { // if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) { // getNextToken(); // } else { logicalinclusiveorExpression(); // while (token != TT_SEMICOLON) { // getNextToken(); // // } // } } public void postfixExpression() { 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; case TT_INTERPOLATED_STRING : getNextToken(); break; case TT_ARGOPEN : getNextToken(); if (token == TT_IDENTIFIER) { // check if identifier is a type: ident = identifier; String str = identifier.toLowerCase(); for (int i = 0; i < PHP_TYPES.length; i++) { if (PHP_TYPES[i].equals(str)) { castFlag = true; break; } } if (castFlag) { getNextToken(); if (token != TT_ARGCLOSE) { throwSyntaxError(") expected after cast-type '" + ident + "'."); } getNextToken(); expression(); break; } } if (!castFlag) { expression(); } if (token != TT_ARGCLOSE) { throwSyntaxError(") expected in postfix-expression."); } getNextToken(); break; case TT_DOUBLE_NUMBER : getNextToken(); break; case TT_INT_NUMBER : getNextToken(); break; case TT_VARIABLE : ident = identifier; getNextToken(); if (token == TT_LISTOPEN) { getNextToken(); expression(); if (token != TT_LISTCLOSE) { throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression."); } 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_list : getNextToken(); if (token == TT_ARGOPEN) { getNextToken(); if (token == TT_COMMA) { getNextToken(); } expressionList(); if (token != TT_ARGCLOSE) { throwSyntaxError("')' expected after 'list' keyword."); } getNextToken(); // if (token == TT_SET) { // getNextToken(); // logicalinclusiveorExpression(); // } } else { 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) { // getNextToken(); // if (token == TT_COMMA) { // getNextToken(); // } // expressionList(); // if (token != TT_ARGCLOSE) { // throwSyntaxError("')' expected after 'list' keyword."); // } // getNextToken(); // if (token == TT_SET) { // getNextToken(); // logicalinclusiveorExpression(); // } // } else { // throwSyntaxError("'(' expected after 'list' keyword."); // } // break; } boolean while_flag = true; do { switch (token) { case TT_PARTOPEN : getNextToken(); expression(); if (token != TT_PARTCLOSE) { throwSyntaxError("] expected in postfix-expression."); } getNextToken(); break; case TT_REF : // -> getNextToken(); 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; case TT_DECREMENT : getNextToken(); break; default : while_flag = false; } } while (while_flag); } public void unaryExpression() { switch (token) { case TT_INCREMENT : getNextToken(); unaryExpression(); break; case TT_DECREMENT : getNextToken(); unaryExpression(); break; //'&' '*' '+' '-' '~' '!' case TT_AMPERSAND : getNextToken(); castExpression(); break; case TT_MULTIPLY : getNextToken(); castExpression(); break; case TT_ADD : getNextToken(); castExpression(); break; case TT_SUBTRACT : getNextToken(); castExpression(); break; case TT_TILDE : getNextToken(); castExpression(); break; case TT_NOT : getNextToken(); castExpression(); break; default : postfixExpression(); } } public void castExpression() { // if (token == TT_ARGOPEN) { // getNextToken(); // typeName(); // if (token != TT_ARGCLOSE) { // throwSyntaxError(") expected after cast-expression."); // } // getNextToken(); // } unaryExpression(); } public void typeName() { //'string' 'unset' 'array' 'object' //'bool' 'boolean' //'real' 'double' 'float' //'int' 'integer' String ident = ""; if (token == TT_IDENTIFIER) { ident = identifier; String str = identifier.toLowerCase(); getNextToken(); for (int i = 0; i < PHP_TYPES.length; i++) { if (PHP_TYPES[i].equals(str)) { return; } } } throwSyntaxError("Expected type cast '( )'; Got '" + ident + "'."); } public void assignExpression() { castExpression(); if (token == TT_ASSIGN) { // = getNextToken(); logicalinclusiveorExpression(); } else if (token == TT_DOTASSIGN) { // .= getNextToken(); logicalinclusiveorExpression(); } 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() { do { assignExpression(); if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) { return; } getNextToken(); } while (true); } public void concatenationExpression() { do { multiplicativeExpression(); if (token != TT_DOT) { return; } getNextToken(); } while (true); } public void additiveExpression() { do { concatenationExpression(); if (token != TT_ADD && token != TT_SUBTRACT) { return; } getNextToken(); } while (true); } public void shiftExpression() { do { additiveExpression(); if (token != TT_LSHIFT && token != TT_RSHIFT) { return; } getNextToken(); } while (true); } public void relationalExpression() { do { shiftExpression(); if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) { return; } getNextToken(); } while (true); } public void identicalExpression() { do { relationalExpression(); if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) { return; } getNextToken(); } while (true); } public void equalityExpression() { do { identicalExpression(); if (token != TT_EQUAL && token != TT_UNEQUAL) { return; } getNextToken(); } 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 { ternaryExpression(); if (token != TT_AMPERSAND) { return; } getNextToken(); } while (true); } public void exclusiveorExpression() { do { andExpression(); if (token != TT_POW) { return; } getNextToken(); } while (true); } public void inclusiveorExpression() { do { exclusiveorExpression(); if (token != TT_LINE) { return; } getNextToken(); } while (true); } public void booleanandExpression() { do { inclusiveorExpression(); if (token != TT_AND) { return; } getNextToken(); } while (true); } public void booleanorExpression() { do { booleanandExpression(); if (token != TT_OR) { return; } getNextToken(); } while (true); } public void logicalandExpression() { do { booleanorExpression(); if (token != TT_and) { return; } getNextToken(); } while (true); } public void logicalexclusiveorExpression() { do { logicalandExpression(); if (token != TT_xor) { return; } getNextToken(); } while (true); } public void logicalinclusiveorExpression() { do { logicalexclusiveorExpression(); if (token != TT_or) { return; } getNextToken(); } while (true); } // public void assignmentExpression() { // if (token == TT_VARIABLE) { // getNextToken(); // if (token == TT_SET) { // getNextToken(); // logicalinclusiveorExpression(); // } // } else { // logicalinclusiveorExpression(); // } // } public void variableList() { do { variable(); if (token == TT_COMMA) { getNextToken(); } else { break; } } while (true); } public void variable() { if (token == TT_VARIABLE) { getNextToken(); } else { throwSyntaxError("$-variable expected in variable-list."); } } 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; case TT_false : getNextToken(); break; case TT_true : getNextToken(); break; case TT_STRING_CONSTANT : getNextToken(); break; case TT_INTERPOLATED_STRING : getNextToken(); break; case TT_DOUBLE_NUMBER : getNextToken(); break; case TT_INT_NUMBER : getNextToken(); break; default : throwSyntaxError("Constant expected."); } } }