-
Notifications
You must be signed in to change notification settings - Fork 12
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
Function with constants variables #2
Comments
Hello @mrxrsd, here you are: using ParameterList = System.Collections.Generic.Dictionary<string, double>;
public Expression<Func<ParameterList, double>> ParseFunction(string text,
ParameterList constants)
{
var calc = new XtensibleCalculator();
var parsed = calc.ParseFunction(text).Compile();
return c => CallWithConstants(parsed, constants, c);
}
public double CallWithConstants(Func<ParameterList, double> function,
ParameterList constants, ParameterList variables)
{
var allVars = constants.Concat(variables).ToDictionary(p => p.Key, p => p.Value);
return function(allVars);
} You can use the code like this: using ParameterList = System.Collections.Generic.Dictionary<string, double>;
static void Main()
{
// parse function with constants
var constants = new ParameterList{{ "a", 1 }, { "b", 2 }};
var parsed = ParseFunction("a+b+c", constants);
var compiled = parsed.Compile();
// call compiled function with variables
var variables = new ParameterList{{ "c", 3 }};
compiled(variables);
} |
It seems like it would be nice to have a more succinct way to write this, so that you can go from a simple calculator to a Von Neumann style computer with registers / saved state. The following doesn't seem possible in Sprache.Calc out of the box:
Otherwise, this library seems like a good start for a project I want to prove to myself I can write. To be clear, I think some guidelines on the following might be worth brainstorming:
|
Hi, Take a look at Jace .net. |
@thiagottt Interesting; thanks. I started making progress towards using Sprache. Do you have any comparison between the two? It seems as though Jace.NET doesn't actually have a "local constant registry" as proposed in that issue, nor is it extensible like Sprache or Sprache.Calc is. For some background, I am trying to replace a homebrewed alert system written using regular expressions. The language examples looks something like:
or
or
Effectively, the last line in a "program" is always the return value. It may or may not start with an "=" sign. |
I think that, I can't use Jace.NET, given the constraints of over >1000 tiny "programs" I would then need to port to Jace.NET. |
Keep in mind that Sprache.Calc doesn't have extensible AST. It uses LINQ expressions as the data model, so everything it generates should be assignable to Expression. As far as I remember, LINQ expressions have support for statements since .NET 4.x, something like |
Hi @yallie One piece of feedback on your CodeProject article: It is a little counter-intuitive to me to declare the Parser properties as virtual instead of |
Just thinking about this comment. Why can't you "lift" such expressions? In effect, massage the data model a bit before trying to convert everything to an expression tree. You can use erecruit.Expr to simplify some of your expression tree manipualtion. |
Thanks for your feedback! Sprache.Calc is my study on grammar inheritance, and everything is virtual so it can be overridden in derived classes. It's not a tutorial on writing Sprache parsers, it's more like an experiment on alternative ways of combining parsers. Using built-in LINQ expression classes is just a way to keep my own code down to minimum. I definitely agree that custom AST classes would give much more flexibility in terms of manipulating the expressions, but it wasn't the goal :) |
Yeah, you may want to Google for The Expression Problem / The Extensibility Problem. Rather than phrasing the problem as "experiment on ways combining parsers", rephrase the problem as independently adding new operators and operands. Note: I am good at the theory, but suck at the practice, so easier said than done:) |
I was interested in parsing different language dialects, like PostgreSQL and Oracle SQL for example, while reusing the core parser. Using OOP inheritance seemed to me like a natural tool for overriding different language parts. |
That makes sense. It appears Nicholas has written a "sequel" to Sprache
called Superpower, which is probably a better basis for very complex
grammars like the ANSI SQL grammar and its vendor-specific extensions.
Did you ever write C#-based parsers for those languages? I'd be very
interested to use them in FluentMigrator, even if they're slow and/or give
bad error messages.
…On Thu, Oct 17, 2019 at 5:00 PM Alexey Yakovlev ***@***.***> wrote:
Rather than phrasing the problem as "experiment on ways combining
parsers", rephrase the problem as independently adding new operators and
operands.
I was interested in parsing different language dialects, like PostgreSQL
and Oracle SQL for example, while reusing the core parser. Using OOP
inheritance seemed to me like a natural tool for overriding different
language parts.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#2?email_source=notifications&email_token=AADNH7INK4D5BEOSM6WFH2LQPDG5ZA5CNFSM4HV6BPPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBRQGKQ#issuecomment-543359786>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADNH7LTKPO4DEM4JMI6S7LQPDG5ZANCNFSM4HV6BPPA>
.
|
Yes, it's not as easy to use as Sprache, but it probably has better error reporting.
No I didn't, that was just an example, sorry :) |
The only grammar inheritance I like is basically the "pluggable parsing"
concepts from Alex Warth and OMeta. The idea is that you use packrat
expression grammar parsers to define the "first" part of your grammar and
the "Rest" as a plug-in. You can the augment a grammar by incrementally
refining what "Rest" Parser(s) do.
However, I am skeptical about its utility on really large scale systems
like ANSI SQL, due to the number of "production rules" in the grammar.
…On Thu, Oct 17, 2019 at 5:52 PM Alexey Yakovlev ***@***.***> wrote:
It appears Nicholas has written a "sequel" to Sprache called Superpower
Yes, it's not as easy to use as Sprache, but it probably has better error
reporting.
Did you ever write C#-based parsers for those languages?
No I didn't, that was just an example, sorry :)
Not sure if I ever used grammar inheritance in a real project.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#2?email_source=notifications&email_token=AADNH7I3TAHNT4H4H5CIKTDQPDNB7A5CNFSM4HV6BPPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBRUNRY#issuecomment-543377095>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADNH7I5D7XFDLCX5JAKV6DQPDNB7ANCNFSM4HV6BPPA>
.
|
Hi,
Is it possible to add constant vars when build a function? something like this:
var fn = calc.ParseFunction("a+b+c");
fn.Variables.Add("a",1);
fn.Variables.Add("b",1);
var compileFn = fn.Compile();
var result = compileFn(new Dictionary<string, double> { { "c", 2 } });
Or I need to interpolation constants variable before parse function?
tks
The text was updated successfully, but these errors were encountered: