I am trying to look at this, but am having some "issues" with running any
Python code at all, so it may be some time before I can get back.
FWIW it seems like you are right and that exmple is wrong. What I would like
to do is extend the approach at
http://code.google.com/p/lepl/source/browse/src/lepl/_example/expression.py
which uses repeptition rather than recursion. I thnk that could give a clean
solution, with some work (eg using "sum(...)")
Sorry I can't be more help right now - will try and be more useful in the new
day or two.
Andrew
> --
> You received this message because you are subscribed to the Google Groups "lepl" group.
> To post to this group, send email to le...@googlegroups.com.
> To unsubscribe from this group, send email to lepl+uns...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/lepl?hl=en.
>
cheers,
andrew
just muddled through to find this during lunch. posting now in case you are
waiting, will explain tonight. hopefully it's fairly self-explanatory. the
idea is to have sums and products, where sums can contain positive and
negative values, and products can contain values and their inverses. i
haven't implemented the node operations to evaluate, but they have obvious
(and reasonably efficient) solutions (i hope!):
def test_repeat3(self):
'''
Fix the problem above by folding - and / into the value itself.
'''
basicConfig(level=DEBUG)
class Op(List): pass
class Sum(Op): pass
class Neg(Op): pass
class Prd(Op): pass
class Inv(Op): pass
with TraceVariables():
value = Token(UnsignedReal())
symbol = Token('[^0-9a-zA-Z \t\r\n]')
number = Optional(symbol('-')) + value >> float
sum = Delayed()
parens = ~symbol('(') & sum & ~symbol(')')
val = parens | number
inv = ~symbol('/') & val > Inv
eve = ~symbol('*') & val
prd = val & (inv | eve)[0:] > Prd
neg = ~symbol('-') & prd > Neg
pos = ~symbol('+') & prd
sum += prd & (neg | pos)[0:] > Sum
line = sum & Eos()
self.examples([
(lambda: line.parse('4-3-2')[0],
"""Sum
+- Prd
| `- 4.0
+- Neg
| `- 3.0
`- Neg
`- 2.0"""),
(lambda: line.parse('1+2-3-4+5+6+7-8-9-10-11')[0],
"""Sum
+- Prd
| `- 1.0
+- 2.0
+- Neg
| `- 3.0
+- Neg
| `- 4.0
+- 5.0
+- 6.0
+- 7.0
+- Neg
| `- 8.0
+- Neg
| `- 9.0
+- Neg
| `- 10.0
`- Neg
`- 11.0"""),
(lambda: line.parse('1+2*(3-4)+5/6+7')[0],
"""Sum
+- Prd
| `- 1.0
+- Prd
| +- 2.0
| `- Sum
| +- Prd
| | `- 3.0
| `- Neg
| `- Prd
| `- 4.0
+- Prd
| +- 5.0
| `- Inv
| `- 6.0
`- Prd
`- 7.0""")])
On Tue, Jun 21, 2011 at 09:54:09PM -0400, Andrew Stromme wrote:
i don't think (but haven't proved) that the natural pair grouping you want is
possible (my argument is that the form implies left-recursion, which
contradicts what you are trying to do). so i had two alternatives: either
rewrite the result tree to re-arrange nodes, or make nested pairs "flat".
since i already had code that parsed to give "flat" trees, that's what i went
with. it took a few attempts (which you can see in the link above) before i
understood what to do - to easily make the flat nodes you need to create a
list in a single "line" of the parser, which means matching just one "kind of
thing". that led to the idea of summing numbers that might be negative, and
the same for products.
hope that all makes sense. i'll update the manual for the next release (which
i am working on, but which is still a long way off).
cheers,
andrew
1 < x < 2
which might in some crazy example be
1 < x > 3
if so, then those aren't binary operators. there some freaky mess. and what
i would do is slurp them up as a sequence of symbols and then try and make
sense of them elsewhere.
so something like:
expression[2:,Or(">","<")] > FreakyMess
where expression matches some sub-expression like "x" or "1".
andrew
andrew
i think you're confused about how this works.
> and < are not (always) binary operators.
1 < 2 < 3 is true because AS A WHOLE the sequence is true.
1 < (2 < 3) is false because it is equivalent to 1 < True and in such
comparisons True is taken as 1.
so the two above are not equivalent. because 1 < 2 < 3 is not formed from
binary operations. it's a freaky mess. you cannot decompose 1 < 2 < 3 into
two binary operators.
andrew
1 < 2 < 2 is 2 between 1 and 2 (not inclusive)? no!
(1 < 2) < 2 is True less than 2? True is 1. so yes!
1 < (2 < 2) is 1 less than False? False is 0. so no!
see how the first is NOT the same as either of the other two? i imagine that
internally the first is reduced to something like:
(1 < 2) and (2 < 2)
while the other two examples are parsed more or less like you'd expect.
for c++ i really have no idea, but i would guess it's more consistent /
logical - probably left to right with 0 and 1 as truth values.
1 < 2 < 2 == 1 < 2 == 1
(1 < 2) < 2 == 1 < 2 == 1
(1 < (2 < 2)) == 1 < 0 == 0
so c++ works like you were thinking python worked.
if you're asking me how i'd parse c++ so that the grouping worked i think i'd
probably do the following:
term[2:,Or(">", "<")] > secondary_function
where secondary_function is a hand-written function that does what you want.
i don't see a good way at the moment to do it purely in lepl (which is
annoying, but part of the reason lepl is in python is so that you can do
exactly that - you can use python itself to extend it however you want).
andrew