1 package net.sourceforge.phpeclipse.phpeditor;
3 import java.util.HashMap;
5 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
7 /**********************************************************************
8 Copyright (c) 2000, 2002 IBM Corp. and others.
9 All rights reserved. This program and the accompanying materials
10 are made available under the terms of the Common Public License v1.0
11 which accompanies this distribution, and is available at
12 http://www.eclipse.org/legal/cpl-v10.html
15 IBM Corporation - Initial implementation
16 Klaus Hartlage - www.eclipseproject.de
17 **********************************************************************/
19 public class PHPParser extends PHPKeywords {
21 private static HashMap keywordMap = null;
29 // row counter for syntax errors:
31 // column counter for syntax errors:
42 final static int TT_EOF = 0;
43 final static int TT_UNDEFINED = 1;
45 final static int TT_NOT = 31;
46 final static int TT_DOT = 32;
47 final static int TT_POW = 33;
48 final static int TT_DIVIDE = 34;
49 final static int TT_MULTIPLY = 35;
50 final static int TT_SUBTRACT = 36;
51 final static int TT_ADD = 37;
52 final static int TT_EQUAL = 38;
53 final static int TT_UNEQUAL = 39;
54 final static int TT_GREATER = 40;
55 final static int TT_GREATEREQUAL = 41;
56 final static int TT_LESS = 42;
57 final static int TT_LESSEQUAL = 43;
58 final static int TT_AND = 44;
59 final static int TT_OR = 45;
60 final static int TT_HASH = 46;
61 final static int TT_DDOT = 47;
62 final static int TT_DOTASSIGN = 48;
64 final static int TT_SET = 49;
65 final static int TT_REF = 50;
66 final static int TT_FOREACH = 51;
67 final static int TT_AMPERSAND = 52;
68 final static int TT_DOLLARLISTOPEN = 53;
69 final static int TT_ARGOPEN = 128;
70 final static int TT_ARGCLOSE = 129;
71 final static int TT_LISTOPEN = 130;
72 final static int TT_LISTCLOSE = 131;
73 final static int TT_PARTOPEN = 132;
74 final static int TT_PARTCLOSE = 133;
75 final static int TT_COMMA = 134;
76 final static int TT_PERCENT = 135;
77 final static int TT_STRING = 136;
78 final static int TT_IDENTIFIER = 138;
79 final static int TT_DIGIT = 139;
80 final static int TT_SEMICOLON = 140;
81 final static int TT_SLOT = 141;
82 final static int TT_SLOTSEQUENCE = 142;
83 final static int TT_DECREMENT = 144;
84 final static int TT_INCREMENT = 145;
85 final static int TT_ADDTO = 146;
86 final static int TT_DIVIDEBY = 147;
87 final static int TT_SUBTRACTFROM = 148;
88 final static int TT_TIMESBY = 149;
89 final static int TT_VARIABLE = 150;
90 final static int TT_INT_NUMBER = 151;
91 final static int TT_DOUBLE_NUMBER = 152;
92 final static int TT_INTERPOLATED_STRING = 153;
93 final static int TT_STRING_CONSTANT = 154;
94 // final static int TT_AT = 153; // @
99 *@param sess Description of Parameter
103 if (keywordMap == null) {
104 keywordMap = new HashMap();
105 for (int i = 0; i < PHP_KEYWORS.length; i++) {
106 keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
113 this.columnCount = 0;
118 private void throwSyntaxError(String error) {
120 if (str.length() < chIndx) {
123 // read until end-of-line
125 while (str.length() > eol) {
126 ch = str.charAt(eol++);
132 throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
136 * Method Declaration.
141 if (str.length() > chIndx) {
142 ch = str.charAt(chIndx++);
147 chIndx = str.length() + 1;
153 * gets the next token from input
155 void getNextToken() {
156 while (str.length() > chIndx) {
157 ch = str.charAt(chIndx++);
158 token = TT_UNDEFINED;
161 columnCount = chIndx;
162 continue; // while loop
165 if (!Character.isWhitespace(ch)) {
166 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$') || (ch == '@')) {
170 if (ch >= '0' && ch <= '9') {
175 if (str.length() > chIndx) {
176 if (str.charAt(chIndx) == '/') {
178 // read comment until end of line:
179 while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
183 } else if (str.charAt(chIndx) == '*') {
185 // multi line comment:
186 while (str.length() > chIndx) {
187 if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
196 } else if (ch == '#') {
197 // read comment until end of line:
198 while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
202 } else if (ch == '"') {
203 // read string until end
204 while ((str.length() > chIndx) && (str.charAt(chIndx++) != '"')) {
205 if (str.charAt(chIndx) == '\\') {
206 if (str.length() > chIndx) {
209 if (str.length() > chIndx) {
213 if (str.charAt(chIndx) == '\n') {
215 columnCount = chIndx;
219 // if (str.length() > chIndx) {
222 token = TT_INTERPOLATED_STRING;
224 } else if (ch == '\'') {
225 // read string until end
226 while ((str.length() > chIndx) && (str.charAt(chIndx++) != '\'')) {
227 if (str.charAt(chIndx) == '\\') {
228 if (str.length() > chIndx) {
231 if (str.length() > chIndx) {
236 // if (str.length() > chIndx) {
239 token = TT_STRING_CONSTANT;
258 token = TT_LISTCLOSE;
266 token = TT_PARTCLOSE;
276 if (str.length() > chIndx) {
277 if (str.charAt(chIndx) == '=') {
279 token = TT_DOTASSIGN;
295 token = TT_SEMICOLON;
305 if (str.length() > chIndx) {
306 if (str.charAt(chIndx) == '=') {
317 if (str.length() > chIndx) {
318 if (str.charAt(chIndx) == '*') {
324 if (str.charAt(chIndx) == '=') {
335 if (str.length() > chIndx) {
336 if (str.charAt(chIndx) == '+') {
338 token = TT_INCREMENT;
342 if (str.charAt(chIndx) == '=') {
352 if (str.length() > chIndx) {
353 if (str.charAt(chIndx) == '-') {
355 token = TT_DECREMENT;
359 if (str.charAt(chIndx) == '=') {
361 token = TT_SUBTRACTFROM;
365 if (str.charAt(chIndx) == '>') {
377 if (str.length() > chIndx) {
378 ch = str.charAt(chIndx);
398 if (str.length() > chIndx) {
399 if (str.charAt(chIndx) == '=') {
411 if (str.length() > chIndx) {
412 if (str.charAt(chIndx) == '=') {
414 token = TT_GREATEREQUAL;
424 if (str.length() > chIndx) {
425 if (str.charAt(chIndx) == '=') {
427 token = TT_LESSEQUAL;
436 if (str.length() > chIndx) {
437 if (str.charAt(chIndx) == '|') {
447 if (str.length() > chIndx) {
448 if (str.charAt(chIndx) == '&') {
454 token = TT_AMPERSAND;
474 throwSyntaxError("unexpected character: '" + ch + "'");
477 if (token == TT_UNDEFINED) {
478 throwSyntaxError("token not found");
485 chIndx = str.length() + 1;
490 void getIdentifier() {
491 StringBuffer ident = new StringBuffer();
497 token = TT_IDENTIFIER;
500 while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch >= '_')) {
504 identifier = ident.toString();
507 Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
509 token = i.intValue();
514 StringBuffer inum = new StringBuffer();
523 // determine number conversions:
524 if (firstCh == '0') {
553 if (numFormat == 16) {
554 while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
559 while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) {
560 if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
561 if (ch == '.' && dFlag != ' ') {
564 if ((dFlag == 'E') || (dFlag == 'e')) {
570 if ((ch == '-') || (ch == '+')) {
584 doubleNumber = new Double(inum.toString());
585 token = TT_DOUBLE_NUMBER;
588 longNumber = Long.valueOf(inum.toString(), numFormat);
589 token = TT_INT_NUMBER;
593 } catch (Throwable e) {
594 throwSyntaxError("Number format error: " + inum.toString());
598 public void start(String s, int rowCount) throws SyntaxError {
603 this.rowCount = rowCount;
604 this.columnCount = 0;
608 if (token != TT_EOF) {
609 if (token == TT_ARGCLOSE) {
610 throwSyntaxError("too many closing ')'; end-of-file not reached");
612 if (token == TT_LISTCLOSE) {
613 throwSyntaxError("too many closing '}'; end-of-file not reached");
615 if (token == TT_PARTCLOSE) {
616 throwSyntaxError("too many closing ']'; end-of-file not reached");
619 if (token == TT_ARGOPEN) {
620 throwSyntaxError("read character '('; end-of-file not reached");
622 if (token == TT_LISTOPEN) {
623 throwSyntaxError("read character '{'; end-of-file not reached");
625 if (token == TT_PARTOPEN) {
626 throwSyntaxError("read character '['; end-of-file not reached");
629 throwSyntaxError("end-of-file not reached");
634 public void statementList() {
637 if ((token == TT_LISTCLOSE)
638 || (token == TT_elseif)
639 || (token == TT_endif)
640 || (token == TT_endfor)
641 || (token == TT_endforeach)
642 || (token == TT_endwhile)
643 || (token == TT_endswitch)
644 || (token == TT_EOF)) {
650 public void statement() {
651 while (token != TT_UNDEFINED && token != TT_EOF) {
652 if (token > TT_KEYWORD) {
653 if (token == TT_case) {
656 if (token == TT_DDOT) {
660 throwSyntaxError("':' character after 'case' constant expected.");
663 } else if (token == TT_default) {
665 if (token == TT_DDOT) {
669 throwSyntaxError("':' character after 'default' expected.");
672 } else if (token == TT_include || token == TT_include_once) {
675 if (token == TT_SEMICOLON) {
678 throwSyntaxError("';' character after 'include' or 'include_once' expected.");
681 } else if (token == TT_require || token == TT_require_once) {
685 if (token == TT_SEMICOLON) {
688 throwSyntaxError("';' character after 'require' or 'require_once' expected.");
691 } else if (token == TT_if) {
693 if (token == TT_ARGOPEN) {
696 throwSyntaxError("'(' expected after 'if' keyword.");
699 if (token == TT_ARGCLOSE) {
702 throwSyntaxError("')' expected after 'if' condition.");
707 } else if (token == TT_switch) {
709 if (token == TT_ARGOPEN) {
712 throwSyntaxError("'(' expected after 'switch' keyword.");
715 if (token == TT_ARGCLOSE) {
718 throwSyntaxError("')' expected after 'switch' condition.");
722 } else if (token == TT_for) {
724 if (token == TT_ARGOPEN) {
727 throwSyntaxError("'(' expected after 'for' keyword.");
729 if (token == TT_SEMICOLON) {
733 if (token == TT_SEMICOLON) {
736 throwSyntaxError("';' character after 'for' expected.");
739 if (token == TT_SEMICOLON) {
743 if (token == TT_SEMICOLON) {
746 throwSyntaxError("';' character after 'for' expected.");
749 if (token == TT_ARGCLOSE) {
753 if (token == TT_ARGCLOSE) {
756 throwSyntaxError("')' expected after 'for' condition.");
761 } else if (token == TT_while) {
763 if (token == TT_ARGOPEN) {
766 throwSyntaxError("'(' expected after 'while' keyword.");
769 if (token == TT_ARGCLOSE) {
772 throwSyntaxError("')' expected after 'while' condition.");
776 } else if (token == TT_foreach) {
778 if (token == TT_ARGOPEN) {
781 throwSyntaxError("'(' expected after 'foreach' keyword.");
784 if (token == TT_as) {
787 throwSyntaxError("'as' expected after 'foreach' exxpression.");
790 if (token == TT_FOREACH) {
794 if (token == TT_ARGCLOSE) {
797 throwSyntaxError("')' expected after 'foreach' expression.");
802 } else if (token == TT_continue || token == TT_break || token == TT_return) {
804 if (token != TT_SEMICOLON) {
807 if (token == TT_SEMICOLON) {
810 throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
814 } else if (token == TT_echo) {
817 if (token == TT_SEMICOLON) {
820 throwSyntaxError("';' expected after 'echo' statement.");
824 } else if (token == TT_print) {
827 if (token == TT_SEMICOLON) {
830 throwSyntaxError("';' expected after 'print' statement.");
834 } else if (token == TT_global || token == TT_static) {
837 if (token == TT_SEMICOLON) {
840 throwSyntaxError("';' expected after 'global' or 'static' statement.");
844 } else if (token == TT_unset) {
846 if (token == TT_ARGOPEN) {
849 throwSyntaxError("'(' expected after 'unset' keyword.");
852 if (token == TT_ARGCLOSE) {
855 throwSyntaxError("')' expected after 'unset' statement.");
857 if (token == TT_SEMICOLON) {
860 throwSyntaxError("';' expected after 'unset' statement.");
864 } else if (token == TT_exit || token == TT_die) {
866 if (token != TT_SEMICOLON) {
869 if (token == TT_SEMICOLON) {
872 throwSyntaxError("';' expected after 'exit' or 'die' statement.");
876 } else if (token == TT_define) {
878 if (token == TT_ARGOPEN) {
881 throwSyntaxError("'(' expected after 'define' keyword.");
884 if (token == TT_COMMA) {
887 throwSyntaxError("',' expected after first 'define' constant.");
890 if (token == TT_ARGCLOSE) {
893 throwSyntaxError("')' expected after 'define' statement.");
895 if (token == TT_SEMICOLON) {
898 throwSyntaxError("';' expected after 'define' statement.");
904 } else if (token == TT_LISTOPEN) {
907 if (token != TT_LISTCLOSE) {
910 if (token == TT_LISTCLOSE) {
913 throwSyntaxError("'}' expected.");
916 if (token != TT_SEMICOLON) {
919 if (token == TT_SEMICOLON) {
922 throwSyntaxError("';' expected after expression.");
928 public void labeledStatement() {
931 public void expressionStatement() {
934 public void inclusionStatement() {
937 // public void compoundStatement() {
940 public void selectionStatement() {
943 public void iterationStatement() {
946 public void jumpStatement() {
949 public void outputStatement() {
952 public void scopeStatement() {
955 public void flowStatement() {
958 public void definitionStatement() {
961 public void ifStatement() {
962 // statement [else-statement]
964 if (token == TT_else) {
970 public void switchStatement() {
973 public void forStatement() {
976 public void whileStatement() {
979 public void foreachStatement() {
982 public void exitStatus() {
983 if (token == TT_ARGOPEN) {
986 throwSyntaxError("'(' expected in 'exit-status'.");
988 if (token != TT_ARGCLOSE) {
991 if (token == TT_ARGCLOSE) {
994 throwSyntaxError("')' expected after 'exit-status'.");
998 public void expressionList() {
1001 if (token == TT_COMMA) {
1009 public void expression() {
1010 if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
1013 postfixExpression();
1014 // while (token != TT_SEMICOLON) {
1020 public void postfixExpression() {
1025 if (token != TT_ARGCLOSE) {
1026 throwSyntaxError(") expected in postfix-expression.");
1030 case TT_DOUBLE_NUMBER :
1033 case TT_INT_NUMBER :
1039 case TT_IDENTIFIER :
1041 if (token == TT_ARGOPEN) {
1043 if (token != TT_ARGCLOSE) {
1045 if (token != TT_ARGCLOSE) {
1046 throwSyntaxError(") expected after identifier in postfix-expression.");
1054 boolean while_flag = true;
1060 if (token != TT_PARTCLOSE) {
1061 throwSyntaxError("] expected in postfix-expression.");
1070 case TT_IDENTIFIER :
1076 if (token != TT_LISTCLOSE) {
1077 throwSyntaxError("] expected in postfix-expression.");
1082 throwSyntaxError("Syntax error after '->' token.");
1093 } while (while_flag);
1096 public void variableList() {
1099 if (token == TT_COMMA) {
1107 public void variable() {
1108 if (token == TT_VARIABLE) {
1111 throwSyntaxError("$-variable expected in variable-list.");
1115 public void constant() {