dlang-community / Pegged

A Parsing Expression Grammar (PEG) module, using the D programming language.
534 stars 66 forks source link

Action called twice with Memo.no, once with Memo.yes #108

Open callumenator opened 11 years ago

callumenator commented 11 years ago
enum g = `
Test:
    Rule <- (!A .)* A
    A <- 'A'{action}
`;

mixin(grammar!(Memoization.no)(g));

T action(T)(T t)
{
    if (t.successful)
        writeln("ACTION!");
    return t;
}

void main()
{
    Test("xxxA");
}

I think in this test action should only be called once, and with memoization on that is what happens. With memoization off, action is called twice. I'm not having much luck debugging it.

callumenator commented 11 years ago

Actually I think I get what is going on now, maybe I have it wrong way round. The memo'd version after trying the neg look-ahead at the end, already has a match that succeeded, so instead of running the A rule again it grabs it from the memo, so the action doesn't get run again.

So now i think both versions should call the action twice because of where it is placed. The memo would need to know about actions then. I'll wait to see what you think.

PhilippeSigaud commented 11 years ago

Ideally, ! (and maybe &) operators should 'gag' actions, disabling them. I think I see how to do that, with an internal NoAction!() operator that propagates towards the children until it finds an Action!() member.

Or else, I can just put in the docs that expressions used inside lookahead should not have side effects?

callumenator commented 11 years ago

Ideally, ! (and maybe &) operators should 'gag' actions, disabling them. I think I see how to do that, with an >internal NoAction!() operator that propagates towards the children until it finds an Action!() member.

Yeh I probably agree.

Or else, I can just put in the docs that expressions used inside lookahead should not have side effects?

If you have a rule on an action, you would then also need a no-action version of it. I think gagging the look-ahead's is better.

PhilippeSigaud commented 11 years ago

Or else, I can just put in the docs that expressions used inside lookahead should not have side effects?

If you have a rule on an action, you would then also need a no-action version of it. I think gagging the look-ahead's is better.

And I guess gagging could be made into a generic mechanism, useful for something else.

callumenator commented 11 years ago

And I guess gagging could be made into a generic mechanism, useful for something else.

Definitely, I have needed it before, and worked around it with two versions of the same rule.