00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "config.h"
00021 #include "scanner.h"
00022 #include "vypIO.h"
00023
00024 #ifndef BUILDING_DOX
00025 # include <algorithm>
00026 # include <sstream>
00027 # include <string>
00028 # include <vector>
00029 #endif
00030
00031 using namespace StreamDecorator;
00032 using std::string;
00033
00034 typedef STD_VECTOR(Token) TTokenList;
00035
00037 struct Test {
00038 string input;
00039 bool hasError;
00040 TTokenList tokenList;
00041 };
00042
00043 static int errorCode = 0;
00044
00046 bool operator==(const Token &a, const Token &b) {
00047 if (a.type != b.type)
00048 return false;
00049 if (a.lineno != b.lineno)
00050 return false;
00051 switch (a.type) {
00052 case ETOKEN_NUMBER_INT:
00053 return a.numberInt == b.numberInt;
00054 case ETOKEN_NUMBER_DOUBLE:
00055 return b.numberDouble == b.numberDouble;
00056 case ETOKEN_ID:
00057 case ETOKEN_STRING:
00058 return a.text == b.text;
00059 default:
00060 return true;
00061 }
00062 }
00064 bool operator!=(const Token &a, const Token &b) {
00065 return !operator==(a,b);
00066 }
00067
00073 void run(const Test &test) {
00074
00075 static int nTest = 0;
00076 std::ostringstream tmp;
00077 tmp << "test" << ++nTest;
00078 string name(tmp.str());
00079
00080
00081 std::cout << ">>> " << name << " - input follows:" << std::endl;
00082 std::cout << test.input << std::endl;
00083 std::istringstream stream(test.input);
00084
00085
00086 IScanner *scanner = ScannerFactory::createScanner(stream, name);
00087 Token token;
00088 const TTokenList &tl = test.tokenList;
00089 unsigned i;
00090 for (i = 0; scanner->readNext(token); i++) {
00091 #if 0
00092 std::cout << token << std::endl;
00093 #endif
00094 if (test.hasError)
00095
00096 continue;
00097
00098 const Token &tokenExpected = tl[i];
00099 if (i >= tl.size()) {
00100 std::cerr << "!!! trailing token" << std::endl
00101 << "--- got: " << token << std::endl << std::endl;
00102 ::errorCode = -1;
00103 break;
00104 }
00105 if (token != tokenExpected) {
00106 std::cerr << "!!! token mismatch" << std::endl
00107 << "--- expected: " << tl[i] << std::endl
00108 << "--- got: " << token << std::endl << std::endl;
00109 ::errorCode = -1;
00110 }
00111 }
00112 if (!test.hasError && i < tl.size()) {
00113 std::cerr << "!!! unexpected end of input" << std::endl
00114 << "--- expected: " << tl[i] << std::endl;
00115 ::errorCode = -1;
00116 }
00117 if (scanner->hasError() != test.hasError) {
00118 std::cerr << "!!! unexpected error status" << std::endl
00119 << "--- expected: " << test.hasError << std::endl
00120 << "--- got: " << scanner->hasError() << std::endl;
00121 ::errorCode = -1;
00122 }
00123 delete scanner;
00124 std::cout << std::endl;
00125 }
00126
00127 int main(int argc, char *argv[]) {
00128 #if CONSOLE_COLOR_OUTPUT
00129 Color::enable(true);
00130 #endif
00131
00132 if (argc == 2 && string(argv[1]) == string("-")) {
00133
00134
00135
00136 IScanner *scanner = ScannerFactory::createScanner(std::cin, "-");
00137
00138
00139 Token t;
00140 while (scanner->readNext(t))
00141 std::cout << t << std::endl;
00142
00143
00144 bool bErr = scanner->hasError();
00145 delete scanner;
00146 return bErr ? -1:0;
00147 }
00148
00149
00150 typedef STD_VECTOR(Test) TTestList;
00151 TTestList testList;
00152 Test t;
00153 TTokenList &tl = t.tokenList;
00154
00155
00156 t.input = "\n\tid1/* simple comment */id2// inline comment /* garbage /*\nid3////////";
00157 t.hasError = false;
00158 tl.clear();
00159 { Token t(ETOKEN_ID, 2, 0, 0.0, "id1"); tl.push_back(t); }
00160 { Token t(ETOKEN_ID, 2, 0, 0.0, "id2"); tl.push_back(t); }
00161 { Token t(ETOKEN_ID, 3, 0, 0.0, "id3"); tl.push_back(t); }
00162 testList.push_back(t);
00163
00164
00165 t.input = "int a;doubleb;double d;string\ts;;";
00166 t.hasError = false;
00167 tl.clear();
00168 { Token t(ETOKEN_KW_INT, 1, 0, 0.0, "" ); tl.push_back(t); }
00169 { Token t(ETOKEN_ID, 1, 0, 0.0, "a" ); tl.push_back(t); }
00170 { Token t(ETOKEN_OP_SEMICOLON, 1, 0, 0.0, "" ); tl.push_back(t); }
00171 { Token t(ETOKEN_ID, 1, 0, 0.0, "doubleb" ); tl.push_back(t); }
00172 { Token t(ETOKEN_OP_SEMICOLON, 1, 0, 0.0, "" ); tl.push_back(t); }
00173 { Token t(ETOKEN_KW_DOUBLE, 1, 0, 0.0, "" ); tl.push_back(t); }
00174 { Token t(ETOKEN_ID, 1, 0, 0.0, "d" ); tl.push_back(t); }
00175 { Token t(ETOKEN_OP_SEMICOLON, 1, 0, 0.0, "" ); tl.push_back(t); }
00176 { Token t(ETOKEN_KW_STRING, 1, 0, 0.0, "" ); tl.push_back(t); }
00177 { Token t(ETOKEN_ID, 1, 0, 0.0, "s" ); tl.push_back(t); }
00178 { Token t(ETOKEN_OP_SEMICOLON, 1, 0, 0.0, "" ); tl.push_back(t); }
00179 { Token t(ETOKEN_OP_SEMICOLON, 1, 0, 0.0, "" ); tl.push_back(t); }
00180 testList.push_back(t);
00181
00182
00183 t.input =
00184 "STRING /* \"asdffsi\" */\"\\\\n - \\n, /* pseudo-comment */, //,\\n"
00185 " \\\\\\\\ - \\\\, \\\\\\\" - \\\", garbge\"id+0.01///\n\"\""
00186 "\"a\\\\b -> \\\"c\\\"\"";
00187 t.hasError = false;
00188 tl.clear();
00189 { Token t(ETOKEN_ID, 1, 0, 0.0, "STRING" ); tl.push_back(t); }
00190 { Token t(ETOKEN_STRING, 1, 0, 0.0, "\\n - \n, /* pseudo-comment */, //,\n \\\\ - \\, \\\" - \", garbge"); tl.push_back(t); }
00191 { Token t(ETOKEN_ID, 1, 0, 0.0, "id" ); tl.push_back(t); }
00192 { Token t(ETOKEN_OP_PLUS, 1, 0, 0.0, "" ); tl.push_back(t); }
00193 { Token t(ETOKEN_NUMBER_DOUBLE, 1, 0, .01, "" ); tl.push_back(t); }
00194 { Token t(ETOKEN_STRING, 2, 0, 0.0, "" ); tl.push_back(t); }
00195 { Token t(ETOKEN_STRING, 2, 0, 0.0, "a\\b -> \"c\""); tl.push_back(t); }
00196 testList.push_back(t);
00197
00198
00199 t.hasError = true;
00200 tl.clear();
00201 t.input = "\"str"; testList.push_back(t);
00202 t.input = "\"str\\a\""; testList.push_back(t);
00203 t.input = "\"str\\\\\"\""; testList.push_back(t);
00204 t.input = "str\""; testList.push_back(t);
00205
00206
00207 t.input = "double d:=0.0000000000000001e15,-15";
00208 t.hasError = false;
00209 tl.clear();
00210 { Token t(ETOKEN_KW_DOUBLE, 1, 0, 0.0, "" ); tl.push_back(t); }
00211 { Token t(ETOKEN_ID, 1, 0, 0.0, "d" ); tl.push_back(t); }
00212 { Token t(ETOKEN_OP_ASSIGN, 1, 0, 0.0, "" ); tl.push_back(t); }
00213 { Token t(ETOKEN_NUMBER_DOUBLE, 1, 0, 0.0000000000000001e15, "" ); tl.push_back(t); }
00214 { Token t(ETOKEN_OP_COMMA, 1, 0, 0.0, "" ); tl.push_back(t); }
00215 { Token t(ETOKEN_OP_MINUS, 1, 0, 0.0, "" ); tl.push_back(t); }
00216 { Token t(ETOKEN_NUMBER_INT, 1, 15, 0.0, "" ); tl.push_back(t); }
00217 testList.push_back(t);
00218
00219
00220 t.hasError = true;
00221 tl.clear();
00222 t.input = "1_"; testList.push_back(t);
00223 t.input = "9999999999999999999"; testList.push_back(t);
00224 t.input = "10.0e1000"; testList.push_back(t);
00225
00226
00227 t.input = "{and}(div)double*/else+-eq if<int>ne\n"
00228 "q\tneq<=not>=or:=string,var\n\n\n;void/**/while \n"
00229 "////////////////////////////////////////////";
00230 t.hasError = false;
00231 tl.clear();
00232 { Token t(ETOKEN_OP_LCBR, 1, 0, 0.0, "" ); tl.push_back(t); }
00233 { Token t(ETOKEN_KW_AND, 1, 0, 0.0, "" ); tl.push_back(t); }
00234 { Token t(ETOKEN_OP_RCBR, 1, 0, 0.0, "" ); tl.push_back(t); }
00235 { Token t(ETOKEN_OP_LPAR, 1, 0, 0.0, "" ); tl.push_back(t); }
00236 { Token t(ETOKEN_KW_DIV, 1, 0, 0.0, "" ); tl.push_back(t); }
00237 { Token t(ETOKEN_OP_RPAR, 1, 0, 0.0, "" ); tl.push_back(t); }
00238 { Token t(ETOKEN_KW_DOUBLE, 1, 0, 0.0, "" ); tl.push_back(t); }
00239 { Token t(ETOKEN_OP_STAR, 1, 0, 0.0, "" ); tl.push_back(t); }
00240 { Token t(ETOKEN_OP_SLASH, 1, 0, 0.0, "" ); tl.push_back(t); }
00241 { Token t(ETOKEN_KW_ELSE, 1, 0, 0.0, "" ); tl.push_back(t); }
00242 { Token t(ETOKEN_OP_PLUS, 1, 0, 0.0, "" ); tl.push_back(t); }
00243 { Token t(ETOKEN_OP_MINUS, 1, 0, 0.0, "" ); tl.push_back(t); }
00244 { Token t(ETOKEN_KW_EQ, 1, 0, 0.0, "" ); tl.push_back(t); }
00245 { Token t(ETOKEN_KW_IF, 1, 0, 0.0, "" ); tl.push_back(t); }
00246 { Token t(ETOKEN_OP_LESS, 1, 0, 0.0, "" ); tl.push_back(t); }
00247 { Token t(ETOKEN_KW_INT, 1, 0, 0.0, "" ); tl.push_back(t); }
00248 { Token t(ETOKEN_OP_GREATER, 1, 0, 0.0, "" ); tl.push_back(t); }
00249 { Token t(ETOKEN_ID, 1, 0, 0.0, "ne" ); tl.push_back(t); }
00250 { Token t(ETOKEN_ID, 2, 0, 0.0, "q" ); tl.push_back(t); }
00251 { Token t(ETOKEN_KW_NEQ, 2, 0, 0.0, "" ); tl.push_back(t); }
00252 { Token t(ETOKEN_OP_LESS_EQ, 2, 0, 0.0, "" ); tl.push_back(t); }
00253 { Token t(ETOKEN_KW_NOT, 2, 0, 0.0, "" ); tl.push_back(t); }
00254 { Token t(ETOKEN_OP_GREATER_EQ, 2, 0, 0.0, "" ); tl.push_back(t); }
00255 { Token t(ETOKEN_KW_OR, 2, 0, 0.0, "" ); tl.push_back(t); }
00256 { Token t(ETOKEN_OP_ASSIGN, 2, 0, 0.0, "" ); tl.push_back(t); }
00257 { Token t(ETOKEN_KW_STRING, 2, 0, 0.0, "" ); tl.push_back(t); }
00258 { Token t(ETOKEN_OP_COMMA, 2, 0, 0.0, "" ); tl.push_back(t); }
00259 { Token t(ETOKEN_KW_VAR, 2, 0, 0.0, "" ); tl.push_back(t); }
00260 { Token t(ETOKEN_OP_SEMICOLON, 5, 0, 0.0, "" ); tl.push_back(t); }
00261 { Token t(ETOKEN_KW_VOID, 5, 0, 0.0, "" ); tl.push_back(t); }
00262 { Token t(ETOKEN_KW_WHILE, 5, 0, 0.0, "" ); tl.push_back(t); }
00263 testList.push_back(t);
00264
00265 std::for_each(testList.begin(), testList.end(), run);
00266 return ::errorCode;
00267 }