my $grammar = <<'__END_OF_GRAMMAR__'; { use strict; use warnings; } parse : item(s?) /\Z/ { $item[1] } item : subnet | option subnet : SUBNET IP_ADDR NETMASK IP_ADDR subnet_blk { [ @item[0,2,4,5] ] } subnet_blk : option(s?) option : OPTION option_list { [ $item[0], @{$item[2]} ] } option_list : ... # Reserved Words # ============== #SUBNET : IDENT { $item[1] eq 'subnet' ? $item[1] : undef } #NETMASK : IDENT { $item[1] eq 'netmask' ? $item[1] : undef } #OPTION : IDENT { $item[1] eq 'option' ? $item[1] : undef } SUBNET : /subnet(?![a-zA-Z-9_])/ NETMASK : /netmask(?![a-zA-Z-9_])/ OPTION : /option(?![a-zA-Z-9_])/ # Tokens # ====== IDENT : /[a-zA-Z][a-zA-Z-9_]*/ IP_ADDR : /\d+\.\d+\.\d+\.\d+/ __END_OF_GRAMMAR__