Closed vike2000 closed 1 year ago
the effective php code that crashes, and though the whole ruleset/machine is probably highly incomplete, I can't say I see a clear reason for it to crash...
<?php
$c='\\t';
$p=new \Parle\RParser;
$p -> token('ESCAPE');
$p -> token('ESCAPED');
$p -> push('start','ESCAPE');
$p -> build();
$l=new \Parle\RLexer;
$l -> pushState('stt_esc');
$l -> push('INITIAL','\\\\',1,'stt_esc');
$l -> push('stt_esc','.',1,'<');
$l -> build();
$p -> consume($c,$l);
$p -> advance();?>
I don't understand much of the c++ code, but looking through the crashing stack in vscode, it looks like most is in the parsertl/lexertl libs, so maybe this could be seen as an upstream issue (@BenHanson)...
the effective php code that crashes, and though the whole ruleset/machine is probably highly incomplete, I can't say I see a clear reason for it to crash...
<?php $c='\\t'; $p=new \Parle\RParser; $p -> token('ESCAPE'); $p -> token('ESCAPED'); $p -> push('start','ESCAPE'); $p -> build(); $l=new \Parle\RLexer; $l -> pushState('stt_esc'); $l -> push('INITIAL','\\\\',1,'stt_esc'); $l -> push('stt_esc','.',1,'<'); $l -> build(); $p -> consume($c,$l); $p -> advance();?>
I don't understand much of the c++ code, but looking through the crashing stack in vscode, it looks like most is in the parsertl/lexertl libs, so maybe this could be seen as an upstream issue (@BenHanson)...
Hello, I am the author of lexertl and parsertl.
The problem is that you are doing a 'goto' state ('stt_esc') and then trying to pop from an empty stack with '<'.
If you do:
$l -> push('stt_esc','.',$p -> tokenId('ESCAPED'),'INITIAL');
instead then things will work as expected.
If you want to stack your states then you would do:
$l -> push('INITIAL',"\\\\",$p -> tokenId("'\\'"),'>stt_esc');
See "Recursive Rules" under http://benhanson.net/lexertl.html
Thank you very much @BenHanson for helping me get the states right. I have them working in a jison program that I now want to port to parle. I have written another program using parle (and looking as much as possible at your documentation) but ended up not using states as I never got them right.
My real issue, as I will now try to make more clear in the OP, is yet that I would like to have an explanatory exception thrown instead of just a crash, in the case I thanks to you now know is
trying to pop from an empty stack
Saying it now I realize that the parle side has to catch that c++ exception and transform it into a php exception any way, so you can't solve my issue with parle in lexertl alone, unless parle has some kind of general exception handling already prepared, hmm... Even if parle would catch an exception raised in lexertl, perhaps parle would be better to throw a PHP exception at some adequate point before calling lexertl in this case. You (and any possible contributors) of course do with exceptions as you see fit in lexertl.
While I realize I shouldn've pinged you for my main issue here I again thank you for helping me getting my states right.
For completeness. An example of a full working example, albeit small:
$c='\\t';
$p=new \Parle\RParser;
$p -> token('ESCAPE');
$p -> token('ESCAPED');
$p -> push('start',"ESCAPE ESCAPED");
$p -> build();
$l=new \Parle\RLexer;
$l -> pushState('stt_esc');
$l -> push('INITIAL','\\\\',$p -> tokenId('ESCAPE'),'>'.'stt_esc');
$l -> push('stt_esc','.',$p -> tokenId('ESCAPED'),'<');
$l -> build();
$p -> consume($c,$l);
echo var_export((\Parle\RParser::ACTION_SHIFT==$p -> action),true).PHP_EOL;
$p -> advance();
echo var_export((\Parle\RParser::ACTION_SHIFT==$p -> action),true).PHP_EOL;
$p -> advance();
echo var_export((\Parle\RParser::ACTION_REDUCE==$p -> action),true).PHP_EOL;
echo var_export(($p -> sigil(0)),true).PHP_EOL;
echo var_export(($p -> sigil(1)),true).PHP_EOL;
Outputs:
true
true
true
'\\'
't'
My bad usage and its crash is reintroduced by removing the '>'.
Thanks for the feedback, glad I could help.
Yes, crashing on an empty stack is pretty brutal. Just FYI, crashing dereferencing invalid iterators is acceptable in C++(!)
I have updated the C++ library to throw when attempting to pop from an empty stack. Anatol has added me as a collaborator so I have pushed that change to the repo. It appears that the code already does a php_parle_rethrow_from_cpp
if parsertl::lookup()
fails, so it should already work as you requested.
If you've got any other queries, I'm happy to answer them.
Addendum edit:
I would like to get a php exception thrown instead of a crash.
Talking with BenHanson below it looks like the crash happens because I am
Original post (sort of):
I am running it locally (w/ major scripting in php and bash(1), via vscode (step-debug - both php/xdebug and c++/lldb - setup in
.vscode
but using external personal toolchain) or just bash in iterm from where the following crash comes - via macOS.It crashes in
std::__1::stack
and "my" call after entry (from php) beingparsertl::lookup(par.sm, lex.iter, par.results, par.productions)
ofparle.cpp
afaics: