diff options
Diffstat (limited to 'test/counting1.lm')
-rw-r--r-- | test/counting1.lm | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/test/counting1.lm b/test/counting1.lm new file mode 100644 index 0000000..83e70d5 --- /dev/null +++ b/test/counting1.lm @@ -0,0 +1,109 @@ +##### LM ##### +context counting + + # + # Regular Definitions + # + rl rl_ws /[ \t\n\r\v]+/ + rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/ + rl rl_num /[0-9]+/ + + # + # Tokens + # + + lex + # Ignore whitespace. + ignore /rl_ws/ + + # Tokens. + token id /rl_id/ + token number /rl_num/ + end + + # + # Global Data + # + + target: int + + # + # Productions + # + + + def get_target + [number] + { + match lhs [Number:number] + target = Number.data.atoi() + } + + # Arbitrary item. + def item + [number] + | [id] + + # Type definition for the count_items nonterminal. + def count_items + count: int + + # List production one. The condition stops the + # greedy list when it has gone too far. + [count_items item] + { + # Pass up the data + lhs.count = r1.count + 1 + if lhs.count > target { + reject + } + } + + # List production two, the base. + | [] + { + lhs.count = 0 + } + + # Wrapper which prevents short lists from getting through if the parser + # encounters an error and needs to backtrack over counted list. + def counted_list + [get_target count_items] + { + if r2.count < target { + reject + } + } + + def start + [counted_list*] + { + for List:counted_list in lhs { + match List [Count:number Items:count_items] + print( 'num items: ' Count.data.atoi() '\n' ) + + i: int = 1 + for Item:item in Items { + print( ' item ' i ': ' ^Item '\n' ) + i = i + 1 + } + } + } +end # counting + +cons Counting: counting[] +parse counting::start(Counting)[ stdin ] +##### IN ##### +3 1 b c 1 1 0 3 a b c +##### EXP ##### +num items: 3 + item 1: 1 + item 2: b + item 3: c +num items: 1 + item 1: 1 +num items: 0 +num items: 3 + item 1: a + item 2: b + item 3: c |