Parsing expressions ! chain of operators - parsing

hi I know how to parse expressions (incl. brackets).
But normally parsing expressions assumes "operand operator operand".
F.e. :
5 + 12
( 5 * 6 ) + 11
( 3 + 4 ) + ( 5 * 2)
As you can see the values are always two.
What I'm looking for is mechanism (grammar) than can parse chain of similar operators as a single item i.e. greedy
F.e. let say I have the following expression :
5 + 4 + 2 + 7 * 6 * 2
=> sum(5 + 4 + 2)
+
=> mult(7 * 6 * 2)
I want the parser to gobble the sum as one single "action", the same for multiplication.
Here is one example of NON-working grammar, but may be you can get the idea what I want to do (python - LEPL module) :
def build_grammar2(self):
spaces = Token('[ \t]+')[:]
plus = Token('\+')
left_bracket = Token('\(')
right_bracket = Token('\)')
mult = Token('\*')
bit_var = Token('[a-zA-Z0-9_!\?]+')
# with Separator(~spaces):
expr, group2 = Delayed(), Delayed()
mul_node = bit_var & (~mult & bit_var)[1:] > Node
add_node = bit_var & (~plus & bit_var)[1:] > Node
node = mul_node | add_node
parens = ~left_bracket & expr & ~right_bracket
group1 = parens | node
add = group1 & ~plus & group2 > Node
group2 += group1 | add
mul = group2 & ~mult & expr > Node
expr += group2 | mul
self.grammar = expr

This is pretty much what you get with pyparsing:
import pyparsing as pp
add_op = pp.oneOf("+ -")
mul_op = pp.oneOf("* /")
operand = pp.pyparsing_common.number | pp.pyparsing_common.identifier
arith = pp.infixNotation(operand,
[
("-", 1, pp.opAssoc.RIGHT),
(mul_op, 2, pp.opAssoc.LEFT),
(add_op, 2, pp.opAssoc.LEFT),
])
print(arith.parseString("1+2-3+X*-7*6+Y*(3+2)").asList())
prints
[[1, '+', 2, '-', 3, '+', ['X', '*', ['-', 7], '*', 6], '+', ['Y', '*', [3, '+', 2]]]]
If you just parse numbers, you can make the parser also do parse-time eval by adding parse actions to each level of precedence (pp.pyparsing_common.number auto-converts numeric strings to int or float):
operand = pp.pyparsing_common.number
op_fn = {
'*': lambda a,b: a*b,
'/': lambda a,b: a/b,
'+': lambda a,b: a+b,
'-': lambda a,b: a-b,
}.get
def binop(t):
t_iter = iter(t[0])
ret = next(t_iter)
for op, val in zip(t_iter, t_iter):
ret = op_fn(op)(ret, val)
return ret
arith = pp.infixNotation(operand,
[
("-", 1, pp.opAssoc.RIGHT, lambda t: -t[1]),
(mul_op, 2, pp.opAssoc.LEFT, binop),
(add_op, 2, pp.opAssoc.LEFT, binop),
])
print(arith.parseString("1+2-3+8*-7*6+4*(3+2)"))
Prints:
[-316]

Related

How to convert a list of binary to char?

I would like to convert a list of zeros and ones to a char.
example :
bitToChar([1,0,0,0,1,0,1]) = $Q
Thanks.
Another way to do it is to use a bit string comprehension:
X = [1,0,0,0,1,0,1],
<<C:7>> = << <<Bit:1>> || Bit <- lists:reverse(X) >>,
$Q == C.
That is, pick one element at a time from the list, and use each element as a bit in the binary being built, and finally extract a seven-bit number into the variable C.
You can add $0 to each of them (to make it a string with $0s and $1s), reverse the list, and use list_to_integer/2 with base 2:
1> list_to_integer(lists:reverse([N + $0 || N <- [1,0,0,0,1,0,1]]), 2) == $Q.
true
You can also use lists:foldl. The code is slightly longer but it doesn't use list_to_binary:
1> element(2, lists:foldl(fun(Digit, {Mul, Acc}) -> {Mul * 2, Acc + Digit * Mul} end, {1, 0}, Xs)) == $Q. true
This is basically equivalent to doing: 1 * 1 + 0 * 2 + 0 * 4 + 0 * 8 + 1 * 16 + 0 * 32 + 1 * 64.
$Q = lists:foldr(fun(X,Acc) -> X + (Acc bsl 1) end, 0,[1,0,0,0,1,0,1]).
Since $Q is integer value all you have to do is use in BitToChar conversion from binary based number to decimal based number.
Simplest conversion is:
to_decimal(X) ->
to_decimal(lists:reverse(X), 1, 0).
% you can validate that if H = 1 then add, if other not but I omitted this validation
to_decimal([H | T], Times, Acc) ->
to_decimal(T, 2 * Times, H * Times + Acc);
to_decimal([], _Times, Acc) -> Acc.
And then it will return integer.
In your case:
> $Q = 81.
81
> $Q == 81.
true

Creating a infix/postfix/prefix parser in SML Alice

So I am trying to create a parser program in SML that prompts the user for an expression. It then tells whether the expression entered is in postfix, prefix, or infix and then it displays the results. Here is an example of what i want it to do:
Enter Expression: "* + 2 3 4"
Postfix: 2 3 + 4 *
Prefix: * + 2 3 4
Infix: (2 + 3) * 4
*
\-- +
\-- 2
\-- 3
\-- 4
I am having trouble with creating the function so that it outputs results to the screen and i'm not really sure if i am even doing the method correctly. I'm not even focusing on outputting the tree until I figure out the conversion first.
fun infix_postfix(PostfixString,operatorStack,expList) =
if null expList then operatorStack
else
if(hd expList = #"^" orelse
hd expList = #"*" orelse
hd expList = #"/" orelse
hd expList = #"+" orelse
hd expList = #"-" = true)
then
hd expList:: operatorStack
else
infix_postfix(hd expList :: PostfixString, operatorStack, tl expList);
val x = "+12";
val expList = (explode x);
val PostfixString = [];
val operatorStack = [#"a"];
infix_postfix(PostfixString, operatorStack, expList);
I feel like I should put a recursive method in the second if statement(that checks for equality with the operators) but due to the limitations in Alice SML's syntax it doesn't let me. Any help would be appreciated, am I even heading in the right direction?
Here is the result in the console:
val infix_postfix : char list * char list * char list -> char list = _fn
val x : string = "+12"
val expList : char list = [#"+", #"1", #"2"]
val PostfixString : 'a list = []
val operatorStack : char list = [#"a"]
val it : char list = [#"+", #"a"]
FYI: I am doing this from the Alice Interpreter Environment
I see that you are indeed making some progress, I would suggest using a stack in your method

Creating 2d string indexed tables in Lua

I need to create a table like:
M = {"A"={"a1"=0, "a2"= 1}, "B"={"b1"=2,"b2"=3}}
but this is what I got: " '}' expected near '=' "
Is there anyway to do/simulate this?
foo.bar is the syntactic sugar of foo["bar"], there are no double quotes in the the former syntax:
M = {A = {a1 = 0, a2 = 1}, B = {b1 = 2, b2 =3 }}

how to compute the number of total constraints in smtlib2 files in api

I used the Z3_ast fs = Z3_parse_smtlib2_file(ctx,arg[1],0,0,0,0,0,0) to read file.
Additionally to add into the solver utilized the expr F = to_expr(ctx,fs) and then s.add(F).
My question is how can I get the number of total constraints in each instance?
I also tried the F.num_args(), however, it is giving wrong size in some instances.
Are there any ways to compute the total constraints?
Using Goal.size() may do what you want, after you add F to some goal. Here's a link to the Python API description, I'm sure you can find the equivalent in the C/C++ API: http://research.microsoft.com/en-us/um/redmond/projects/z3/z3.html#Goal-size
An expr F represents an abstract syntax tree, so F.num_args() returns the number of (one-step) children that F has, which is probably why what you've been trying doesn't always work. For example, suppose F = a + b, then F.num_args() = 2. But also, if F = a + b*c, then F.num_args() = 2 as well, where the children would be a and b*c (assuming usual order of operations). Thus, to compute the number of constraints (in case your definition is different than what Goal.size() yields), you can use a recursive method that traverses the tree.
I've included an example below highlighting all of these (z3py link here: http://rise4fun.com/Z3Py/It5E ).
For instance, my definition of constraint (or rather the complexity of an expression in some sense) might be the number of leaves or the depth of the expression. You can get as detailed as you want with this, e.g., counting different types of operands to fit whatever your definition of constraint might be, since it's not totally clear from your question. For instance, you might define a constraint as the number of equalities and/or inequalities appearing in an expression. This would probably need to be modified to work for formulas with quantifiers, arrays, or uninterpreted functions. Also note that Z3 may simplify things automatically (e.g., 1 - 1 gets simplified to 0 in the example below).
a, b, c = Reals('a b c')
F = a + b
print F.num_args() # 2
F = a + b * c
print F.num_args() # 2
print F.children() # [a,b*c]
g = Goal()
g.add(F == 0)
print g.size() # number of constraints = 1
g.add(Or(F == 0, F == 1, F == 2, F == 3))
print g.size() # number of constraints = 2
print g
g.add(And(F == 0, F == 1, F == 2, F == 3))
print g.size() # number of constraints = 6
print g
def count_constraints(c,d,f):
print 'depth: ' + str(d) + ' expr: ' + str(f)
if f.num_args() == 0:
return c + 1
else:
d += 1
for a in f.children():
c += count_constraints(0, d, a)
return c
exp = a + b * c + a + c * c
print count_constraints(0,0,exp)
exp = And(a == b, b == c, a == 0, c == 0, b == 1 - 1)
print count_constraints(0,0,exp)
q, r, s = Bools('q r s')
exp = And(q, r, s)
print count_constraints(0,0,exp)

LPeg grammar oddity

Part of a Lua application of mine is a search bar, and I'm trying to make it understand boolean expressions. I'm using LPeg, but the current grammar gives a strange result:
> re, yajl = require're', require'yajl'
> querypattern = re.compile[=[
QUERY <- ( EXPR / TERM )? S? !. -> {}
EXPR <- S? TERM ( (S OPERATOR)? S TERM )+ -> {}
TERM <- KEYWORD / ( "(" S? EXPR S? ")" ) -> {}
KEYWORD <- ( WORD {":"} )? ( WORD / STRING )
WORD <- {[A-Za-z][A-Za-z0-9]*}
OPERATOR <- {("AND" / "XOR" / "NOR" / "OR")}
STRING <- ('"' {[^"]*} '"' / "'" {[^']*} "'") -> {}
S <- %s+
]=]
> = yajl.to_string(lpeg.match(querypattern, "bar foo"))
"bar"
> = yajl.to_string(lpeg.match(querypattern, "name:bar AND foo"))
> = yajl.to_string(lpeg.match(querypattern, "name:bar AND foo"))
"name"
> = yajl.to_string(lpeg.match(querypattern, "name:'bar' AND foo"))
"name"
> = yajl.to_string(lpeg.match(querypattern, "bar AND (name:foo OR place:here)"))
"bar"
It only parses the first token, and I cannot figure out why it does this. As far as I know, a partial match is impossible because of the !. at the end of the starting non-terminal. How can I fix this?
The match is getting the entire string, but the captures are wrong. Note that
'->' has a higher precedence than concatenation, so you probably need parentheses around things like this:
EXPR <- S? ( TERM ( (S OPERATOR)? S TERM )+ ) -> {}

Resources