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 start { # Ignore whitespace. ignore /rl_ws/ literal ';' # Tokens. token id /rl_id/ token number /rl_num/ } # # Global Data # target: int count: int # # Productions # def get_target [number] { count = 0 target = r1.data.atoi() print( 'target: ' target '\n' ) } # Arbitrary item. def item [number] | [id] def count_items [one_item count_items] | [] def one_item [item] { count = count + 1 if count > target { reject } print( 'ITEM\n' ) } # 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] { print( 'trying: ' count ' for: ' target '\n' ) if 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 } } print( '*** SUCCESS ***\n' ) } } cons Counting: counting[] parse counting::start(Counting)[ stdin ]