Can someone point me in the right direction to begin parsing this string in dart? - dart

I have a series of string like this:
(((S|69|L || S|69|R || S|72|L || S|72|R) && ((S|62|L && (S|78|L || S|55|L) && (S|77|L || S|1|L)) || (S|62|R && (S|78|R || S|55|R) && (S|77|R || S|1|R)))) && (M|34|L || M|34|R) && (((M|40|L && M|39|L && M|36|L) || (M|40|R && M|39|R && M|36|R)) || ((M|38|L && M|36|L && M|37|L) || (M|38|R && M|36|R && M|37|R))))
And I need to run items that look like S|69|L to see if they satisfy this criteria. You can see that it's a series of && or || operations organized by parentheses.
I'm trying to use this tutorial: https://github.com/petitparser/dart-petitparser
But I'm having trouble getting off of the ground. Can anyone give me an example to get started with this? Maybe I just need more coffee...
Update: Making progress. This at least pulls off outside parentheses. I think I just need to continue to play with it, but I would still appreciate any tips for those who know how this works.
String testString = '((1||2) || 3)';
final inner = undefined();
final paren = (char('(').trim() & inner.star().flatten() & char(')').trim())
.map((values) => values[1]);
inner.set(paren | pattern('^)'));
final parser = inner.end();
final result = parser.parse(testString);
print(result.value);

The grammar you provide in the question seems to work for me and the provided example inputs pass.
A couple of tips:
If you are not interested in the parser output, instead of calling parser.parse(input) you could use parser.accept(input) to get a boolean.
Similarly, if you are not interested in the output, you can drop the calls to flatten() and map(...). Both are used to build an AST. Furthermore, flatten() hides the generated tree, which can make it hard to see what is happening.
For the actual values you could use a primitive parser like the following. However, not sure what your exact specification is?
final primitive = (uppercase() & char('|') & digit().plus() & char('|') & uppercase()).flatten().trim();
If you have the primitive parser, you can add an undefined parser for the logical expression (called outer) like so:
final outer = undefined();
final inner = undefined();
final operator = string('&&') | string('||');
outer.set(inner.separatedBy(operator));
final paren = char('(').trim() & outer & char(')').trim();
inner.set(paren | primitive);
final parser = outer.end();
Building expression parsers can get complicated and unwieldy quite quickly. With the Expression Builder this becomes much simpler:
final builder = ExpressionBuilder();
builder.group().primitive(primitive);
builder.group()
.wrapper(char('(').trim(), char(')').trim(), (l, v, r) => [l, v, r]);
builder.group()
..left(string('&&').trim(), (a, op, b) => [a, '&&', b])
..left(string('||').trim(), (a, op, b) => [a, '||', b]);
final parser = builder.build().end();

Related

Why does Dart typing system make equate difficult and does that bar pattern matching?

I tried to do this thing in dart but it failed and I don't really understand why. I know that dart doesn't support robust "Pattern Matching" like elixir does, but I thought it should be able to compare two lists. No. Why not? what is it about the typing system that can't equate two lists and if it could, could it support even rudimentary pattern matching? I'm just trying to understand how equate works in dart I guess.
void main() {
final x = 1;
final y = 2;
if (x == 1 && y == 2) {
print('this works fine of course');
}
if ([1, 2] == [1, 2]) {
print('but this does not');
}
if ([x, y] == [1, 2]) {
print('would this work if dart could equate lists?');
}
}
Dart lists do not implement operator== in a way that checks the elements for equality.
Dart lists are assumed to be mutable, and the Dart platform libraries generally do not provide an equality for mutable objects, because they are not guaranteed to preserve that equality over time.
Also, for lists, because it's not obvious which equality to use. Should it just compare elements? Then a <num>[1] list would be equal to <int>[1], even if they are very different lists.
For those reasons, you are supposed to decide which equality you actually want, without one being the canonical one.
You can, for example, use const ListEquality().equals from package:collection. It defaults to using == on the elements, but can be configured to use other equalities as well.
import 'package:flutter/foundation.dart';
void main() async {
final x = 1;
final y = 2;
if (x == 1 && y == 2) {
print('this works fine of course');
}
if (listEquals([1, 2],[1, 2])) {
print('Yep');
}
if (listEquals([x, y], [1, 2])) {
print('would this work if dart could equate lists? Yep');
}
}
Output:
this works fine of course
Yep
would this work if dart could equate lists? Yep

Trouble with TransitiveClosure function in Z3Py

I am trying to model graph connectivity with Z3. Specifically I am partitioning a graph and need the subgraphs to remain connected. However TransitiveClosure doesn't work as I expect. I model edges with F
Here's a MWE:
s = Solver()
N = DeclareSort('N')
a,b,c = Consts('a b c', N)
F = Function(N,N,BoolSort())
s.add(F(A,B) == True)
s.add(F(B,A) == True)
s.add(F(B,C) == False)
s.add(F(C,B) == False)
s.add(F(A,C) == False)
s.add(F(C,A) == False)
s.add(A != B, B != C, C != A)
FX = TransitiveClosure(F)
s.add(FX(A,C))
This is apparently SAT, which doesn't make much sense to me. If I change s.add(FX(A,C)) to s.add(Not(FX(A,C))).
Why is this? C should not be a member of FX. Am I somehow setting FX(A,C) == True) by adding it to the model? Why doesn't that conflict with the definition of FX.
The output/connection lines of the model are hard to understand so I'm not quite sure what's going on.
I am working with tclosures as well and found this helpful: https://theory.stanford.edu/~nikolaj/programmingz3.html#sec-transitive-closure
Maybe there is an answer to your 2nd question as well.

Process user-inputted conditions (==, &&) inside app

I have the task, and I can understand how to deal with it (in what direction I need to start). Application need to understand user-inputted condition like that:
((VAR1 != 1 && VAR2 == 2) OR (VAR3 != 1 && VAR4 == 2)) AND (VAR5 = 2)
I have that variables inside my database, so it's no problem to replace VAR1 with real data. How in what way I can process that condition inside application. I thought about separating full condition to little blocks, but I don't understand yet how to separate, there is no symbol that I can split string.
So can you help in what direction I need to start working to process such conditions in Swift app?
Thanks to #Sulthan, NSPredicate is solution.
let expressionString = "((1 == 1) or (1 == 2)) and (1 == 2)"
let predicate = NSPredicate(format: expressionString)
print(predicate.evaluateWithObject(nil))
// Output: false

Get the `Middle` of a string with certain prefix and postfix?

The following active pattern doesn't use regular expression for better performance. However, it seems quite procedural style. Is it a better way to write in F#?
let (|Middle|_|) prefix postfix (input : string) =
if input.StartsWith(prefix) && input.EndsWith(postfix)
&& input.Length > prefix.Length + postfix.Length then
let len = input.Length - prefix.Length - postfix.Length
Some(input.Substring(prefix.Length, len))
else None
I think it's fine.
Why do you think it's not functional?
I would change only the last line in order to use string slices:
if input.StartsWith(prefix) && input.EndsWith(postfix)
&& input.Length > prefix.Length + postfix.Length then
Some(input.[prefix.Length .. input.Length - postfix.Length - 1])
else None
Anyway I don't think it makes it more functional.

Inverse if statement

I have a question about Objective C
I want an inverted if statement. Like: if (!example.hidden == YES) {
Here's my code:
if ((randomBallTouch.x>_randomColorBall.center.x-(_randomColorBall.frame.size.width)/2) &&
(randomBallTouch.x<_randomColorBall.center.x+(_randomColorBall.frame.size.width)/2) &&
(randomBallTouch.y>_randomColorBall.center.y-(_randomColorBall.frame.size.height)/2) &&
(randomBallTouch.y<_randomColorBall.center.y+(_randomColorBall.frame.size.height)/2)) {
_randomColorBall.center = CGPointMake(randomBallTouch.x, randomBallTouch.y);
if (_randomColorBall.hidden == NO) {
_redBall.center = CGPointMake(_redBall.center.x, _redBall.center.y - 200);
}
}
But when i do: if(!(randomBallTouch.x>_randomColorBall.center.x)) etc. It does not work.
And I can't do else because that will bug with the other two if statements.
Any help?? I am using Xcode 5.1.
You can't just add an ! at the beginning to invert the condition. You need to wrap the whole expression in a set of parentheses first.
If you have:
if (a && b) {
then the inversion is:
if (!(a && b)) {
You didn't add those parentheses.
Try this, just replace your if with this one.
if(!((randomBallTouch.x > (_randomColorBall.center.x-(_randomColorBall.frame.size.width)/2)) && (randomBallTouch.x < (_randomColorBall.center.x+(_randomColorBall.frame.size.width)/2)) && (randomBallTouch.y > (_randomColorBall.center.y-(_randomColorBall.frame.size.height)/2)) &&(randomBallTouch.y < (_randomColorBall.center.y+(_randomColorBall.frame.size.height)/2)))) {
You are missing a lot of parenthesis to make your statement a valid boolean.

Resources