00001
00002
00003
00004
00005
00006 #include "cparser.h"
00007
00008 #include <string.h>
00009 #include <stdlib.h>
00010
00011 #include "lexer.h"
00012 #include "eparser.h"
00013 #include "settings.h"
00014 #include "logic.h"
00015 #include "data.h"
00016 #include "guess.h"
00017 #include "ast.h"
00018 #include "tplate.h"
00019
00020
00021 using namespace std;
00022 using fityk::SyntaxError;
00023
00024 const char *command_list[] = {
00025 "debug", "define", "delete", "exec", "fit", "guess", "info", "plot",
00026 "quit", "reset", "set", "sleep", "title", "undefine", "use"
00027 };
00028
00029 const char* info_args[] = {
00030 "version", "compiler", "variables", "types", "functions",
00031 "dataset_count", "view", "fit_history",
00032 "filename", "title", "data",
00033 "formula", "gnuplot_formula",
00034 "simplified_formula", "simplified_gnuplot_formula",
00035 "models", "state", "history_summary", "peaks", "peaks_err",
00036 "set",
00037 "history", "guess",
00038 "fit", "errors", "confidence", "cov",
00039 "refs", "prop",
00040 NULL
00041 };
00042
00043 const char* debug_args[] = {
00044
00045 "parse", "lex", "expr", "der", "rd", "idx", "df", "%", "$", NULL
00046 };
00047
00048
00049 const char* commandtype2str(CommandType c)
00050 {
00051 switch (c) {
00052 case kCmdDebug: return "Debug";
00053 case kCmdDefine: return "Define";
00054 case kCmdDelete: return "Delete";
00055 case kCmdDeleteP: return "Delete";
00056 case kCmdExec: return "Exec";
00057 case kCmdFit: return "Fit";
00058 case kCmdGuess: return "Guess";
00059 case kCmdInfo: return "Info";
00060 case kCmdPlot: return "Plot";
00061 case kCmdPrint: return "Print";
00062 case kCmdQuit: return "Quit";
00063 case kCmdReset: return "Reset";
00064 case kCmdSet: return "Set";
00065 case kCmdSleep: return "Sleep";
00066 case kCmdTitle: return "Title";
00067 case kCmdUndef: return "Undef";
00068 case kCmdUse: return "Use";
00069 case kCmdShell: return "Shell";
00070 case kCmdLoad: return "Load";
00071 case kCmdDatasetTr: return "DatasetTr";
00072 case kCmdNameFunc: return "NameFunc";
00073 case kCmdAssignParam: return "AssignParam";
00074
00075 case kCmdNameVar: return "NameVar";
00076 case kCmdChangeModel: return "ChangeModel";
00077 case kCmdPointTr: return "PointTr";
00078 case kCmdAllPointsTr: return "AllPointsTr";
00079 case kCmdResizeP: return "ResizeP";
00080 case kCmdNull: return "Null";
00081 }
00082 return NULL;
00083 }
00084
00085 Token nop()
00086 {
00087 Token t;
00088 t.type = kTokenNop;
00089 return t;
00090 }
00091
00092 bool is_command(const Token& token, const char* cmd_base,
00093 const char* cmd_suffix)
00094 {
00095 assert(token.type == kTokenLname);
00096 int base_len = strlen(cmd_base);
00097 if (strncmp(token.str, cmd_base, base_len) != 0)
00098 return false;
00099 int left_chars = token.length - base_len;
00100 return left_chars == 0 ||
00101 (left_chars <= (int) strlen(cmd_suffix) &&
00102 strncmp(token.str + base_len, cmd_suffix, left_chars) == 0);
00103 }
00104
00105
00106 Parser::Parser(const Ftk* F)
00107 : F_(F), ep_(F)
00108 {
00109 }
00110
00111 Parser::~Parser()
00112 {
00113 }
00114
00115 Token Parser::read_expr(Lexer& lex, ExpressionParser::ParseMode mode)
00116 {
00117 Token t;
00118 t.type = kTokenExpr;
00119 t.str = lex.pchar();
00120 ep_.clear_vm();
00121 assert(!st_.datasets.empty());
00122 int ds = st_.datasets[0];
00123 ep_.parse_expr(lex, ds, NULL, NULL, mode);
00124 t.length = lex.pchar() - t.str;
00125 t.value.d = 0.;
00126 return t;
00127 }
00128
00129 Token Parser::read_and_calc_expr(Lexer& lex)
00130 {
00131 Token t = read_expr(lex);
00132 int ds = st_.datasets[0];
00133 const vector<Point>& points = F_->get_data(ds)->points();
00134 t.value.d = ep_.calculate(0, points);
00135 return t;
00136 }
00137
00138
00139 Token Parser::read_var(Lexer& lex)
00140 {
00141 Token t;
00142 t.type = kTokenEVar;
00143 t.str = lex.pchar();
00144 int ds = st_.datasets[0];
00145 ep_.clear_vm();
00146 ep_.parse_expr(lex, ds, NULL, NULL, ExpressionParser::kAstMode);
00147 t.value.i = st_.vdlist.size();
00148 st_.vdlist.push_back(ep_.vm());
00149 t.length = lex.pchar() - t.str;
00150 return t;
00151 }
00152
00153
00154 Token Parser::read_define_arg(Lexer& lex, const vector<string>& allowed_names,
00155 vector<string> *new_names)
00156 {
00157 Token t;
00158 t.type = kTokenExpr;
00159 t.str = lex.pchar();
00160 ep_.clear_vm();
00161 ep_.parse_expr(lex, -1, &allowed_names, new_names);
00162 t.length = lex.pchar() - t.str;
00163 t.value.d = 0.;
00164 return t;
00165 }
00166
00167
00168
00169 void Parser::parse_real_range(Lexer& lex, vector<Token>& args)
00170 {
00171 if (lex.peek_token().type == kTokenLSquare) {
00172 lex.get_token();
00173 const Token& t = lex.peek_token();
00174 if (t.type == kTokenColon) {
00175 args.push_back(nop());
00176 lex.get_token();
00177 }
00178 else if (t.type == kTokenRSquare) {
00179
00180 args.push_back(nop());
00181 }
00182 else {
00183 args.push_back(read_and_calc_expr(lex));
00184 lex.get_expected_token(kTokenColon);
00185 }
00186
00187 const Token& r = lex.peek_token();
00188 if (r.type == kTokenRSquare) {
00189 lex.get_token();
00190 args.push_back(nop());
00191 }
00192 else {
00193 args.push_back(read_and_calc_expr(lex));
00194 lex.get_expected_token(kTokenRSquare);
00195 }
00196 }
00197 else {
00198 args.push_back(nop());
00199 args.push_back(nop());
00200 }
00201 }
00202
00203
00204
00205
00206 void Parser::parse_func_id(Lexer& lex, vector<Token>& args, bool accept_fz)
00207 {
00208 Token t = lex.get_token();
00209 if (t.type == kTokenFuncname) {
00210 args.push_back(t);
00211 return;
00212 }
00213 if (t.type == kTokenDataset) {
00214 args.push_back(t);
00215 lex.get_expected_token(kTokenDot);
00216 t = lex.get_token();
00217 }
00218 else
00219 args.push_back(nop());
00220 if (t.as_string() != "F" && t.as_string() != "Z")
00221 lex.throw_syntax_error("expected %function ID");
00222 args.push_back(t);
00223 if (accept_fz && lex.peek_token().type != kTokenLSquare) {
00224 args.push_back(nop());
00225 return;
00226 }
00227 lex.get_expected_token(kTokenLSquare);
00228 args.push_back(read_and_calc_expr(lex));
00229 lex.get_expected_token(kTokenRSquare);
00230 }
00231
00232 void Parser::parse_set_args(Lexer& lex, vector<Token>& args)
00233 {
00234 do {
00235 Token key = lex.get_expected_token(kTokenLname);
00236 lex.get_expected_token(kTokenAssign);
00237 SettingsMgr::ValueType t =
00238 F_->settings_mgr()->get_value_type(key.as_string());
00239 if (t == SettingsMgr::kNotFound)
00240 lex.throw_syntax_error("no such option: " + key.as_string());
00241 Token value;
00242 if (t == SettingsMgr::kString)
00243 value = lex.get_expected_token(kTokenString);
00244 else if (t == SettingsMgr::kEnum)
00245 value = lex.get_expected_token(kTokenLname);
00246 else
00247 value = read_and_calc_expr(lex);
00248 args.push_back(key);
00249 args.push_back(value);
00250 } while (lex.discard_token_if(kTokenComma));
00251 }
00252
00253
00254 class ArgReader
00255 {
00256 public:
00257 ArgReader(Lexer& lex) : lex_(lex)
00258 {
00259 lex_.get_expected_token(kTokenOpen);
00260 flag_ = (lex.get_token_if(kTokenClose).type == kTokenClose ? 0 : 1);
00261 }
00262
00263 bool next_arg()
00264 {
00265 if (flag_ == 0)
00266 return false;
00267 else if (flag_ == 1) {
00268 flag_ = 2;
00269 return true;
00270 }
00271 else
00272 return (lex_.get_expected_token(kTokenComma, kTokenClose).type
00273 == kTokenComma);
00274 }
00275
00276 private:
00277 Lexer& lex_;
00278 int flag_;
00279 };
00280
00281
00282 void Parser::parse_component(Lexer& lex, const vector<string>& lhs_vars,
00283 Tplate::Component* c)
00284 {
00285 Token name = lex.get_expected_token(kTokenCname);
00286 c->p = F_->get_tpm()->get_shared_tp(name.as_string());
00287 c->cargs.clear();
00288 ArgReader ar(lex);
00289 while (ar.next_arg()) {
00290 read_define_arg(lex, lhs_vars, NULL);
00291 c->cargs.push_back(ep_.vm());
00292 }
00293 if (c->p && c->cargs.size() != c->p->fargs.size())
00294 lex.throw_syntax_error("function " + c->p->name + " should have "
00295 + S(c->p->fargs.size()) + " parameters (not "
00296 + S(c->cargs.size()) + ")");
00297 }
00298
00299 void Parser::parse_define_rhs(Lexer& lex, Tplate *tp)
00300 {
00301 Token t = lex.get_token();
00302
00303 if (t.type == kTokenCname) {
00304 lex.go_back(t);
00305 do {
00306 Tplate::Component c;
00307 parse_component(lex, tp->fargs, &c);
00308 tp->components.push_back(c);
00309 } while (lex.discard_token_if(kTokenPlus));
00310 tp->create = &create_CompoundFunction;
00311 }
00312
00313
00314 else if (t.as_string() == "x" && lex.discard_token_if(kTokenLT)) {
00315 tp->components.resize(3);
00316 read_define_arg(lex, tp->fargs, NULL);
00317 tp->components[0].cargs.push_back(ep_.vm());
00318 lex.get_expected_token(kTokenQMark);
00319 parse_component(lex, tp->fargs, &tp->components[1]);
00320 lex.get_expected_token(kTokenColon);
00321 parse_component(lex, tp->fargs, &tp->components[2]);
00322 tp->create = &create_SplitFunction;
00323 }
00324
00325
00326 else {
00327 lex.go_back(t);
00328 vector<string> extra_names;
00329 string rhs = read_define_arg(lex, tp->fargs, &extra_names).as_string();
00330 if (lex.peek_token().as_string() == "where") {
00331 lex.get_token();
00332 do {
00333 string name = lex.get_expected_token(kTokenLname).as_string();
00334 lex.get_expected_token(kTokenAssign);
00335 int idx = index_of_element(extra_names, name);
00336 if (idx == -1)
00337 lex.throw_syntax_error("unused substitution: " + name);
00338 extra_names.erase(extra_names.begin() + idx);
00339 Token s = read_define_arg(lex, tp->fargs, &extra_names);
00340 replace_words(rhs, name, "("+s.as_string()+")");
00341 } while (lex.discard_token_if(kTokenComma));
00342 }
00343 v_foreach (string, i, extra_names) {
00344 if (*i != "x")
00345 lex.throw_syntax_error("unknown argument: " + *i);
00346 }
00347
00348 Lexer lex2(rhs.c_str());
00349 ExpressionParser ep(NULL);
00350 ep.parse_expr(lex2, -1, &tp->fargs, NULL, ExpressionParser::kAstMode);
00351 tp->op_trees = prepare_ast_with_der(ep.vm(), tp->fargs.size() + 1);
00352
00353 tp->create = &create_CustomFunction;
00354 }
00355 }
00356
00357
00358 Tplate::Ptr Parser::parse_define_args(Lexer& lex)
00359 {
00360 boost::shared_ptr<Tplate> tp(new Tplate);
00361
00362 tp->name = lex.get_expected_token(kTokenCname).as_string();
00363
00364
00365 ArgReader arg_reader(lex);
00366 const vector<string> empty;
00367 vector<string> new_vars;
00368 while (arg_reader.next_arg()) {
00369 string name = lex.get_expected_token(kTokenLname).as_string();
00370 if (name == "x") {
00371 if (lex.peek_token().type == kTokenAssign)
00372 lex.throw_syntax_error("do not use x at left-hand side.");
00373 continue;
00374 }
00375 tp->fargs.push_back(name);
00376 string default_value;
00377 if (lex.discard_token_if(kTokenAssign))
00378 default_value = read_define_arg(lex, empty, &new_vars).as_string();
00379 else
00380 new_vars.push_back(name);
00381 tp->defvals.push_back(default_value);
00382 }
00383
00384 tp->linear_d = false;
00385 v_foreach (string, i, new_vars)
00386 if (contains_element(Guess::linear_traits, *i)) {
00387 tp->linear_d = true;
00388 break;
00389 }
00390 tp->peak_d = false;
00391 v_foreach (string, i, new_vars)
00392 if (contains_element(Guess::peak_traits, *i)) {
00393 tp->peak_d = true;
00394 break;
00395 }
00396
00397
00398 lex.get_expected_token(kTokenAssign);
00399
00400 const char* start_rhs = lex.pchar();
00401 while (isspace(*start_rhs))
00402 ++start_rhs;
00403 parse_define_rhs(lex, tp.get());
00404 tp->rhs = string(start_rhs, lex.pchar());
00405 return tp;
00406 }
00407
00408 void parse_undefine_args(Lexer& lex, vector<Token>& args)
00409 {
00410 do {
00411 args.push_back(lex.get_expected_token(kTokenCname));
00412 } while (lex.discard_token_if(kTokenComma));
00413 }
00414
00415 void parse_delete_args(Lexer& lex, vector<Token>& args)
00416 {
00417 do {
00418
00419 Token t = lex.get_glob_token();
00420 if (t.type == kTokenDataset ||
00421 t.type == kTokenFuncname ||
00422 t.type == kTokenVarname)
00423 args.push_back(t);
00424 else if (t.type == kTokenLname && t.as_string() == "file")
00425 args.push_back(lex.get_filename_token());
00426 else
00427 lex.throw_syntax_error("unexpected arg after `delete'");
00428 } while (lex.discard_token_if(kTokenComma));
00429 }
00430
00431 void parse_exec_args(Lexer& lex, vector<Token>& args)
00432 {
00433 if (lex.discard_token_if(kTokenBang))
00434 args.push_back(lex.get_rest_of_line());
00435 else
00436 args.push_back(lex.get_filename_token());
00437 }
00438
00439 void Parser::parse_fit_args(Lexer& lex, vector<Token>& args)
00440 {
00441 Token t = lex.get_token();
00442 if (t.type == kTokenLname) {
00443 string name = t.as_string();
00444 if (name == "undo" || name == "redo" || name == "clear_history") {
00445 args.push_back(t);
00446 }
00447 else if (name == "history") {
00448 args.push_back(t);
00449 args.push_back(read_and_calc_expr(lex));
00450 }
00451 else
00452 lex.throw_syntax_error("unexpected name after `fit'");
00453 }
00454 else if (t.type == kTokenPlus) {
00455 args.push_back(t);
00456 args.push_back(lex.get_expected_token(kTokenNumber));
00457 if (lex.peek_token().type == kTokenDataset)
00458 throw ExecuteError("No need to specify datasets to continue fit.");
00459 }
00460
00461 else if (t.type == kTokenNumber || t.type == kTokenDataset) {
00462 args.push_back(t);
00463 while (lex.peek_token().type == kTokenDataset)
00464 args.push_back(lex.get_token());
00465 }
00466 else
00467 lex.go_back(t);
00468 }
00469
00470
00471 void Parser::parse_guess_args(Lexer& lex, vector<Token>& args)
00472 {
00473 Token t = lex.get_expected_token(kTokenCname, kTokenFuncname);
00474 if (t.type == kTokenFuncname) {
00475 args.push_back(t);
00476 lex.get_expected_token(kTokenAssign);
00477 t = lex.get_expected_token(kTokenCname);
00478 }
00479 else
00480 args.push_back(nop());
00481 args.push_back(t);
00482 if (lex.peek_token().type == kTokenOpen) {
00483 lex.get_expected_token(kTokenOpen);
00484 Token t = lex.get_token_if(kTokenClose);
00485 while (t.type != kTokenClose) {
00486 args.push_back(lex.get_expected_token(kTokenLname));
00487 lex.get_expected_token(kTokenAssign);
00488 args.push_back(read_var(lex));
00489 t = lex.get_expected_token(kTokenComma, kTokenClose);
00490 }
00491 }
00492 parse_real_range(lex, args);
00493 }
00494
00495 static
00496 void parse_redir(Lexer& lex, vector<Token>& args)
00497 {
00498 if (lex.peek_token().type == kTokenGT ||
00499 lex.peek_token().type == kTokenAppend) {
00500 args.push_back(lex.get_token());
00501 Token f = lex.get_filename_token();
00502 if (f.type == kTokenNop)
00503 lex.throw_syntax_error("expected filename");
00504 args.push_back(f);
00505 }
00506 }
00507
00508 void Parser::parse_info_args(Lexer& lex, vector<Token>& args)
00509 {
00510 if (lex.peek_token().type == kTokenNop)
00511 return;
00512 parse_one_info_arg(lex, args);
00513 while (lex.discard_token_if(kTokenComma))
00514 parse_one_info_arg(lex, args);
00515 parse_redir(lex, args);
00516 }
00517
00518 void Parser::parse_one_info_arg(Lexer& lex, vector<Token>& args)
00519 {
00520 Token token = lex.get_glob_token();
00521 if (token.type == kTokenLname) {
00522 string word = token.as_string();
00523 const char** pos = info_args;
00524 while (*pos != NULL && *pos != word)
00525 ++pos;
00526 if (*pos == NULL)
00527 lex.throw_syntax_error("Unknown info argument: " + word);
00528 args.push_back(token);
00529 if (word == "set") {
00530 if (lex.peek_token().type == kTokenLname)
00531 args.push_back(lex.get_token());
00532 else
00533 args.push_back(nop());
00534 }
00535 else if (word == "history" || word == "guess") {
00536 parse_real_range(lex, args);
00537 }
00538 else if (word == "fit" || word == "errors" || word == "cov") {
00539 while (lex.peek_token().type == kTokenDataset)
00540 args.push_back(lex.get_token());
00541 args.push_back(nop());
00542 }
00543 else if (word == "confidence") {
00544 args.push_back(lex.get_expected_token(kTokenNumber));
00545 while (lex.peek_token().type == kTokenDataset)
00546 args.push_back(lex.get_token());
00547 args.push_back(nop());
00548 }
00549 else if (word == "refs") {
00550 args.push_back(lex.get_expected_token(kTokenVarname));
00551 }
00552 else if (word == "prop") {
00553 args.push_back(lex.get_expected_token(kTokenFuncname));
00554 }
00555 }
00556 else if (token.type == kTokenCname || token.type == kTokenFuncname ||
00557 token.type == kTokenVarname) {
00558 args.push_back(token);
00559 }
00560
00561 else if ((token.type == kTokenUletter &&
00562 (*token.str == 'F' || *token.str == 'Z'))
00563 || token.type == kTokenDataset) {
00564 args.push_back(token);
00565 if (token.type == kTokenDataset) {
00566 lex.get_expected_token(kTokenDot);
00567 args.push_back(lex.get_expected_token("F", "Z"));
00568 }
00569 if (lex.peek_token().type == kTokenLSquare) {
00570 lex.get_token();
00571 args.push_back(read_and_calc_expr(lex));
00572 lex.get_expected_token(kTokenRSquare);
00573 }
00574 }
00575 else
00576 lex.throw_syntax_error("Unknown info argument: " + token.as_string());
00577 }
00578
00579 void Parser::parse_print_args(Lexer& lex, vector<Token>& args)
00580 {
00581
00582
00583
00584
00585 bool once = true;
00586 if (lex.peek_token().as_string() == "all") {
00587 lex.get_token();
00588
00589 args.push_back(lex.get_expected_token(kTokenColon));
00590 once = false;
00591 }
00592 else if (lex.peek_token().as_string() == "if") {
00593 lex.get_token();
00594 args.push_back(read_expr(lex));
00595 lex.get_expected_token(kTokenColon);
00596 once = false;
00597 }
00598 else
00599 args.push_back(nop());
00600 do {
00601 if (lex.peek_token().type == kTokenString)
00602 args.push_back(lex.get_token());
00603 else if (lex.peek_token().as_string() == "filename" ||
00604 lex.peek_token().as_string() == "title")
00605 args.push_back(lex.get_token());
00606 else {
00607 Token t = once ? read_and_calc_expr(lex) : read_expr(lex);
00608 args.push_back(t);
00609 }
00610
00611 } while (lex.discard_token_if(kTokenComma));
00612 parse_redir(lex, args);
00613 }
00614
00615 CommandType Parser::parse_xysa_args(Lexer& lex, vector<Token>& args)
00616 {
00617 Token t = lex.get_expected_token(kTokenAssign, kTokenLSquare);
00618
00619 if (t.type == kTokenAssign) {
00620 for (;;) {
00621 args.push_back(read_expr(lex));
00622 if (!lex.discard_token_if(kTokenComma))
00623 break;
00624 Token a = lex.get_expected_token(kTokenUletter);
00625 char d = *a.str;
00626 if (d != 'X' && d != 'Y' && d != 'S' && d != 'A')
00627 lex.throw_syntax_error("unexpected letter");
00628 args.push_back(a);
00629 lex.get_expected_token(kTokenAssign);
00630 }
00631 return kCmdAllPointsTr;
00632 }
00633
00634 else {
00635 for (;;) {
00636 args.push_back(read_and_calc_expr(lex));
00637 lex.get_expected_token(kTokenRSquare);
00638 lex.get_expected_token(kTokenAssign);
00639 args.push_back(read_and_calc_expr(lex));
00640 if (!lex.discard_token_if(kTokenComma))
00641 break;
00642 Token a = lex.get_expected_token(kTokenUletter);
00643 char d = *a.str;
00644 if (d != 'X' && d != 'Y' && d != 'S' && d != 'A')
00645 lex.throw_syntax_error("unexpected letter");
00646 args.push_back(a);
00647 lex.get_expected_token(kTokenLSquare);
00648 }
00649 return kCmdPointTr;
00650 }
00651 }
00652
00653 void Parser::parse_assign_func(Lexer& lex, vector<Token>& args)
00654 {
00655 Token f = lex.get_expected_token(kTokenCname, "copy");
00656 if (f.type == kTokenCname) {
00657
00658 args.push_back(f);
00659 bool has_kwarg = false;
00660 ArgReader arg_reader(lex);
00661 while (arg_reader.next_arg()) {
00662 Token t = lex.get_token();
00663 if (lex.discard_token_if(kTokenAssign)) {
00664 if (t.type != kTokenLname)
00665 lex.throw_syntax_error("wrong token before '='");
00666 args.push_back(t);
00667 has_kwarg = true;
00668 }
00669 else {
00670 if (has_kwarg)
00671 lex.throw_syntax_error("non-keyword arg after keyword arg");
00672 args.push_back(nop());
00673 lex.go_back(t);
00674 }
00675 args.push_back(read_var(lex));
00676 }
00677 }
00678 else {
00679
00680 args.push_back(f);
00681 lex.get_expected_token(kTokenOpen);
00682 parse_func_id(lex, args, false);
00683 lex.get_expected_token(kTokenClose);
00684 }
00685 }
00686
00687 void Parser::parse_fz(Lexer& lex, Command &cmd)
00688 {
00689 Token t = lex.get_token();
00690
00691
00692 if (t.type == kTokenAssign || t.type == kTokenAddAssign) {
00693 cmd.type = kCmdChangeModel;
00694 cmd.args.push_back(t);
00695 for (;;) {
00696 const Token& p = lex.peek_token();
00697 if (p.type == kTokenCname) {
00698 parse_assign_func(lex, cmd.args);
00699 }
00700 else if (p.as_string() == "0") {
00701 cmd.args.push_back(lex.get_token());
00702 }
00703 else if (p.as_string() == "copy") {
00704 cmd.args.push_back(lex.get_token());
00705 lex.get_expected_token(kTokenOpen);
00706 parse_func_id(lex, cmd.args, true);
00707 lex.get_expected_token(kTokenClose);
00708 }
00709 else
00710 parse_func_id(lex, cmd.args, true);
00711
00712 if (lex.peek_token().type == kTokenPlus)
00713 cmd.args.push_back(lex.get_token());
00714 else
00715 break;
00716 }
00717 }
00718
00719 else if (t.type == kTokenDot) {
00720
00721
00722
00723
00724 lex.throw_syntax_error("Illegal syntax, did you mean F[*].par= ?");
00725 }
00726
00727 else if (t.type == kTokenLSquare) {
00728 Token tok_idx;
00729 if (lex.peek_token().type == kTokenMult)
00730 tok_idx = lex.get_token();
00731 else
00732 tok_idx = read_and_calc_expr(lex);
00733 cmd.args.push_back(tok_idx);
00734 lex.get_expected_token(kTokenRSquare);
00735 Token k = lex.get_expected_token(kTokenAssign, kTokenDot);
00736 if (k.type == kTokenAssign) {
00737 if (tok_idx.type == kTokenMult)
00738 lex.throw_syntax_error("Illegal syntax F[*]=...");
00739 cmd.type = kCmdChangeModel;
00740 if (lex.peek_token().type == kTokenFuncname)
00741 cmd.args.push_back(lex.get_token());
00742 else
00743 parse_assign_func(lex, cmd.args);
00744 }
00745 else {
00746 cmd.type = kCmdAssignParam;
00747 cmd.args.push_back(lex.get_expected_token(kTokenLname));
00748 lex.get_expected_token(kTokenAssign);
00749 cmd.args.push_back(read_var(lex));
00750 }
00751 }
00752 else
00753 lex.throw_syntax_error("unexpected token after F/Z");
00754 }
00755
00756 void add_to_datasets(const Ftk* F_, vector<int>& datasets, int n)
00757 {
00758 if (n == Lexer::kAll)
00759 for (int j = 0; j != F_->get_dm_count(); ++j)
00760 datasets.push_back(j);
00761 else
00762 datasets.push_back(n);
00763 }
00764
00765 bool Parser::parse_statement(Lexer& lex)
00766 {
00767 st_.datasets.clear();
00768 st_.with_args.clear();
00769 st_.vdlist.clear();
00770 st_.commands.resize(1);
00771 st_.commands[0].args.clear();
00772 st_.commands[0].defined_tp.reset();
00773
00774 Token first = lex.peek_token();
00775 if (first.type == kTokenNop)
00776 return false;
00777 if (first.type == kTokenDataset) {
00778 lex.get_token();
00779 Token t = lex.get_token();
00780 if (t.type == kTokenDataset || t.type == kTokenColon) {
00781 add_to_datasets(F_, st_.datasets, first.value.i);
00782 while (t.type == kTokenDataset) {
00783 add_to_datasets(F_, st_.datasets, t.value.i);
00784 t = lex.get_expected_token(kTokenDataset, kTokenColon);
00785 }
00786 }
00787 else {
00788 lex.go_back(first);
00789 }
00790 }
00791 if (st_.datasets.empty())
00792 st_.datasets.push_back(F_->default_dm());
00793
00794 if (lex.peek_token().type == kTokenLname &&
00795 is_command(lex.peek_token(), "w","ith")) {
00796 lex.get_token();
00797 parse_set_args(lex, st_.with_args);
00798 }
00799
00800 parse_command(lex, st_.commands[0]);
00801
00802 while (lex.discard_token_if(kTokenSemicolon) &&
00803 lex.peek_token().type != kTokenNop) {
00804 st_.commands.resize(st_.commands.size() + 1);
00805 parse_command(lex, st_.commands.back());
00806 }
00807
00808 if (lex.peek_token().type != kTokenNop)
00809 lex.throw_syntax_error(S("unexpected token: `")
00810 + tokentype2str(lex.peek_token().type) + "'");
00811
00812 return true;
00813 }
00814
00815
00816 void Parser::parse_command(Lexer& lex, Command& cmd)
00817 {
00818 cmd.type = kCmdNull;
00819 const Token token = lex.get_token();
00820 if (token.type == kTokenLname) {
00821 if (is_command(token, "deb","ug")) {
00822 cmd.type = kCmdDebug;
00823 cmd.args.push_back(lex.get_token());
00824 cmd.args.push_back(lex.get_rest_of_line());
00825 }
00826 else if (is_command(token, "def","ine")) {
00827 cmd.type = kCmdDefine;
00828 cmd.defined_tp = parse_define_args(lex);
00829 }
00830 else if (is_command(token, "del","ete")) {
00831 if (lex.peek_token().type == kTokenOpen) {
00832 cmd.type = kCmdDeleteP;
00833 lex.get_expected_token(kTokenOpen);
00834 cmd.args.push_back(read_expr(lex));
00835 lex.get_expected_token(kTokenClose);
00836 }
00837 else {
00838 cmd.type = kCmdDelete;
00839 parse_delete_args(lex, cmd.args);
00840 }
00841 }
00842 else if (is_command(token, "e","xecute")) {
00843 cmd.type = kCmdExec;
00844 parse_exec_args(lex, cmd.args);
00845 }
00846 else if (is_command(token, "f","it")) {
00847 cmd.type = kCmdFit;
00848 parse_fit_args(lex, cmd.args);
00849 }
00850 else if (is_command(token, "g","uess")) {
00851 cmd.type = kCmdGuess;
00852 parse_guess_args(lex, cmd.args);
00853 }
00854 else if (is_command(token, "i","nfo")) {
00855 cmd.type = kCmdInfo;
00856 parse_info_args(lex, cmd.args);
00857 }
00858 else if (is_command(token, "pl","ot")) {
00859 cmd.type = kCmdPlot;
00860 parse_real_range(lex, cmd.args);
00861 parse_real_range(lex, cmd.args);
00862 while (lex.peek_token().type == kTokenDataset)
00863 cmd.args.push_back(lex.get_token());
00864 }
00865 else if (is_command(token, "p","rint")) {
00866 cmd.type = kCmdPrint;
00867 parse_print_args(lex, cmd.args);
00868 }
00869 else if (is_command(token, "quit","")) {
00870 cmd.type = kCmdQuit;
00871
00872 }
00873
00874
00875 else if (is_command(token, "s","et") &&
00876 !(token.length == 1 &&
00877 (lex.peek_token().type == kTokenAssign ||
00878 lex.peek_token().type == kTokenLSquare))) {
00879 cmd.type = kCmdSet;
00880 parse_set_args(lex, cmd.args);
00881 }
00882 else if (is_command(token, "undef","ine")) {
00883 cmd.type = kCmdUndef;
00884 parse_undefine_args(lex, cmd.args);
00885 }
00886 else if (is_command(token, "reset","")) {
00887 cmd.type = kCmdReset;
00888
00889 }
00890 else if (is_command(token, "sleep","")) {
00891 cmd.type = kCmdSleep;
00892 Token value = read_and_calc_expr(lex);
00893 cmd.args.push_back(value);
00894 }
00895 else if (is_command(token, "title","")) {
00896
00897 cmd.type = kCmdTitle;
00898 lex.get_expected_token(kTokenAssign);
00899 cmd.args.push_back(lex.get_filename_token());
00900 }
00901 else if (is_command(token, "use","")) {
00902 cmd.type = kCmdUse;
00903 cmd.args.push_back(lex.get_expected_token(kTokenDataset));
00904 }
00905 else if (token.length == 1 && (*token.str == 'x' || *token.str == 'y' ||
00906 *token.str == 's' || *token.str == 'a')){
00907 cmd.args.push_back(token);
00908 cmd.type = parse_xysa_args(lex, cmd.args);
00909 }
00910 }
00911 else if (token.type == kTokenUletter) {
00912 const char c = *token.str;
00913 if (c == 'F' || c == 'Z') {
00914 cmd.args.push_back(nop());
00915 cmd.args.push_back(token);
00916 parse_fz(lex, cmd);
00917 }
00918 else if (c == 'M') {
00919 cmd.type = kCmdResizeP;
00920 lex.get_expected_token(kTokenAssign);
00921 cmd.args.push_back(read_and_calc_expr(lex));
00922 }
00923 else if (c == 'X' || c == 'Y' || c == 'S' || c == 'A') {
00924 cmd.args.push_back(token);
00925 cmd.type = parse_xysa_args(lex, cmd.args);
00926 }
00927 else
00928 lex.throw_syntax_error("unknown name: " + token.as_string());
00929 }
00930 else if (token.type == kTokenBang) {
00931 cmd.type = kCmdShell;
00932 cmd.args.push_back(lex.get_rest_of_line());
00933 }
00934
00935 else if (token.type == kTokenVarname &&
00936 lex.peek_token().type == kTokenAssign) {
00937 cmd.type = kCmdNameVar;
00938 cmd.args.push_back(token);
00939 lex.get_token();
00940 cmd.args.push_back(read_var(lex));
00941 parse_real_range(lex, cmd.args);
00942 }
00943
00944 else if (token.type == kTokenFuncname &&
00945 lex.peek_token().type == kTokenAssign) {
00946 cmd.type = kCmdNameFunc;
00947 cmd.args.push_back(token);
00948 lex.get_token();
00949 parse_assign_func(lex, cmd.args);
00950 }
00951
00952 else if (token.type == kTokenFuncname &&
00953 lex.peek_token().type == kTokenDot) {
00954 cmd.type = kCmdAssignParam;
00955 cmd.args.push_back(token);
00956 lex.get_token();
00957 cmd.args.push_back(lex.get_expected_token(kTokenLname));
00958 lex.get_expected_token(kTokenAssign);
00959 cmd.args.push_back(read_var(lex));
00960 }
00961 else if (token.type == kTokenDataset &&
00962 lex.peek_token().type == kTokenDot) {
00963 cmd.args.push_back(token);
00964 lex.get_token();
00965 string arg = lex.peek_token().as_string();
00966 if (arg == "F" || arg == "Z") {
00967 cmd.args.push_back(lex.get_token());
00968 parse_fz(lex, cmd);
00969 }
00970 else
00971 lex.throw_syntax_error("@n. must be followed by F or Z");
00972 }
00973 else if (token.type == kTokenDataset &&
00974 lex.peek_token().type == kTokenLT) {
00975 cmd.type = kCmdLoad;
00976 cmd.args.push_back(token);
00977 lex.get_token();
00978 cmd.args.push_back(lex.get_filename_token());
00979 while (lex.peek_token().type == kTokenLname)
00980 cmd.args.push_back(lex.get_token());
00981 }
00982 else if (token.type == kTokenDataset &&
00983 lex.peek_token().type == kTokenAssign) {
00984 cmd.type = kCmdDatasetTr;
00985 cmd.args.push_back(token);
00986 lex.get_token();
00987 cmd.args.push_back(read_expr(lex, ExpressionParser::kDatasetTrMode));
00988 }
00989
00990 if (cmd.type == kCmdNull)
00991 lex.throw_syntax_error("unexpected token at command beginning");
00992 }
00993
00994 bool Parser::check_syntax(const string& str)
00995 {
00996 try {
00997 Lexer lex(str.c_str());
00998 parse_statement(lex);
00999 } catch (ExecuteError&) {
01000 return false;
01001 } catch (SyntaxError&) {
01002
01003
01004 return false;
01005 }
01006 return true;
01007 }
01008
01009 string Parser::get_statements_repr() const
01010 {
01011 string r = "datasets: " + join_vector(st_.datasets, " ");
01012 if (!st_.with_args.empty()) {
01013 r += "\nWith:";
01014 v_foreach (Token, i, st_.with_args)
01015 r += "\n\t" + token2str(*i);
01016 }
01017 v_foreach (Command, i, st_.commands) {
01018 r += S("\n") + commandtype2str(i->type);
01019 v_foreach (Token, j, i->args)
01020 r += "\n\t" + token2str(*j);
01021 }
01022 return r;
01023 }
01024