© Copyright 2005 Peri Hankey - documentation license Gnu FDL - code license Gnu GPL - validate HTML
SourceForge.net Logo left-recursion and backtracking

Here is a small ruleset that recognises a list and prints it first forwards, and then backwards, putting commas between the elements of the list. The first element is required to be a word, and subsequent elements may be either word or number:

 .left()
 - error output        <- eof -;
 - sample output       <- eof -;
 - word :X             <- sample - list :X :X;
 list :B :F ';'        <- sample   'here it is forwards:  ' F '\n' 'here it is backwards: ' B '\n'eom; 
 list :B :F word   :X  <- sample - list:{ X ', ' B } :{ F ', ' X };
 list :B :F number :X  <- sample - list:{ X ', ' B } :{ F ', ' X };
 .left(20L)
 .[0-9] % { repeat .[0-9]       % } { option '.' % repeat [0-9] % } toNum :N <- number :N;
 .[a-zA-Z] % { repeat .[a-zA-Z] % } toSym :W                                 <- word   :W;
 .[ \n\t]                                                                    <- -        ;
 .left(30R)
 - anything            <- line -  ;
 eof                   <- line eof;
 '\n'                  <- line;
 - line                <- error '--- not understood - skipping one line\n' eom;
 - eom                 <- output ;
 - out                 <- eom -  ;

Here is the ruleset in action - it has been compiled to produce leftRecursion.gdc (the .gdc extension is used for examples where the same rules are being compiled to several different executable representations - it is a D language wrapping round the lmr load format)

 [peri@a4 examples]$ ./leftRecursion.gdc
 a 1 2 c;
 here it is forwards:  a, 1, 2, c
 here it is backwards: c, 2, 1, a

In the ruleset, the following rules are used to add words and numbers to the list:

 list :B :F word   :X  <- sample - list:{ X ', ' B } :{ F ', ' X };
 list :B :F number :X  <- sample - list:{ X ', ' B } :{ F ', ' X };

The second rule (as the newest) will be tried first. So when a word is used in the body of a list, these rules will always try to recognise list :B :F number :X before falling back on the alternative list :B :F word :X. It can be seen in the lm-diagram output below that this involves re-establishing two levels of right-nesting.

Fortunately the language machine is designed specifically to deal with this kind of situation in a reasonably efficient way. Where performance is important, it's best to avoid backtracks - for example:

 - word :X          <- item :X;
 - number :X        <- item :X;
 list :F :B item :X <- sample - list:{ X ', ' B } :{ F ', ' X };

home lm-diagram output

 [peri@a4 examples]$ ./leftRecursion.gdc -W 40 -t D
 a 1 2 c;
                                   eof 'a'
         ?                         eof 'a'
         .------------000001
         |                      sample 'a'
         |?                     sample 'a'
         |.-----------000002
         ||                       word 'a'
         ||?                      word 'a'
         ||.----------000003
         |||                         % ' '
         |||                    repeat ' '
         |||                  [a-zA-Z] ' '
         |||?                 [a-zA-Z] ' '
         |||-                 [a-zA-Z] ' '
         |||                     toSym ' '
         |||                         : ' '
         ||'----------000003---------- ----------000003-------------.
         ||                       word word                         |
         ||                          : :                            |
         |'-----------000002---------- ----------000002------------.|
         |                      sample list                        ||
         |?                     sample list                        ??
         |.-----------000005                                       ||
         ||                          : :                           ||
         ||                          : :                           ||
         ||                                      000002------------'|
         ||                                      000003-------------'
         ||                     number ' '
         ||?                    number ' '
         ||                     number '1'
         ||?                    number '1'
         ||.----------000007
         |||                         % ' '
         |||                    repeat ' '
         |||                     [0-9] ' '
         |||?                    [0-9] ' '
         |||-                    [0-9] ' '
         |||                    option ' '
         |||                       '.' ' '
         |||?                      '.' ' '
         |||-                      '.' ' '
         |||                     toNum ' '
         |||                         : ' '
         ||'----------000007---------- ----------000007-------------.
         ||                     number number                       |
         ||                          : :                            |
         |'-----------000005---------- ----------000005------------.|
         |                      sample list                        ||
         |?                     sample list                        ??
         |.-----------000010                                       ||
         ||                          : :                           ||
         ||                          : :                           ||
         ||                                      000005------------'|
         ||                                      000007-------------'
         ||                     number ' '
         ||?                    number ' '
         ||                     number '2'
         ||?                    number '2'
         ||.----------000012
         |||                         % ' '
         |||                    repeat ' '
         |||                     [0-9] ' '
         |||?                    [0-9] ' '
         |||-                    [0-9] ' '
         |||                    option ' '
         |||                       '.' ' '
         |||?                      '.' ' '
         |||-                      '.' ' '
         |||                     toNum ' '
         |||                         : ' '
         ||'----------000012---------- ----------000012-------------.
         ||                     number number                       |
         ||                          : :                            |
         |'-----------000010---------- ----------000010------------.|
         |                      sample list                        ||
         |?                     sample list                        ??
         |.-----------000015                                       ||
         ||                          : :                           ||
         ||                          : :                           ||
         ||                                      000010------------'|
         ||                                      000012-------------'
         ||                     number ' '
         ||?                    number ' '
         ||                     number 'c'
         ||?                    number 'c'
         ||-                    number 'c'
         ||                          : :                           ||
         ||                          : :                           ||
         ||                                      000010------------'|
         ||                                      000012-------------'
         ||                       word ' '
         ||?                      word ' '
         ||                       word 'c'
         ||?                      word 'c'
         ||.----------000018
         |||                         % ';'
         |||                    repeat ';'
         |||                  [a-zA-Z] ';'
         |||?                 [a-zA-Z] ';'
         |||-                 [a-zA-Z] ';'
         |||                     toSym ';'
         |||                         : ';'
         ||'----------000018---------- ----------000018-------------.
         ||                       word word                         |
         ||                          : :                            |
         |'-----------000015---------- ----------000015------------.|
         |                      sample list                        ||
         |?                     sample list                        ??
         |.-----------000019                                       ||
         ||                          : :                           ||
         ||                          : :                           ||
         ||                                      000015------------'|
         ||                                      000018-------------'
         ||                     number ';'
         ||?                    number ';'
         ||-                    number ';'
         ||                          : :                           ||
         ||                          : :                           ||
         ||                                      000015------------'|
         ||                                      000018-------------'
         ||                       word ';'
         ||?                      word ';'
         ||-                      word ';'
         ||                          : :                           ||
         ||                          : :                           ||
         ||                                      000015------------'|
         ||                                      000018-------------'
         ||                        ';' ';'
         |'-----------000019---------- ----------000019-------------.
         |                      sample sample                       |
         |                      output 'h'                          |
         |?                     output 'h'                          ?
         |.-----------000020                                        |
         ||                        eom 'h'                          |
         ||?                       eom 'h'                          ?
         ||.----------000021                                        |
         |||                       out 'h'                          |
 h       ||'----------000021                                        |
         ||                        eom 'e'                          |
         ||?                       eom 'e'                          ?
         ||.----------000022                                        |
         |||                       out 'e'                          |
 e       ||'----------000022                                        |
         ||                        eom 'r'                          |
         ||?                       eom 'r'                          ?
         ||.----------000023                                        |
         |||                       out 'r'                          |
 r       ||'----------000023                                        |
         ||                        eom 'e'                          |
         ||?                       eom 'e'                          ?
         ||.----------000024                                        |
         |||                       out 'e'                          |
 e       ||'----------000024                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000025                                        |
         |||                       out ' '                          |
         ||'----------000025                                        |
         ||                        eom 'i'                          |
         ||?                       eom 'i'                          ?
         ||.----------000026                                        |
         |||                       out 'i'                          |
 i       ||'----------000026                                        |
         ||                        eom 't'                          |
         ||?                       eom 't'                          ?
         ||.----------000027                                        |
         |||                       out 't'                          |
 t       ||'----------000027                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000028                                        |
         |||                       out ' '                          |
         ||'----------000028                                        |
         ||                        eom 'i'                          |
         ||?                       eom 'i'                          ?
         ||.----------000029                                        |
         |||                       out 'i'                          |
 i       ||'----------000029                                        |
         ||                        eom 's'                          |
         ||?                       eom 's'                          ?
         ||.----------000030                                        |
         |||                       out 's'                          |
 s       ||'----------000030                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000031                                        |
         |||                       out ' '                          |
         ||'----------000031                                        |
         ||                        eom 'f'                          |
         ||?                       eom 'f'                          ?
         ||.----------000032                                        |
         |||                       out 'f'                          |
 f       ||'----------000032                                        |
         ||                        eom 'o'                          |
         ||?                       eom 'o'                          ?
         ||.----------000033                                        |
         |||                       out 'o'                          |
 o       ||'----------000033                                        |
         ||                        eom 'r'                          |
         ||?                       eom 'r'                          ?
         ||.----------000034                                        |
         |||                       out 'r'                          |
 r       ||'----------000034                                        |
         ||                        eom 'w'                          |
         ||?                       eom 'w'                          ?
         ||.----------000035                                        |
         |||                       out 'w'                          |
 w       ||'----------000035                                        |
         ||                        eom 'a'                          |
         ||?                       eom 'a'                          ?
         ||.----------000036                                        |
         |||                       out 'a'                          |
 a       ||'----------000036                                        |
         ||                        eom 'r'                          |
         ||?                       eom 'r'                          ?
         ||.----------000037                                        |
         |||                       out 'r'                          |
 r       ||'----------000037                                        |
         ||                        eom 'd'                          |
         ||?                       eom 'd'                          ?
         ||.----------000038                                        |
         |||                       out 'd'                          |
 d       ||'----------000038                                        |
         ||                        eom 's'                          |
         ||?                       eom 's'                          ?
         ||.----------000039                                        |
         |||                       out 's'                          |
 s       ||'----------000039                                        |
         ||                        eom ':'                          |
         ||?                       eom ':'                          ?
         ||.----------000040                                        |
         |||                       out ':'                          |
 :       ||'----------000040                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000041                                        |
         |||                       out ' '                          |
         ||'----------000041                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000042                                        |
         |||                       out ' '                          |
         ||'----------000042                                        |
         ||                        eom a                            |
         ||?                       eom a                            ?
         ||.----------000043                                        |
         |||                       out a                            |
 a       ||'----------000043                                        |
         ||                        eom ','                          |
         ||?                       eom ','                          ?
         ||.----------000044                                        |
         |||                       out ','                          |
 ,       ||'----------000044                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000045                                        |
         |||                       out ' '                          |
         ||'----------000045                                        |
         ||                        eom 1                            |
         ||?                       eom 1                            ?
         ||.----------000046                                        |
         |||                       out 1                            |
 1       ||'----------000046                                        |
         ||                        eom ','                          |
         ||?                       eom ','                          ?
         ||.----------000047                                        |
         |||                       out ','                          |
 ,       ||'----------000047                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000048                                        |
         |||                       out ' '                          |
         ||'----------000048                                        |
         ||                        eom 2                            |
         ||?                       eom 2                            ?
         ||.----------000049                                        |
         |||                       out 2                            |
 2       ||'----------000049                                        |
         ||                        eom ','                          |
         ||?                       eom ','                          ?
         ||.----------000050                                        |
         |||                       out ','                          |
 ,       ||'----------000050                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000051                                        |
         |||                       out ' '                          |
         ||'----------000051                                        |
         ||                        eom c                            |
         ||?                       eom c                            ?
         ||.----------000052                                        |
         |||                       out c                            |
 c       ||'----------000052                                        |
         ||                        eom '\n'                         |
         ||?                       eom '\n'                         ?
         ||.----------000053                                        |
         |||                       out '\n'                         |
         ||'----------000053                                        |
         ||                        eom 'h'                          |
         ||?                       eom 'h'                          ?
         ||.----------000054                                        |
         |||                       out 'h'                          |
 h       ||'----------000054                                        |
         ||                        eom 'e'                          |
         ||?                       eom 'e'                          ?
         ||.----------000055                                        |
         |||                       out 'e'                          |
 e       ||'----------000055                                        |
         ||                        eom 'r'                          |
         ||?                       eom 'r'                          ?
         ||.----------000056                                        |
         |||                       out 'r'                          |
 r       ||'----------000056                                        |
         ||                        eom 'e'                          |
         ||?                       eom 'e'                          ?
         ||.----------000057                                        |
         |||                       out 'e'                          |
 e       ||'----------000057                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000058                                        |
         |||                       out ' '                          |
         ||'----------000058                                        |
         ||                        eom 'i'                          |
         ||?                       eom 'i'                          ?
         ||.----------000059                                        |
         |||                       out 'i'                          |
 i       ||'----------000059                                        |
         ||                        eom 't'                          |
         ||?                       eom 't'                          ?
         ||.----------000060                                        |
         |||                       out 't'                          |
 t       ||'----------000060                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000061                                        |
         |||                       out ' '                          |
         ||'----------000061                                        |
         ||                        eom 'i'                          |
         ||?                       eom 'i'                          ?
         ||.----------000062                                        |
         |||                       out 'i'                          |
 i       ||'----------000062                                        |
         ||                        eom 's'                          |
         ||?                       eom 's'                          ?
         ||.----------000063                                        |
         |||                       out 's'                          |
 s       ||'----------000063                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000064                                        |
         |||                       out ' '                          |
         ||'----------000064                                        |
         ||                        eom 'b'                          |
         ||?                       eom 'b'                          ?
         ||.----------000065                                        |
         |||                       out 'b'                          |
 b       ||'----------000065                                        |
         ||                        eom 'a'                          |
         ||?                       eom 'a'                          ?
         ||.----------000066                                        |
         |||                       out 'a'                          |
 a       ||'----------000066                                        |
         ||                        eom 'c'                          |
         ||?                       eom 'c'                          ?
         ||.----------000067                                        |
         |||                       out 'c'                          |
 c       ||'----------000067                                        |
         ||                        eom 'k'                          |
         ||?                       eom 'k'                          ?
         ||.----------000068                                        |
         |||                       out 'k'                          |
 k       ||'----------000068                                        |
         ||                        eom 'w'                          |
         ||?                       eom 'w'                          ?
         ||.----------000069                                        |
         |||                       out 'w'                          |
 w       ||'----------000069                                        |
         ||                        eom 'a'                          |
         ||?                       eom 'a'                          ?
         ||.----------000070                                        |
         |||                       out 'a'                          |
 a       ||'----------000070                                        |
         ||                        eom 'r'                          |
         ||?                       eom 'r'                          ?
         ||.----------000071                                        |
         |||                       out 'r'                          |
 r       ||'----------000071                                        |
         ||                        eom 'd'                          |
         ||?                       eom 'd'                          ?
         ||.----------000072                                        |
         |||                       out 'd'                          |
 d       ||'----------000072                                        |
         ||                        eom 's'                          |
         ||?                       eom 's'                          ?
         ||.----------000073                                        |
         |||                       out 's'                          |
 s       ||'----------000073                                        |
         ||                        eom ':'                          |
         ||?                       eom ':'                          ?
         ||.----------000074                                        |
         |||                       out ':'                          |
 :       ||'----------000074                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000075                                        |
         |||                       out ' '                          |
         ||'----------000075                                        |
         ||                        eom c                            |
         ||?                       eom c                            ?
         ||.----------000076                                        |
         |||                       out c                            |
 c       ||'----------000076                                        |
         ||                        eom ','                          |
         ||?                       eom ','                          ?
         ||.----------000077                                        |
         |||                       out ','                          |
 ,       ||'----------000077                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000078                                        |
         |||                       out ' '                          |
         ||'----------000078                                        |
         ||                        eom 2                            |
         ||?                       eom 2                            ?
         ||.----------000079                                        |
         |||                       out 2                            |
 2       ||'----------000079                                        |
         ||                        eom ','                          |
         ||?                       eom ','                          ?
         ||.----------000080                                        |
         |||                       out ','                          |
 ,       ||'----------000080                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000081                                        |
         |||                       out ' '                          |
         ||'----------000081                                        |
         ||                        eom 1                            |
         ||?                       eom 1                            ?
         ||.----------000082                                        |
         |||                       out 1                            |
 1       ||'----------000082                                        |
         ||                        eom ','                          |
         ||?                       eom ','                          ?
         ||.----------000083                                        |
         |||                       out ','                          |
 ,       ||'----------000083                                        |
         ||                        eom ' '                          |
         ||?                       eom ' '                          ?
         ||.----------000084                                        |
         |||                       out ' '                          |
         ||'----------000084                                        |
         ||                        eom a                            |
         ||?                       eom a                            ?
         ||.----------000085                                        |
         |||                       out a                            |
 a       ||'----------000085                                        |
         ||                        eom '\n'                         |
         ||?                       eom '\n'                         ?
         ||.----------000086                                        |
         |||                       out '\n'                         |
         ||'----------000086                                        |
         ||                        eom eom                          |
         |'-----------000020---------- ----------000020------------.|
         |                      output output                      ||
         '------------000001                                       ||
                                                 000020------------'|
                                                 000019-------------'
                                   eof '\n'
         ?                         eof '\n'
                                   eof eof
 [peri@a4 examples]$
home