]> www.ginac.de Git - ginac.git/blobdiff - ginsh/ginsh_parser.yy
Make sure add::eval() collects all numeric terms.
[ginac.git] / ginsh / ginsh_parser.yy
index 79ae94cee86b8d576eac497ec44e1b26d2705272..9783bf8cdb129711cf7b17c86925e025701ca292 100644 (file)
@@ -4,7 +4,7 @@
  *  This file must be processed with yacc/bison. */
 
 /*
- *  GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2010 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 
 %{
 #include "config.h"
-
+#ifdef HAVE_RUSAGE
 #include <sys/resource.h>
+#else
+#include <ctime>
+#endif
 
 #if HAVE_UNISTD_H
 #include <sys/types.h>
 
 #define YYERROR_VERBOSE 1
 
+#ifdef HAVE_LIBREADLINE
 // Original readline settings
 static int orig_completion_append_character;
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-static char *orig_basic_word_break_characters;
-#else
 static const char *orig_basic_word_break_characters;
-#endif
 
-#if (GINAC_RL_VERSION_MAJOR >= 5)
+#if (RL_VERSION_MAJOR >= 5)
 #define GINAC_RL_COMPLETER_CAST(a) const_cast<char *>((a))
 #else
 #define GINAC_RL_COMPLETER_CAST(a) (a)
 #endif
+#endif // HAVE_LIBREADLINE
 
 // Expression stack for %, %% and %%%
 static void push(const ex &e);
 static ex exstack[3];
+// Assigned symbols
+static exmap assigned_symbol_table;
 
 // Start and end time for the time() function
+#ifdef HAVE_RUSAGE
 static struct rusage start_time, end_time;
+#define START_TIMER getrusage(RUSAGE_SELF, &start_time);
+#define STOP_TIMER getrusage(RUSAGE_SELF, &end_time);
+#define PRINT_TIME_USED cout << \
+   (end_time.ru_utime.tv_sec - start_time.ru_utime.tv_sec) + \
+       (end_time.ru_stime.tv_sec - start_time.ru_stime.tv_sec) + \
+       double(end_time.ru_utime.tv_usec - start_time.ru_utime.tv_usec) / 1e6 + \
+       double(end_time.ru_stime.tv_usec - start_time.ru_stime.tv_usec) / 1e6 \
+                       << 's' << endl;
+#else
+static std::clock_t start_time, end_time;
+#define START_TIMER start_time = std::clock();
+#define STOP_TIMER end_time = std::clock();
+#define PRINT_TIME_USED \
+  cout << double(end_time - start_time)/CLOCKS_PER_SEC << 's' << endl;
+#endif
 
 // Table of functions (a multimap, because one function may appear with different
 // numbers of parameters)
@@ -210,19 +229,19 @@ line      : ';'
        }
        | T_REAL_SYMBOLS { symboltype = domain::real; }
        | T_COMPLEX_SYMBOLS { symboltype = domain::complex; }
-       | T_TIME {getrusage(RUSAGE_SELF, &start_time);} '(' exp ')' {
-               getrusage(RUSAGE_SELF, &end_time);
-               cout << (end_time.ru_utime.tv_sec - start_time.ru_utime.tv_sec) +
-                       (end_time.ru_stime.tv_sec - start_time.ru_stime.tv_sec) +
-                        double(end_time.ru_utime.tv_usec - start_time.ru_utime.tv_usec) / 1e6 +
-                        double(end_time.ru_stime.tv_usec - start_time.ru_stime.tv_usec) / 1e6 << 's' << endl;
-       }
+       | T_TIME { START_TIMER } '(' exp ')' { STOP_TIMER PRINT_TIME_USED }
        | error ';'             {yyclearin; yyerrok;}
        | error ':'             {yyclearin; yyerrok;}
        ;
 
 exp    : T_NUMBER              {$$ = $1;}
-       | T_SYMBOL              {$$ = $1.eval();}
+       | T_SYMBOL              {
+               exmap::const_iterator i = assigned_symbol_table.find($1);
+               if (i == assigned_symbol_table.end())
+                       $$ = $1;
+               else
+                       $$ = i->second.eval();
+       }
        | '\'' T_SYMBOL '\''    {$$ = $2;}
        | T_LITERAL             {$$ = $1;}
        | T_DIGITS              {$$ = $1;}
@@ -238,7 +257,7 @@ exp : T_NUMBER              {$$ = $1;}
                }
        }
        | T_DIGITS '=' T_NUMBER {$$ = $3; Digits = ex_to<numeric>($3).to_int();}
-       | T_SYMBOL '=' exp      {$$ = $3; const_cast<symbol&>(ex_to<symbol>($1)).assign($3);}
+       | T_SYMBOL '=' exp      {$$ = $3; assigned_symbol_table[$1] = $3; }
        | exp T_EQUAL exp       {$$ = $1 == $3;}
        | exp T_NOTEQ exp       {$$ = $1 != $3;}
        | exp '<' exp           {$$ = $1 < $3;}
@@ -315,6 +334,7 @@ static ex f_evalf1(const exprseq &e) {return e[0].evalf();}
 static ex f_evalm(const exprseq &e) {return e[0].evalm();}
 static ex f_eval_integ(const exprseq &e) {return e[0].eval_integ();}
 static ex f_expand(const exprseq &e) {return e[0].expand();}
+static ex f_factor(const exprseq &e) {return factor(e[0]);}
 static ex f_gcd(const exprseq &e) {return gcd(e[0], e[1]);}
 static ex f_has(const exprseq &e) {return e[0].has(e[1]) ? ex(1) : ex(0);}
 static ex f_lcm(const exprseq &e) {return lcm(e[0], e[1]);}
@@ -406,9 +426,20 @@ static ex f_evalf2(const exprseq &e)
 
 static ex f_find(const exprseq &e)
 {
-       lst found;
+       exset found;
        e[0].find(e[1], found);
-       return found;
+       lst l;
+       for (exset::const_iterator i = found.begin(); i != found.end(); ++i)
+               l.append(*i);
+       return l;
+}
+
+static ex f_fsolve(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, fsolve);
+       CHECK_ARG(2, numeric, fsolve);
+       CHECK_ARG(3, numeric, fsolve);
+       return fsolve(e[0], ex_to<symbol>(e[1]), ex_to<numeric>(e[2]), ex_to<numeric>(e[3]));
 }
 
 static ex f_integer_content(const exprseq &e)
@@ -450,11 +481,14 @@ static ex f_map(const exprseq &e)
 
 static ex f_match(const exprseq &e)
 {
-       lst repl_lst;
-       if (e[0].match(e[1], repl_lst))
+       exmap repls;
+       if (e[0].match(e[1], repls)) {
+               lst repl_lst;
+               for (exmap::const_iterator i = repls.begin(); i != repls.end(); ++i)
+                       repl_lst.append(relational(i->first, i->second, relational::equal));
                return repl_lst;
-       else
-               return fail();
+       }
+       throw std::runtime_error("FAIL");
 }
 
 static ex f_normal2(const exprseq &e)
@@ -543,7 +577,9 @@ static ex f_transpose(const exprseq &e)
 static ex f_unassign(const exprseq &e)
 {
        CHECK_ARG(0, symbol, unassign);
-       const_cast<symbol&>(ex_to<symbol>(e[0])).unassign();
+       exmap::iterator i = assigned_symbol_table.find(e[0]);
+       if (i != assigned_symbol_table.end())
+               assigned_symbol_table.erase(i);
        return e[0];
 }
 
@@ -587,7 +623,9 @@ static const fcn_init builtin_fcns[] = {
        {"evalm", f_evalm, 1},
        {"eval_integ", f_eval_integ, 1},
        {"expand", f_expand, 1},
+       {"factor", f_factor, 1},
        {"find", f_find, 2},
+       {"fsolve", f_fsolve, 4},
        {"gcd", f_gcd, 2},
        {"has", f_has, 2},
        {"integer_content", f_integer_content, 1},
@@ -689,11 +727,12 @@ static void insert_fcns(const fcn_init *p)
 
 static ex f_ginac_function(const exprseq &es, int serial)
 {
-       return function(serial, es).eval(1);
+       return GiNaC::function(serial, es).eval(1);
 }
 
 // All registered GiNaC functions
-void GiNaC::ginsh_get_ginac_functions(void)
+namespace GiNaC {
+void ginsh_get_ginac_functions(void)
 {
        vector<function_options>::const_iterator i = function::registered_functions().begin(), end = function::registered_functions().end();
        unsigned serial = 0;
@@ -703,6 +742,7 @@ void GiNaC::ginsh_get_ginac_functions(void)
                serial++;
        }
 }
+}
 
 
 /*
@@ -826,6 +866,7 @@ static char *fcn_generator(const char *text, int state)
        return NULL;
 }
 
+#ifdef HAVE_LIBREADLINE
 static char **fcn_completion(const char *text, int start, int end)
 {
        if (rl_line_buffer[0] == '!') {
@@ -833,28 +874,32 @@ static char **fcn_completion(const char *text, int start, int end)
                rl_completion_append_character = orig_completion_append_character;
                rl_basic_word_break_characters = orig_basic_word_break_characters;
                rl_completer_word_break_characters = GINAC_RL_COMPLETER_CAST(rl_basic_word_break_characters);
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-               return completion_matches(const_cast<char *>(text), (CPFunction *)filename_completion_function);
-#else
                return rl_completion_matches(text, rl_filename_completion_function);
-#endif
        } else {
                // Otherwise, complete function names
                rl_completion_append_character = '(';
                rl_basic_word_break_characters = " \t\n\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~";
                rl_completer_word_break_characters = GINAC_RL_COMPLETER_CAST(rl_basic_word_break_characters);
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-               return completion_matches(const_cast<char *>(text), (CPFunction *)fcn_generator);
-#else
                return rl_completion_matches(text, fcn_generator);
-#endif
        }
 }
+#endif // HAVE_LIBREADLINE
+
+static void ginsh_readline_init(char* name)
+{
+#ifdef HAVE_LIBREADLINE
+       // Init readline completer
+       rl_readline_name = name;
+       rl_attempted_completion_function = fcn_completion;
+       orig_completion_append_character = rl_completion_append_character;
+       orig_basic_word_break_characters = rl_basic_word_break_characters;
+#endif // HAVE_LIBREADLINE
+}
 
 void greeting(void)
 {
     cout << "ginsh - GiNaC Interactive Shell (" << PACKAGE << " V" << VERSION << ")" << endl;
-    cout << "  __,  _______  Copyright (C) 1999-2005 Johannes Gutenberg University Mainz,\n"
+    cout << "  __,  _______  Copyright (C) 1999-2010 Johannes Gutenberg University Mainz,\n"
          << " (__) *       | Germany.  This is free software with ABSOLUTELY NO WARRANTY.\n"
          << "  ._) i N a C | You are welcome to redistribute it under certain conditions.\n"
          << "<-------------' For details type `warranty;'.\n" << endl;
@@ -870,6 +915,7 @@ int main(int argc, char **argv)
        // Print banner in interactive mode
        if (isatty(0)) 
                greeting();
+       assigned_symbol_table = exmap();
 
        // Init function table
        insert_fcns(builtin_fcns);
@@ -893,15 +939,7 @@ int main(int argc, char **argv)
        insert_help("print_latex", "print_latex(expression) - prints a LaTeX representation of the given expression");
        insert_help("print_csrc", "print_csrc(expression) - prints a C source code representation of the given expression");
 
-       // Init readline completer
-       rl_readline_name = argv[0];
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-       rl_attempted_completion_function = (CPPFunction *)fcn_completion;
-#else
-       rl_attempted_completion_function = fcn_completion;
-#endif
-       orig_completion_append_character = rl_completion_append_character;
-       orig_basic_word_break_characters = rl_basic_word_break_characters;
+       ginsh_readline_init(argv[0]);
 
        // Init input file list, open first file
        num_files = argc - 1;