# jay skeleton # character in column 1 determines outcome... # # is a comment # . is copied # t is copied as //t if -t is set # other lines are interpreted to call jay procedures .// created by jay 0.7 (c) 1998 Axel.Schreiner@informatik.uni-osnabrueck.de . prolog ## %{ ... %} prior to the first %% .// %token constants . tokens public static final int . . /** thrown for irrecoverable syntax errors and stack overflow. . */ . public static class yyException extends java.lang.Exception { . public yyException (String message) { . super(message); . } . } . . /** must be implemented by a scanner object to supply input to the parser. . */ . public interface yyInput { . /** move on to next token. . @return false if positioned beyond tokens. . @throws IOException on input error. . */ . boolean advance () throws java.io.IOException; . /** classifies current token. . Should not be called if advance() returned false. . @return current %token or single character. . */ . int token (); . /** associated with current token. . Should not be called if advance() returned false. . @return value for token(). . */ . Object value (); . } . . /** simplified error message. . @see yyerror . */ . public void yyerror (String message) { . yyerror(message, null); . } . . /** (syntax) error message. . Can be overwritten to control message format. . @param message text to be displayed. . @param expected vector of acceptable tokens, if available. . */ . public void yyerror (String message, String[] expected) { . if (expected != null && expected.length > 0) { . System.err.print(message+", expecting"); . for (int n = 0; n < expected.length; ++ n) . System.err.print(" "+expected[n]); . System.err.println(); . } else . System.err.println(message); . } . . /** debugging support, requires the package jay.yydebug. . Set to null to suppress debugging messages. . */ t protected jay.yydebug.yyDebug yydebug; . debug ## tables for debugging support . . /** index-checked interface to yyNames[]. . @param token single character or %token value. . @return token name or [illegal] or [unknown]. . */ t public static final String yyname (int token) { t if (token < 0 || token > yyNames.length) return "[illegal]"; t String name; t if ((name = yyNames[token]) != null) return name; t return "[unknown]"; t } . . /** computes list of expected tokens on error by tracing the tables. . @param state for which to compute the list. . @return list of token names. . */ . protected String[] yyExpecting (int state) { . int token, n, len = 0; . boolean[] ok = new boolean[yyNames.length]; . . if ((n = yySindex[state]) != 0) . for (token = n < 0 ? -n : 0; . token < yyNames.length && n+token < yyTable.length; ++ token) . if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) { . ++ len; . ok[token] = true; . } . if ((n = yyRindex[state]) != 0) . for (token = n < 0 ? -n : 0; . token < yyNames.length && n+token < yyTable.length; ++ token) . if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) { . ++ len; . ok[token] = true; . } . . String result[] = new String[len]; . for (n = token = 0; n < len; ++ token) . if (ok[token]) result[n++] = yyNames[token]; . return result; . } . . /** the generated parser, with debugging messages. . Maintains a state and a value stack, currently with fixed maximum size. . @param yyLex scanner. . @param yydebug debug message writer implementing yyDebug, or null. . @return result of the last reduction, if any. . @throws yyException on irrecoverable parse error. . */ . public Object yyparse (yyInput yyLex, Object yydebug) . throws java.io.IOException, yyException { t this.yydebug = (jay.yydebug.yyDebug)yydebug; . return yyparse(yyLex); . } . . /** initial size and increment of the state/value stack [default 256]. . This is not final so that it can be overwritten outside of invocations . of yyparse(). . */ . protected int yyMax; . . /** executed at the beginning of a reduce action. . Used as $$ = yyDefault($1), prior to the user-specified action, if any. . Can be overwritten to provide deep copy, etc. . @param first value for $1, or null. . @return first. . */ . protected Object yyDefault (Object first) { . return first; . } . . /** the generated parser. . Maintains a state and a value stack, currently with fixed maximum size. . @param yyLex scanner. . @return result of the last reduction, if any. . @throws yyException on irrecoverable parse error. . */ . public Object yyparse (yyInput yyLex) . throws java.io.IOException, yyException { . if (yyMax <= 0) yyMax = 256; // initial size . int yyState = 0, yyStates[] = new int[yyMax]; // state stack . Object yyVal = null, yyVals[] = new Object[yyMax]; // value stack . int yyToken = -1; // current input . int yyErrorFlag = 0; // #tks to shift . local ## %{ ... %} after the first %% . yyLoop: for (int yyTop = 0;; ++ yyTop) { . if (yyTop >= yyStates.length) { // dynamically increase . int[] i = new int[yyStates.length+yyMax]; . System.arraycopy(yyStates, 0, i, 0, yyStates.length); . yyStates = i; . Object[] o = new Object[yyVals.length+yyMax]; . System.arraycopy(yyVals, 0, o, 0, yyVals.length); . yyVals = o; . } . yyStates[yyTop] = yyState; . yyVals[yyTop] = yyVal; t if (yydebug != null) yydebug.push(yyState, yyVal); . . yyDiscarded: for (;;) { // discarding a token does not change stack . int yyN; . if ((yyN = yyDefRed[yyState]) == 0) { // else [default] reduce (yyN) . if (yyToken < 0) { . yyToken = yyLex.advance() ? yyLex.token() : 0; t if (yydebug != null) t yydebug.lex(yyState, yyToken, yyname(yyToken), yyLex.value()); . } . if ((yyN = yySindex[yyState]) != 0 && (yyN += yyToken) >= 0 . && yyN < yyTable.length && yyCheck[yyN] == yyToken) { t if (yydebug != null) t yydebug.shift(yyState, yyTable[yyN], yyErrorFlag-1); . yyState = yyTable[yyN]; // shift to yyN . yyVal = yyLex.value(); . yyToken = -1; . if (yyErrorFlag > 0) -- yyErrorFlag; . continue yyLoop; . } . if ((yyN = yyRindex[yyState]) != 0 && (yyN += yyToken) >= 0 . && yyN < yyTable.length && yyCheck[yyN] == yyToken) . yyN = yyTable[yyN]; // reduce (yyN) . else . switch (yyErrorFlag) { . . case 0: . yyerror("syntax error", yyExpecting(yyState)); t if (yydebug != null) yydebug.error("syntax error"); . . case 1: case 2: . yyErrorFlag = 3; . do { . if ((yyN = yySindex[yyStates[yyTop]]) != 0 . && (yyN += yyErrorCode) >= 0 && yyN < yyTable.length . && yyCheck[yyN] == yyErrorCode) { t if (yydebug != null) t yydebug.shift(yyStates[yyTop], yyTable[yyN], 3); . yyState = yyTable[yyN]; . yyVal = yyLex.value(); . continue yyLoop; . } t if (yydebug != null) yydebug.pop(yyStates[yyTop]); . } while (-- yyTop >= 0); t if (yydebug != null) yydebug.reject(); . throw new yyException("irrecoverable syntax error"); . . case 3: . if (yyToken == 0) { t if (yydebug != null) yydebug.reject(); . throw new yyException("irrecoverable syntax error at end-of-file"); . } t if (yydebug != null) t yydebug.discard(yyState, yyToken, yyname(yyToken), t yyLex.value()); . yyToken = -1; . continue yyDiscarded; // leave stack alone . } . } . int yyV = yyTop + 1-yyLen[yyN]; t if (yydebug != null) t yydebug.reduce(yyState, yyStates[yyV-1], yyN, YYRules.getRule[yyN], yyLen[yyN]); . yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]); . switch (yyN) { actions ## code from the actions within the grammar . } . yyTop -= yyLen[yyN]; . yyState = yyStates[yyTop]; . int yyM = yyLhs[yyN]; . if (yyState == 0 && yyM == 0) { t if (yydebug != null) yydebug.shift(0, yyFinal); . yyState = yyFinal; . if (yyToken < 0) { . yyToken = yyLex.advance() ? yyLex.token() : 0; t if (yydebug != null) t yydebug.lex(yyState, yyToken,yyname(yyToken), yyLex.value()); . } . if (yyToken == 0) { t if (yydebug != null) yydebug.accept(yyVal); . return yyVal; . } . continue yyLoop; . } . if ((yyN = yyGindex[yyM]) != 0 && (yyN += yyState) >= 0 . && yyN < yyTable.length && yyCheck[yyN] == yyState) . yyState = yyTable[yyN]; . else . yyState = yyDgoto[yyM]; t if (yydebug != null) yydebug.shift(yyStates[yyTop], yyState); . continue yyLoop; . } . } . } . tables ## tables for rules, default reduction, and action calls . epilog ## text following second %%