# # 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 start { # Ignore whitespace. ignore /rl_ws/ # Tokens. token id /rl_id/ token number /rl_num/ } # # Productions # # Arbitrary item. def item [id] | [number] # List production one. The condition stops the # greedy list when it has gone too far. def count_items target: int count: int [count_items item] { # Pass up the data lhs.target = r1.target lhs.count = r1.count + 1 if lhs.count > lhs.target { reject } } # List production two, the base. | [number] { match lhs [Number: number] lhs.target = Number.data.atoi() 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 [count_items] { if r1.count < r1.target { reject } } def start [counted_list*] { for List: counted_list in lhs { match List [CountItems:count_items] print( 'num items: ' CountItems.target '\n' ) i: int = 1 for Item:item in CountItems { print( ' item ' i ': ' Item '\n' ) i = i + 1 } } } parse start( stdin )