簡易的なXPathParser を作っています。Jayでやっているんですが、生成後のcsファイル(39行目)にある「yacc_verbose_flag」が定義されてないよって出ます。
これはなんでだろう(定義されてないものを参照してるからエラーとかそういう意味ではなくて)。
とりあえず参照しないように書き換えて進めるか...
この最初のif文フラグ。どこで定義されたのか(いや、されてないんだけど)。謎。
/** (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 ((yacc_verbose_flag > 0) && (expected != null) && (expected.Length > 0)) { ErrorOutput.Write (message+", expecting"); for (int n = 0; n < expected.Length; ++ n) ErrorOutput.Write (" "+expected[n]); ErrorOutput.WriteLine (); } else ErrorOutput.WriteLine (message); }
XPathParser の実装にはmonoのコードを参考に書いています。大変ありがたい。
参考: http://www.angstrom-distribution.org/ unstable/ sources/ mono-1.2.2.1.tar.gz/ mono-1.2.2.1/ mcs/ class/ System.XML/ System.Xml.XPath/Parser.jay - Googleソースコード検索
現在のコード(PathParser.jay, PathParser.cs)。
PathParser.jay
%{ using System; using System.Xml; using System.Xml.XPath; namespace xpath_parser { internal class XPathParser { internal XPathParser() { } %} %token ERROR %token EOF %token SLASH "/" %token SLASH2 "//" %token DOT "." %token DOT2 ".." %token ATTRIBUTE "attribute" %token CHILD "child" %token NAMESPACE "NameSpace" %token PARENT "parent" %token SELF "self" %token TEXT "text" %token NODE "node" %start Expr %% Expr : LocPath ; LocPath : RelLocPath | AbsLocPath ; Step : DOT { // $$ = new NodeTypeTest( Axes.Self, XPathNodeType.All ); } | DOT2 { // $$ = new NodeTypeTest( Axes.Parent, XPathNodeType.All ); } ; RelLocPath : Step | RelLocPath SLASH Step { $$ = new Expression.ExprSLASH( ( Expression ) $1, ( NodeSet ) $3 ); // $$ = new ExprSLASH( ( Expression ) $1, ( NodeSet ) $3 ); } | RelLocPath SLASH2 Step { $$ = new Expression.ExprSLASH2( ( Expression ) $1, ( NodeSet ) $3 ); } ; AbsLocPath : SLASH { $$ = new Expression.ExprRoot(); } | SLASH RelLocPath { $$ = new Expression.ExprSLASH( ( Expression ) $1, ( NodeSet ) $2 ); } | SLASH2 RelLocPath { $$ = new Expression.ExprSLASH2( ( Expression ) $1, ( NodeSet ) $2 ); } ; %% } // End of XPathParser class
PathParser.cs
// created by jay 0.7 (c) 1998 Axel.Schreiner@informatik.uni-osnabrueck.de #line 2 "/Users/inohiro/Desktop/n_PathParser.jay" using System; using System.Xml; using System.Xml.XPath; namespace xpath_parser { internal class XPathParser { internal XPathParser() { } #line default /** error output stream. It should be changeable. */ public System.IO.TextWriter ErrorOutput = System.Console.Out; /** simplified error message. @see <a href="#yyerror(java.lang.String, java.lang.String[])">yyerror</a> */ 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 ((yacc_verbose_flag > 0) && (expected != null) && (expected.Length > 0)) { ErrorOutput.Write (message+", expecting"); for (int n = 0; n < expected.Length; ++ n) ErrorOutput.Write (" "+expected[n]); ErrorOutput.WriteLine (); } else ErrorOutput.WriteLine (message); } /** debugging support, requires the package jay.yydebug. Set to null to suppress debugging messages. */ //t internal yydebug.yyDebug debug; protected static int yyFinal = 5; //t // Put this array into a separate class so it is only initialized if debugging is actually used //t // Use MarshalByRefObject to disable inlining //t class YYRules : MarshalByRefObject { //t public static string [] yyRule = { //t "$accept : Expr", //t "Expr : LocPath", //t "LocPath : RelLocPath", //t "LocPath : AbsLocPath", //t "Step : DOT", //t "Step : DOT2", //t "RelLocPath : Step", //t "RelLocPath : RelLocPath SLASH Step", //t "RelLocPath : RelLocPath SLASH2 Step", //t "AbsLocPath : SLASH", //t "AbsLocPath : SLASH RelLocPath", //t "AbsLocPath : SLASH2 RelLocPath", //t }; //t public static string getRule (int index) { //t return yyRule [index]; //t } //t} protected static string [] yyNames = { "end-of-file",null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,"'.'","'/'",null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,null,null,null,null,null,null, null,null,null,null,null,null,null,null,"ERROR","EOF","SLASH", "SLASH2","\"//\"","DOT","DOT2","\"..\"","ATTRIBUTE","\"attribute\"", "CHILD","\"child\"","NAMESPACE","\"NameSpace\"","PARENT","\"parent\"", "SELF","\"self\"","TEXT","\"text\"","NODE","\"node\"", }; /** index-checked interface to yyNames[]. @param token single character or %token value. @return token name or [illegal] or [unknown]. */ //t public static 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; bool[] ok = new bool[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. */ internal Object yyparse (yyParser.yyInput yyLex, Object yyd) { //t this.debug = (yydebug.yyDebug)yyd; 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. */ internal Object yyparse (yyParser.yyInput yyLex) { if (yyMax <= 0) yyMax = 256; // initial size int yyState = 0; // state stack ptr int [] yyStates = new int[yyMax]; // state stack Object yyVal = null; // value stack ptr Object [] yyVals = new Object[yyMax]; // value stack int yyToken = -1; // current input int yyErrorFlag = 0; // #tks to shift /*yyLoop:*/ for (int yyTop = 0;; ++ yyTop) { if (yyTop >= yyStates.Length) { // dynamically increase int[] i = new int[yyStates.Length+yyMax]; yyStates.CopyTo (i, 0); yyStates = i; Object[] o = new Object[yyVals.Length+yyMax]; yyVals.CopyTo (o, 0); yyVals = o; } yyStates[yyTop] = yyState; yyVals[yyTop] = yyVal; //t if (debug != null) debug.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 (debug != null) //t debug.lex(yyState, yyToken, yyname(yyToken), yyLex.value()); } if ((yyN = yySindex[yyState]) != 0 && ((yyN += yyToken) >= 0) && (yyN < yyTable.Length) && (yyCheck[yyN] == yyToken)) { //t if (debug != null) //t debug.shift(yyState, yyTable[yyN], yyErrorFlag-1); yyState = yyTable[yyN]; // shift to yyN yyVal = yyLex.value(); yyToken = -1; if (yyErrorFlag > 0) -- yyErrorFlag; goto 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(String.Format ("syntax error, got token `{0}'", yyname (yyToken)), yyExpecting(yyState)); //t if (debug != null) debug.error("syntax error"); goto case 1; case 1: case 2: yyErrorFlag = 3; do { if ((yyN = yySindex[yyStates[yyTop]]) != 0 && (yyN += Token.yyErrorCode) >= 0 && yyN < yyTable.Length && yyCheck[yyN] == Token.yyErrorCode) { //t if (debug != null) //t debug.shift(yyStates[yyTop], yyTable[yyN], 3); yyState = yyTable[yyN]; yyVal = yyLex.value(); goto continue_yyLoop; } //t if (debug != null) debug.pop(yyStates[yyTop]); } while (-- yyTop >= 0); //t if (debug != null) debug.reject(); throw new yyParser.yyException("irrecoverable syntax error"); case 3: if (yyToken == 0) { //t if (debug != null) debug.reject(); throw new yyParser.yyException("irrecoverable syntax error at end-of-file"); } //t if (debug != null) //t debug.discard(yyState, yyToken, yyname(yyToken), //t yyLex.value()); yyToken = -1; goto continue_yyDiscarded; // leave stack alone } } int yyV = yyTop + 1-yyLen[yyN]; //t if (debug != null) //t debug.reduce(yyState, yyStates[yyV-1], yyN, YYRules.getRule (yyN), yyLen[yyN]); yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]); switch (yyN) { case 4: #line 47 "/Users/inohiro/Desktop/n_PathParser.jay" { /* $$ = new NodeTypeTest( Axes.Self, XPathNodeType.All );*/ } break; case 5: #line 51 "/Users/inohiro/Desktop/n_PathParser.jay" { /* $$ = new NodeTypeTest( Axes.Parent, XPathNodeType.All );*/ } break; case 7: #line 58 "/Users/inohiro/Desktop/n_PathParser.jay" { yyVal = new Expression.ExprSLASH( ( Expression ) yyVals[-2+yyTop], ( NodeSet ) yyVals[0+yyTop] ); /* $$ = new ExprSLASH( ( Expression ) $1, ( NodeSet ) $3 );*/ } break; case 8: #line 63 "/Users/inohiro/Desktop/n_PathParser.jay" { yyVal = new Expression.ExprSLASH2( ( Expression ) yyVals[-2+yyTop], ( NodeSet ) yyVals[0+yyTop] ); } break; case 9: #line 69 "/Users/inohiro/Desktop/n_PathParser.jay" { yyVal = new Expression.ExprRoot(); } break; case 10: #line 73 "/Users/inohiro/Desktop/n_PathParser.jay" { yyVal = new Expression.ExprSLASH( ( Expression ) yyVals[-1+yyTop], ( NodeSet ) yyVals[0+yyTop] ); } break; case 11: #line 77 "/Users/inohiro/Desktop/n_PathParser.jay" { yyVal = new Expression.ExprSLASH2( ( Expression ) yyVals[-1+yyTop], ( NodeSet ) yyVals[0+yyTop] ); } break; #line default } yyTop -= yyLen[yyN]; yyState = yyStates[yyTop]; int yyM = yyLhs[yyN]; if (yyState == 0 && yyM == 0) { //t if (debug != null) debug.shift(0, yyFinal); yyState = yyFinal; if (yyToken < 0) { yyToken = yyLex.advance() ? yyLex.token() : 0; //t if (debug != null) //t debug.lex(yyState, yyToken,yyname(yyToken), yyLex.value()); } if (yyToken == 0) { //t if (debug != null) debug.accept(yyVal); return yyVal; } goto 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 (debug != null) debug.shift(yyStates[yyTop], yyState); goto continue_yyLoop; continue_yyDiscarded: continue; // implements the named-loop continue: 'continue yyDiscarded' } continue_yyLoop: continue; // implements the named-loop continue: 'continue yyLoop' } } static short [] yyLhs = { -1, 0, 1, 1, 4, 4, 2, 2, 2, 3, 3, 3, }; static short [] yyLen = { 2, 1, 1, 1, 1, 1, 1, 3, 3, 1, 2, 2, }; static short [] yyDefRed = { 0, 0, 0, 4, 5, 0, 1, 0, 3, 6, 0, 0, 0, 0, 7, 8, }; protected static short [] yyDgoto = { 5, 6, 7, 8, 9, }; protected static short [] yySindex = { -259, -257, -257, 0, 0, 0, 0, -252, 0, 0, -252, -252, -257, -257, 0, 0, }; protected static short [] yyRindex = { 0, 2, 0, 0, 0, 0, 0, 13, 0, 0, 14, 15, 0, 0, 0, 0, }; protected static short [] yyGindex = { 0, 0, 8, 0, -1, }; protected static short [] yyTable = { 1, 2, 9, 3, 4, 3, 4, 12, 13, 10, 11, 14, 15, 2, 10, 11, }; protected static short [] yyCheck = { 259, 260, 0, 262, 263, 262, 263, 259, 260, 1, 2, 12, 13, 0, 0, 0, }; #line 83 "/Users/inohiro/Desktop/n_PathParser.jay" } // End of XPathParser class #line default namespace yydebug { using System; internal interface yyDebug { void push (int state, Object value); void lex (int state, int token, string name, Object value); void shift (int from, int to, int errorFlag); void pop (int state); void discard (int state, int token, string name, Object value); void reduce (int from, int to, int rule, string text, int len); void shift (int from, int to); void accept (Object value); void error (string message); void reject (); } class yyDebugSimple : yyDebug { void println (string s){ Console.Error.WriteLine (s); } public void push (int state, Object value) { println ("push\tstate "+state+"\tvalue "+value); } public void lex (int state, int token, string name, Object value) { println("lex\tstate "+state+"\treading "+name+"\tvalue "+value); } public void shift (int from, int to, int errorFlag) { switch (errorFlag) { default: // normally println("shift\tfrom state "+from+" to "+to); break; case 0: case 1: case 2: // in error recovery println("shift\tfrom state "+from+" to "+to +"\t"+errorFlag+" left to recover"); break; case 3: // normally println("shift\tfrom state "+from+" to "+to+"\ton error"); break; } } public void pop (int state) { println("pop\tstate "+state+"\ton error"); } public void discard (int state, int token, string name, Object value) { println("discard\tstate "+state+"\ttoken "+name+"\tvalue "+value); } public void reduce (int from, int to, int rule, string text, int len) { println("reduce\tstate "+from+"\tuncover "+to +"\trule ("+rule+") "+text); } public void shift (int from, int to) { println("goto\tfrom state "+from+" to "+to); } public void accept (Object value) { println("accept\tvalue "+value); } public void error (string message) { println("error\t"+message); } public void reject () { println("reject"); } } } // %token constants class Token { public const int ERROR = 257; public const int EOF = 258; public const int SLASH = 259; public const int SLASH2 = 260; public const int DOT = 262; public const int DOT2 = 263; public const int ATTRIBUTE = 265; public const int attribute = 266; public const int CHILD = 267; public const int child = 268; public const int NAMESPACE = 269; public const int NameSpace = 270; public const int PARENT = 271; public const int parent = 272; public const int SELF = 273; public const int self = 274; public const int TEXT = 275; public const int text = 276; public const int NODE = 277; public const int node = 278; public const int yyErrorCode = 256; } namespace yyParser { using System; /** thrown for irrecoverable syntax errors and stack overflow. */ internal class yyException : System.Exception { public yyException (string message) : base (message) { } } /** must be implemented by a scanner object to supply input to the parser. */ internal interface yyInput { /** move on to next token. @return false if positioned beyond tokens. @throws IOException on input error. */ bool 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 (); } } } // close outermost namespace, that MUST HAVE BEEN opened in the prolog