qr{ (?(DEFINE) (? (?&number) (?&expr_) ) (? (?: \s++ (?: (?&expr) \s++ (?&binary_op) (?&expr_) | (?&unary_op) (?&expr_) ) )? ) (? ( (?&NUMBER) ) (?{ local @stack = @stack; push @stack, $^N; }) ) (? ( (?&IDENT) ) (?(?{ !exists($unary_ops{$^N}) }) (*FAIL) ) (?{ local @stack = @stack; $unary_ops{$^N}->($stack[-1]); }) ) (? ( [-+/*^] ) (?{ local @stack = @stack; $binary_ops{$^N}->($stack[-2], pop(@stack)); }) ) # Tokens. # Backtracking can't cause a token # rule to return something different. (? \d++ (?: [.] \d*+ )?+ | [.] \d++ ) (? [_A-Za-z][_A-Za-z0-9]*+ ) ) (?{ local @stack = (); }) \A \s* (?&expr) \s* \z (?{ $result = pop(@stack) }) }sx;