<div dir="ltr"><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div>I have a ragel machine that generates passing Go code when built with -G1, but failing code when built with -G2 (using ragel 6.10 on ubuntu).</div><div><br></div><div>Given the following machine definition:</div><div><br></div><div>-------------------------------------------------------------------------</div><div>package safe16l<br><br>import (<br>    "fmt"<br>)<br><br>%%{<br>    machine safe16;<br>    access this.;<br><br>    numeric_hi = [0-9] @{<br>        accumulator = (fc - '0') << 4<br>    };<br>    af_hi = [a-f] @{<br>        accumulator = (fc - 'a' + 10) << 4<br>    };<br>    AF_hi = [A-F] @{<br>        accumulator = (fc - 'A' + 10) << 4<br>    };<br>    numeric_lo = [0-9] @{<br>        accumulator |= fc - '0'<br>    };<br>    af_lo = [a-f] @{<br>        accumulator |= fc - 'a' + 10<br>    };<br>    AF_lo = [A-F] @{<br>        accumulator |= fc - 'A' + 10<br>    };<br><br>    sequence = space* (numeric_hi | af_hi | AF_hi) space* (numeric_lo | af_lo | AF_lo) %{<br>        dst[dstIndex] = accumulator<br>        dstIndex++<br>    };<br><br><br>    length_nocontinue = [0-7] @{<br>        this.length = this.length << 3 + int(fc - '0')<br>    };<br>    length_numeric = [8-9] @{<br>        this.length = this.length << 3 + int(fc - '0')<br>    };<br>    length_af = [a-f] @{<br>        this.length = this.length << 3 + int(fc - 'a' + 10 - 8)<br>    };<br>    length_AF = [A-F] @{<br>        this.length = this.length << 3 + int(fc - 'A' + 10 - 8)<br>    };<br><br>    length = (length_numeric | length_af | length_AF)* length_nocontinue;<br><br>    sequence_counted = sequence %{<br>        fmt.Printf("### End of sequence\n")<br>        this.length--<br>        if this.length == 0 {<br>            this.isComplete = true<br>            fbreak;<br>        }<br>    };<br><br>    main := length sequence_counted* @/{<br>        err = fmt.Errorf("Incomplete document")<br>    };<br>}%%<br><br><br>%% write data;<br><br>type Parser struct {<br>    cs int // Current Ragel state<br>    data []byte<br>    length int<br>    isComplete bool<br>}<br><br>func (this *Parser) Init() {<br>}<br><br>func NewParser() *Parser {<br>    this := new(Parser)<br>    return this<br>}<br><br>func (this *Parser) Parse(src []byte, dst []byte) (bytesWritten int, isComplete bool, err error) {<br>    this.data = src<br>    p := 0 // Position: current<br>    pe := len(this.data) // Position: end of buffer<br>    // TODO: Change to -1 and check for end of file<br>    eof := pe // Position: end of file<br>    accumulator := byte(0)<br>    dstIndex := 0<br><br>    _ = eof<br>    <br>    %%{<br>        write init;<br>        write exec;<br>    }%%<br><br>    if this.cs == safe16_error {<br>        err = fmt.Errorf("Parse error at %v", p)<br>    }<br><br>    return dstIndex, this.isComplete, err<br>}<br></div><div><div>-------------------------------------------------------------------------</div><div></div></div><div><br></div><div>And the following test code:</div><div><br></div><div>-------------------------------------------------------------------------</div><div></div><div>package safe16l<br><br>import (<br>    "bytes"<br>    "testing"<br>)<br><br>func testSafe16L(t *testing.T, src string, expected []byte) {<br>    dst := make([]byte, len(src))<br>    parser := NewParser()<br><br>    bytesWritten, isComplete, err := parser.Parse([]byte(src), dst)<br>    if err != nil {<br>        t.Error(err)<br>    }<br>    if !isComplete {<br>        t.Errorf("Sequence [%v]: Incomplete parse", src)<br>    }<br><br>    actual := dst[:bytesWritten]<br>    if !bytes.Equal(actual, expected) {<br>        t.Errorf("Sequence [%v]: Expected %v but got %v", src, expected, actual)<br>    }<br>}<br><br>func TestSafe16L(t *testing.T) {<br>    testSafe16L(t, "100", []byte{0x00})<br>}<br></div><div><div>-------------------------------------------------------------------------</div><div></div></div><div><br></div><div>With G1:</div><div><br></div><div>$ ragel -Z -G1 safe16l.rl && go test<br>### End of sequence<br>PASS<br>ok          <a href="http://github.com/kstenerud/go-safe16">github.com/kstenerud/go-safe16</a>        0.001s<br></div><div><br></div><div>With G2:</div><div><br></div><div>$ ragel -Z -G2 safe16l.rl && go test<br>### End of sequence<br>--- FAIL: TestSafe16L (0.00s)<br>    parser_test.go:14: Parse error at 4<br>FAIL<br>exit status 1<br>FAIL  <a href="http://github.com/kstenerud/go-safe16">github.com/kstenerud/go-safe16</a>        0.001s<br></div><div><br></div><div><div><div>-------------------------------------------------------------------------</div><div><br></div><div>Looking at the generated code, I see this in the -G2 version:</div><div><br></div><div>//line safe16l.rl:51<br><br>        fmt.Printf("### End of sequence\n")<br>        this.length--<br>        if this.length == 0 {<br>            this.isComplete = true<br>            {p++;  this.cs = 0; goto _out }<br>        }</div><div><br></div><div>I'm not sure why cs would be set to 0 here. This isn't an error state as far as I can tell...</div><div><br></div><div><br></div><div>Cheers,</div><div>Karl</div><div><br></div><div></div></div><div></div></div></div></div></div>