New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implemented parsing (string -> Basic) #772
Conversation
I think this looks nice and clean. My only comment is about naming conventions --- |
|
||
namespace SymEngine { | ||
|
||
class expressionParser |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Class name should start with Caps.
I think all source is in |
|
||
public: | ||
|
||
RCP<const Basic> parse_string(unsigned int l, unsigned int h) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you think of any case where it might be useful to expose this by making parse_string
public? I didn't see this in the tests. If not, it would be better to keep it private.
Will get it done. Right now, my main focus is getting the function to work correctly, and including all features. Variable names, formatting and trivial changes, I'll make later. |
Looks good to me. If you have any doubts, please feel free to ask.
|
if(expr == "ln") return log(param1); | ||
|
||
if(expr == "zeta") if(s[iter+1] != ',') return zeta(param1); | ||
if(expr == "log") if(s[iter+1] != ',') return log(param1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of a linear search (i.e. a linear list of ifs), one can probably make it faster by checking std::map
or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't think anything faster than linear is possible. I have to search if 'any' of them matches, and do a unique thing on a match. I am not looking to 'find' an element in a array/map. Whatever way it is implemented, it will have to boil down to checking each the expr
against each of these terms. (or something equivalent to these linear checks)
One complicated way to optimize maybe to make a search tree based on the letters of the expr
. But I feel that is an overkill. Maybe do it after the main tasks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can see how to optimize this later.
Your current solution is O(n). A faster is to use O(log(n)) or O(1) using std::map
or std::unordered_map
, and you store a lambda function there that will do what you need.
The mingw is failing because it can't find |
http://www.cplusplus.com/reference/string/stoi/ |
|
some function arguments can be made |
{'*', 3}, {'/', 4}, {'^', 5} | ||
}; | ||
std::map<std::string, RCP<const Basic> > constants = { | ||
{"e", E}, {"EulerGamma", EulerGamma}, {"pi", pi} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add I
as a constant too. Then complex numbers will be supported as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh didn't think about that! Thanks!
// i am still not clear about the fundamentals of realdouble | ||
|
||
s = "sqrt(2.0)+5"; | ||
// s = "sqrt(2)+5" this fails! (will the user add `.0` to integers to get them `computed`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this line. It's supposed to work that way. If the user just wants numerics, then they are better off using a specialized library.
if (in[i] == ' ') { | ||
continue; | ||
|
||
} else if (in[i] == '*' and in[(i+1) % in.length()] == '*') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
% in.length()
why is this there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If in[i]
is the last character of the entered string, in[i+1]
goes out of bounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then the best approach would be to check that i + 1 < in.length()
.
Looks good to me. Can you add a header file |
Looks good to me too! +1 |
@certik Can you have a final look at this? |
|
||
#include <symengine/basic.h> | ||
#include <symengine/dict.h> | ||
#include <symengine/parser.cpp> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not include a .cpp
file. Remove this include and just change
inline RCP<const Basic> parse(std::string& s) {
ExpressionParser p;
return p.parse_expr(s);
}
to
RCP<const Basic> parse(const std::string& s);
and implement it in parser.cpp
. Also make the input argument const
, as I did.
I left some comments. Otherwise it looks good to me as well. |
@certik made the changes |
The header change is good, thanks. Please ping me once you fix the const thing, I'll do one final review. |
done @certik |
+1 to merge as it is, if tests pass. |
I'm not able to figure out what's wrong with the build. After changing all the maps to |
Ok, revert the const change, just to the header file change. In general, create git commits that are logical. So the header file change should go into its own commit. Since we both approved it, you just push it in and let it be. Then we can tackle the const thing, and if it's difficult, we can do it in a future PR. |
Btw, the reason it fails is because the Just forget about the const thing in this PR, fix the header and make sure all tests pass. Then we can merge this. |
@certik done |
I think that this looks good. Thanks for the work! |
implemented parsing (string -> Basic)
Addresses #559