On Mon, 7 Nov 2016 18:14:22 +1100, Jack Andrews <[email protected]>
wrote:
> I'm new to PEGs (but I've been parsing for a while)
Welcome!
> and I don't
> understand why this..
>
> E->XYE|ZE|
>
> ...doesn't parse "1+1-2" the way I expect (it fails):
>
> i've tried using PackCC and I now in leg (it's more likely you know
> leg than pcc)
I can't comment on PackCC, but the problem with your leg grammar is
that you've defined YY_INPUT incorrectly. It needs to set r to the
result. Also, the macro outputs the next character, instead of the
current one. Finally, your start rule attempts to match '\n',
which is presumably a leftover from an earlier version.
Here's a patch that fixes all 3 problems, and results in success.
--- a/g.peg
+++ b/g.peg
@@ -1,9 +1,9 @@
#leg g.peg -o g.c && cc g.c -o g && ./g
%{
char*in="1+1-2";
-#define YY_INPUT(b,r,m) *in?*(b)=*in++,putchar(*in),1:0
+#define YY_INPUT(b,r,m) r=*in?*(b)=*in++,putchar(*b),1:0;
%}
-S=E '\n';
+S=E !.;
E=x:X y:Y z:E {printf("%c%c%c\n",x,y,z);$$='E';}
|x:Z y:E {printf("%c%c\n",x,y);$$='E';}
|'' {printf("''");$$='E';}
You might also be interested in pacc_, which was inspired by peg/leg,
but has the advantage of writing a packrat parser, not a recursive
descent one. I tend to think it has nicer syntax too, but as pacc's
author I would say that, wouldn't I? :)
.. _pacc: https://paccrat.org/
To help you judge for yourself, here's your grammar converted to pacc:
# pacc g.pacc && gcc -o g g.c && ./g
{
int pacc_wrap(const char *, char *, size_t, int *);
int main(void) {
char *in = "1+1-2";
int result;
if (pacc_wrap("arg", in, strlen(in), &result))
printf("parsed with value %d\n", result);
}
}
Expr = d:Digit o:Op e:Expr { printf("%c%c%c\n", d, o, e), 'E' }
| b:Both e:Expr { printf("%c%c\n", b, e), 'E' }
| { printf("''"), 'E' }
Both = Digit | Op
Digit = [0-9] { ref_0(ref()) }
Op = [+-] { ref_0(ref()) }
Regards,
Toby.
_______________________________________________
PEG mailing list
[email protected]
https://lists.csail.mit.edu/mailman/listinfo/peg