April 19, 2020
I 've started experimenting Pegged action. Quickly i got blocked by this problem. The start action works where I use the rule but not directly in the rule. Test program:

gdb_commander.d:
---
/+dub.sdl:
dependency "pegged" version="~>0.4.4"
versions "dub_run"
+/
module gdb_commander;

import core.stdc.string, std.json;
import pegged.grammar, pegged.peg;

enum gdbMiOutput = `GdbmiOutput:

    Output          < OutOfBandRecord* ResultRecord? '(gdb)' #HERE before ResRec OK
    ResultRecord    < {beginResultRecord} Token? '^' ResultClass (',' Result)* {endResultRecord}
    OutOfBandRecord < AsyncRecord
                    / StreamRecord
    AsyncRecord     < ExecAsyncOutput
                    / StatusAsyncOutput
                    / NotifyAsyncOutput
    ExecAsyncOutput < Token? '*' AsyncOutput
    StatusAsyncOutput   < Token? '+' AsyncOutput
    NotifyAsyncOutput   < Token? '=' AsyncOutput
    AsyncOutput     < AsyncClass ( ',' Result )*
    ResultClass     < 'done'
                    / 'running'
                    / 'connected'
                    / 'error'
                    / 'exit'
    AsyncClass      < 'stopped'
    Result          < Variable '=' Value
    Variable        < String
    Value           < Const / Object / List
    Const           < CString
    Object          < '{}'
                    / '{' Result ( ',' Result )* '}'
    List            < '[]'
                    / '[' Value ( ',' Value )* ']'
                    / '[' Result ( ',' Result )* ']'
    StreamRecord    < ConsoleStreamOutput
                    / TargetStreamOutput
                    / LogStreamOutput
    ConsoleStreamOutput < '~' CString
    TargetStreamOutput  < '@' CString
    LogStreamOutput     < '&' CString
    Token           <~ [a-zA-Z_][a-zA-Z0-9_]*
    CString         <~ "\"" (EscapedQuotes / (!"\"" .) )* :"\""
    EscapedQuotes   <~ backslash doublequote
    String          <~ [a-zA-Z0-9_\-]*`;

T beginResultRecord(T)(T t)
{
    import std.stdio;
    writeln(__PRETTY_FUNCTION__);
    return t;
}

T endResultRecord(T)(T t)
{
    import std.stdio;
    writeln(t);
    return t;
}

mixin(grammar(gdbMiOutput));

version(dub_run)
{
    import std.stdio, std.path, std.file, std.process;
    import pegged.tohtml;

    enum testString01 = `^done,path="/usr/bin"
    (gdb)`;
    enum testString02 = `^done,threads=[
    {id="2",target-id="Thread 0xb7e14b90 (LWP 21257)",
    frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",
    args=[]},state="running"},
    {id="1",target-id="Thread 0xb7e156b0 (LWP 21254)",
    frame={level="0",addr="0x0804891f",func="foo",
    args=[{name="i",value="10"}],
    file="/tmp/a.c",fullname="/tmp/a.c",line="158",arch="i386:x86_64"},
    state="running"}],
    current-thread-id="1"
    (gdb)`;
    enum testString03 = `^done,new-thread-id="3",
    frame={level="0",func="vprintf",
    args=[{name="format",value="0x8048e9c \"%*s%c %d %c\\n\""},
    {name="arg",value="0x2"}],file="vprintf.c",line="31",arch="i386:x86_64"}
    (gdb)`;

    void exportHTMLandBrowse(T)(auto ref T tree, string name)
    {
        string fname = __FILE_FULL_PATH__.dirName ~ "/" ~ name ~ ".html";
        if (fname.exists)
            remove(fname);
        toHTML(tree, fname);
        browse(fname);
    }

    void main()
    {
        GdbmiOutput(testString01).exportHTMLandBrowse("t1");
        GdbmiOutput(testString02).exportHTMLandBrowse("t2");
        GdbmiOutput(testString03).exportHTMLandBrowse("t3");
    }
}
---

---
$ dub gdb_commander.d
---

Also I'd like to report that actions dont work with partially specialized templates:

---
T handleResultRecord(bool end,  T)(T t);
// then you use handleResultRecord!true and handleResultRecord!false in the PEG.
---
June 11, 2020
On Sunday, 19 April 2020 at 16:47:06 UTC, Basile B. wrote:
> I 've started experimenting Pegged action. Quickly i got blocked by this problem. The start action works where I use the rule but not directly in the rule.

I don't understand the difference between how you use "where" and "directly in".

Note that semantic actions are executed during the parsing process, even in branches that eventually fail, before the parser back tracks. They are not a substitute for traversing the final parse tree, rather, they are a method for manipulating the parsing process as it happens.

That's why `endResultRecord` is executed directly after `(',' Result)*` succeeds, and `beginResultRecord` is executed directly after `ResultRecord` succeeds (even if `'(gdb)'` would not match).

> Test program:
[...]
>     ResultRecord    < {beginResultRecord} Token? '^' ResultClass (',' Result)* {endResultRecord}

Remove the space between "<" and "{", then it works.

> Also I'd like to report that actions dont work with partially specialized templates:
>
> ---
> T handleResultRecord(bool end,  T)(T t);
> // then you use handleResultRecord!true and handleResultRecord!false in the PEG.
> ---

That fails for the same reason as `handleResultRecord!true(1)` fails to instantiate.

-- Bastiaan.