Handle direct left recusion

db4
Chris Double 2008-03-29 01:17:54 +13:00
parent 010ce80076
commit 68cbdf76aa
1 changed files with 35 additions and 4 deletions

View File

@ -24,6 +24,9 @@ SYMBOL: fail
TUPLE: memo-entry ans pos ; TUPLE: memo-entry ans pos ;
C: <memo-entry> memo-entry C: <memo-entry> memo-entry
TUPLE: left-recursion detected? ;
C: <left-recursion> left-recursion
: rule-parser ( rule -- parser ) : rule-parser ( rule -- parser )
#! A rule is the parser compiled down to a word. It has #! A rule is the parser compiled down to a word. It has
#! a "peg" property containing the original parser. #! a "peg" property containing the original parser.
@ -48,7 +51,9 @@ C: <memo-entry> memo-entry
#! Return fail if the rule failed. The rule has #! Return fail if the rule failed. The rule has
#! stack effect ( input -- parse-result ) #! stack effect ( input -- parse-result )
pos get swap pos get swap
execute [ execute
! drop f f <parse-result>
[
nip nip
[ ast>> ] [ remaining>> ] bi [ ast>> ] [ remaining>> ] bi
input-from pos set input-from pos set
@ -65,18 +70,44 @@ C: <memo-entry> memo-entry
#! Store an entry in the cache #! Store an entry in the cache
rule-parser input-cache set-at ; rule-parser input-cache set-at ;
:: (grow-lr) ( r p m h -- )
p pos set
r eval-rule
dup fail = pos get m pos>> <= or [
drop
] [
m (>>ans)
pos get m (>>pos)
r p m h (grow-lr)
] if ;
:: grow-lr ( r p m h -- ast )
#! Placeholder for full left recursion implementation
r p m h (grow-lr) m pos>> pos set m ans>>
;
:: apply-non-memo-rule ( r p -- ast ) :: apply-non-memo-rule ( r p -- ast )
[let* | [let* |
m [ fail p <memo-entry> dup p r set-memo ] lr [ f <left-recursion> ]
m [ lr p <memo-entry> dup p r set-memo ]
ans [ r eval-rule ] ans [ r eval-rule ]
| |
ans m (>>ans) ans m (>>ans)
pos get m (>>pos) pos get m (>>pos)
lr detected?>> ans fail = not and [
r p m f grow-lr
] [
ans ans
] if
] ; ] ;
: apply-memo-rule ( m -- ast ) : apply-memo-rule ( m -- ast )
[ ans>> ] [ pos>> ] bi pos set ; [ ans>> ] [ pos>> ] bi
pos set
dup left-recursion? [
t swap (>>detected?)
fail
] when ;
:: apply-rule ( r p -- ast ) :: apply-rule ( r p -- ast )
[let* | [let* |