Skip to content
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

Redmine#2111: eval() function for math evaluation #882

Merged
merged 2 commits into from Sep 10, 2013

Conversation

tzz
Copy link
Contributor

@tzz tzz commented Aug 16, 2013

Feature requested in https://cfengine.com/dev/issues/2111

This implementation uses a PEG (parsing expression grammar). The peg tool used to compile math.peg into math.pc (a C file) is MIT licensed at http://piumarta.com/software/peg/ and is tiny, so it could be included in the distribution. I've included math.pc in a separate commit so you can test it, and added a rudimentary Makefile.am rule to generate it via peg -o math.pc math.peg.

Note that unlike lex, the expression parser here is reentrant and thread-safe. It works off a local context for every invocation, so there are no global variables. The trivial stack implementation resides in the local context as well.

I am not sure about the mechanics of incorporating the peg tool or math.pc into the Automake process properly.

The list of functions and operators is trivial to extend through math.peg and the grammar is (IMHO) much simpler to write and understand than the classic lex+yacc grammars, so I feel this is a good extensible solution.

Acceptance test included. I will add documentation if this pull request is accepted in some form.

@tzz
Copy link
Contributor Author

tzz commented Aug 16, 2013

There are lots of warnings when compiling; they can be cleaned up or silenced if the general approach is OK.

@tzz
Copy link
Contributor Author

tzz commented Sep 3, 2013

Any blockers to merging this?

@kacf
Copy link
Contributor

kacf commented Sep 4, 2013

I like the idea!

Some thoughts: I would disable the Makefile rule. If we don't build the tool by default, people will just be confused if Git happens to check out the files with slightly different timestamps and 'make' tries to rebuild it. Put a comment at the top of the peg file instead on how to rebuild it.

I also think we should include the tool if it is not common to have it. Make a 3rdparty folder or something like that. Otherwise we risk that other site going down and us being stranded with no way to generate a new file.

Remember documentation!

{
vars:
"values[0]" string => "x";
"values[1]" string => "+ 200";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unary plus not allowed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not mathematically valid so I disallowed it. libmatheval agrees with me FWIW, but I can allow it if you think it's needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it seems a bit odd, but I have no strong preference.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

:P

@kacf
Copy link
Contributor

kacf commented Sep 4, 2013

I also think we should include the tool if it is not common to have it.

When I say include, I don't mean build.

@tzz
Copy link
Contributor Author

tzz commented Sep 4, 2013

I'll write docs when the feature is merged.

I'm OK with just including the compiled syntax, it's very unlikely to change, and removing the Makefile rule. We can put http://piumarta.com/software/peg/ under contrib/ or or 3rdparty/ or somewhere else and document how to regenerate the syntax. If that plan sounds good to you and @vohi I'll do it. Please confirm.

@kacf
Copy link
Contributor

kacf commented Sep 4, 2013

Yep, sounds good!

@tzz
Copy link
Contributor Author

tzz commented Sep 4, 2013

Please don't merge, still under discussion.

@kacf
Copy link
Contributor

kacf commented Sep 5, 2013

There is no license in the peg directory. We should make it clear it is MIT licensed.


#include <math.pc>

double EvaluateMathInfix(EvalContext *ctx, char *input, char *failure)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use const char * here, at least for input.

Is failure supposed to contain a message if the evaluation fails? How do we know peg will not write a longer message than we have allocated for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input constified.

The failure is only populated once, with strcpy(yy->failure, "expression could not be parsed"). Should I use strncpy()?

@tzz
Copy link
Contributor Author

tzz commented Sep 5, 2013

OK, license brought in, inputs constified, and tests still pass.

@kacf
Copy link
Contributor

kacf commented Sep 10, 2013

Alright, looks good with the fixes! Merge when you want!

@cduclos
Copy link
Contributor

cduclos commented Sep 10, 2013

Can one of the admins verify this patch?

tzz added a commit that referenced this pull request Sep 10, 2013
Redmine#2111: eval() function for math evaluation
@tzz tzz merged commit eec5b34 into cfengine:master Sep 10, 2013
@tzz
Copy link
Contributor Author

tzz commented Sep 10, 2013

@vohi @kacfengine I will write the docs later today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants