<div dir="ltr"><div>The problem is that a finite state machine, having read the "3", cannot know if the parser is "done" or not - only that it in a certain state. You have a couple of options that I know:</div><div><br></div><div>* Add some "end-of-string" sentinel value (like a null terminator)</div><div>* Use first_final instead of state transition actions</div><div>* Use EOF actions</div><div><br></div><div>For the 'first_final' method, you would essentially do something like what is described in the ragel guide:</div><div><br></div><div>parser_parse(&parser, str, strlen(str));</div><div>if ( parser.cs < %%{ write first_final; }%% ) {</div><div>  printf("parsing failed\n");</div><div>}</div><div><br></div><div>The downside with this is that partial reads are no longer supported, e.g. when</div><div>* reading larger data sets, like reading network logs from a file</div><div>* reading data over a network or some serial communication</div><div><br></div><div>a normal loop over these might look like</div><div><br></div><div>char buf[BUFLEN];</div><div>bytes_read = read(fd, &buf, BUFLEN); </div><div>while (bytes_read > 0) {</div><div>  parser_parse(&parser, buf, bytes_read);</div><div>  bytes_read = read(fd, &buf, BUFLEN);</div><div>}</div><div><br></div><div>and a certain read might have read exactly 3 characters, "123", but you don't know if the next read will get you "456789" or EOF - but "cs" is in a final state.</div><div><br></div><div>In the first method, you would define a parser like</div><div><br></div><div>foo = ('123' 0) | ('12345' 0)</div><div><br></div><div>then the finishing state action would occur on the null terminator. You would call your parser like</div><div><br></div><div>parser_parse(&parser, str, strlen(str)+1);</div><div><br></div><div>or, while over a network, you could do</div><div><br></div><div>char buf[BUFLEN];</div><div>bytes_read = read(fd, &buf, BUFLEN);</div><div>while (bytes_read > 0) {</div><div>  parser_parse(&parser, buf, bytes_read);</div><div>  bytes_read = read(fd, &buf, BUFLEN):</div><div>}</div><div>if (0 == bytes_read) {</div><div>  // read EOF</div><div>  parser_parse(&parser, (char[]){0}, 1);</div><div>}</div><div><br></div><div>the downside is that adding null terminators to the parser reduces the extensibility of the parser; it's harder to add the parser as a "sub parser" of another parser.</div><div><br></div><div>EOF actions are run when 'p == pe == eof'. These are essentially the same as adding a null terminator to the parser since you need to know in advance that you've hit the EOF - but you move the action from a final state transition to an EOF action. I've not really used eof actions that much because I find them slightly wierd to use, but someone can fill in on the details.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Feb 29, 2020 at 1:05 AM Iñaki Baz Castillo <<a href="mailto:ibc@aliax.net">ibc@aliax.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
After many years using my Ragel based IPv6 parser, I've found a bug. I<br>
think I've also understood the problem and simplified the code as much<br>
as possible.<br>
<br>
Let's assume this simple grammar:<br>
<br>
--------------------<br>
foo = "12345" | "123";<br>
-------------------<br>
<br>
The parser.rl has a function that receives a char* data pointer and a<br>
size_t len. It includes the Ragel %% lines as usual. At the end of the<br>
function it checks:<br>
<br>
--------------------<br>
// Ensure that the parsing has consumed all the given length.<br>
if (len == p - data)<br>
  return true;<br>
else<br>
  return false;<br>
--------------------<br>
<br>
The problem is that, when the input is "1234", the parser returns true.<br>
<br>
I think I understand the problem:<br>
<br>
- The parser first matches "123" which is valid.<br>
- It continues and matches "1234".<br>
- At this time it has consumed 4 chars.<br>
- It exits now because there is no more chars in the input.<br>
- However it did match "123" so the Ragel action was executed.<br>
<br>
May I know how to avoid this problem and make the parser function<br>
return false in this case?<br>
<br>
Thanks a lot.<br>
<br>
<br>
<br>
-- <br>
Iñaki Baz Castillo<br>
<<a href="mailto:ibc@aliax.net" target="_blank">ibc@aliax.net</a>><br>
<br>
_______________________________________________<br>
ragel-users mailing list<br>
<a href="mailto:ragel-users@colm.net" target="_blank">ragel-users@colm.net</a><br>
<a href="http://www.colm.net/cgi-bin/mailman/listinfo/ragel-users" rel="noreferrer" target="_blank">http://www.colm.net/cgi-bin/mailman/listinfo/ragel-users</a><br>
</blockquote></div></div>