File indexing completed on 2024-04-28 15:24:58

0001 /*
0002  * tokenizer_tester.cc - Copyright 2005 Frerich Raabe <raabe@kde.org>
0003  *
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  *
0008  * 1. Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0015  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0016  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0017  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0018  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0019  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0020  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0021  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0023  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0024  */
0025 #include "expression.h"
0026 #include "step.h"         //
0027 #include "path.h"         //
0028 #include "predicate.h"    // Order dependency.
0029 #include "parser.h"       //
0030 
0031 #include <QStringList>
0032 #include <QtDebug>
0033 
0034 extern int xpathyylex();
0035 extern void initTokenizer(QString s);
0036 
0037 QString tokenAsString(yytokentype token)
0038 {
0039     switch (token) {
0040     case MULOP: return QString("MULOP[%1]").arg(xpathyylval.num);
0041     case MINUS: return "MINUS";
0042     case PLUS: return "PLUS";
0043     case RELOP: return QString("RELOP[%1]").arg(xpathyylval.num);
0044     case EQOP: return QString("EQOP[%1]").arg(xpathyylval.num);
0045     case AND: return "AND";
0046     case OR: return "OR";
0047     case AXISNAME: return QString("AXISNAME['%1']").arg(Step::axisAsString(xpathyylval.axisType));
0048     case NODETYPE: return QString("NODETYPE['%1']").arg(*xpathyylval.str);
0049     case PI: return "PI";
0050     case FUNCTIONNAME: return QString("FUNCTIONNAME['%1']").arg(*xpathyylval.str);
0051     case LITERAL: return QString("LITERAL['%1']").arg(*xpathyylval.str);
0052     case VARIABLEREFERENCE: return QString("VARIABLEREFERENCE['%1']").arg(*xpathyylval.str);
0053     case NAMETEST: return QString("NAMETEST['%1']").arg(*xpathyylval.str);
0054     case NUMBER: return QString("NUMBER['%1']").arg(*xpathyylval.str);
0055     case DOTDOT: return "DOTDOT";
0056     case SLASHSLASH: return "SLASHSLASH";
0057     case ERROR:  return "ERROR";
0058     }
0059 
0060     return QString("'%1'").arg(char(token));
0061 }
0062 
0063 QString getTokenString(const QString &s)
0064 {
0065     initTokenizer(s);
0066 
0067     QStringList tokenStrings;
0068     int token = xpathyylex();
0069     while (token != 0) {
0070         tokenStrings << tokenAsString((yytokentype)token);
0071         token = xpathyylex();
0072     };
0073 
0074     return tokenStrings.join(" ");
0075 }
0076 
0077 void check(const QString &statement, const QString &expected)
0078 {
0079     QString result = getTokenString(statement);
0080     if (result != expected) {
0081         qCDebug(KHTML_LOG) << "ERROR: failed to tokenizer " << statement << " as expected";
0082         qCDebug(KHTML_LOG) << "Expected: " << expected;
0083         qCDebug(KHTML_LOG) << "Got     : " << result;
0084         exit(1);
0085     }
0086 }
0087 
0088 int main()
0089 {
0090     check("child        ::book",
0091           "AXISNAME['child'] NAMETEST['book']");
0092     check("/this/and/that",
0093           "'/' NAMETEST['this'] '/' NAMETEST['and'] '/' NAMETEST['that']");
0094     check("self::self/book[@and=\"and\" and true( \t\t)   ]",
0095           "AXISNAME['self'] NAMETEST['self'] '/' NAMETEST['book'] '[' '@' NAMETEST['and'] EQOP[1] LITERAL['and'] AND FUNCTIONNAME['true'] '(' ')' ']'");
0096     check("123 . .43 31. 3131.22 2.2.2",
0097           "NUMBER['123'] '.' NUMBER['.43'] NUMBER['31.'] NUMBER['3131.22'] NUMBER['2.2'] NUMBER['.2']");
0098     check("/or/and[\"and\" and 'or\"' ]",
0099           "'/' NAMETEST['or'] '/' NAMETEST['and'] '[' LITERAL['and'] AND LITERAL['or\"'] ']'");
0100     check("self ::node  (   )[true  (   )]",
0101           "AXISNAME['self'] NODETYPE['node'] '(' ')' '[' FUNCTIONNAME['true'] '(' ')' ']'");
0102 
0103     const QChar alpha(0x03B1);
0104     check(QString("self::") + alpha + alpha + alpha,
0105           QString("AXISNAME['self'] NAMETEST['") + alpha + alpha + alpha + "']");
0106 
0107     check("this[substring-after(\"Name=Joe\", \"=\" )=\"Joe\"]",
0108           "NAMETEST['this'] '[' FUNCTIONNAME['substring-after'] '(' LITERAL['Name=Joe'] ',' LITERAL['='] ')' EQOP[1] LITERAL['Joe'] ']'");
0109     check("child::processing-instruction()",
0110           "AXISNAME['child'] PI '(' ')'");
0111     check("child::processing-instruction(\"yadda\")",
0112           "AXISNAME['child'] PI '(' LITERAL['yadda'] ')'");
0113     check("*",
0114           "NAMETEST['*']");
0115     check("comment() | text() | processing-instruction() | node()",
0116           "NODETYPE['comment'] '(' ')' '|' NODETYPE['text'] '(' ')' '|' PI '(' ')' '|' NODETYPE['node'] '(' ')'");
0117     qDebug("All OK!");
0118 }
0119