Commit | Line | Data |
---|---|---|

88e1f1a2 JV |
1 | =head1 NAME |

2 | ||

3 | XS::APItest::KeywordRPN - write arithmetic expressions in RPN | |

4 | ||

5 | =head1 SYNOPSIS | |

6 | ||

7 | use XS::APItest::KeywordRPN qw(rpn calcrpn); | |

8 | ||

9 | $triangle = rpn($n $n 1 + * 2 /); | |

10 | ||

11 | calcrpn $triangle { $n $n 1 + * 2 / } | |

12 | ||

13 | =head1 DESCRIPTION | |

14 | ||

15 | This module supplies plugged-in keywords, using the new mechanism in Perl | |

16 | 5.11.2, that allow arithmetic to be expressed in reverse Polish notation, | |

17 | in an otherwise Perl program. This module has serious limitations and | |

18 | is not intended for real use: its purpose is only to test the keyword | |

19 | plugin mechanism. For that purpose it is part of the Perl core source | |

20 | distribution, and is not meant to be installed. | |

21 | ||

22 | =head2 RPN expression syntax | |

23 | ||

24 | Tokens of an RPN expression may be separated by whitespace, but such | |

25 | separation is usually not required. It is required only where unseparated | |

26 | tokens would look like a longer token. For example, C<12 34 +> can be | |

27 | written as C<12 34+>, but not as C<1234 +>. | |

28 | ||

29 | An RPN expression may be any of: | |

30 | ||

31 | =over | |

32 | ||

33 | =item C<1234> | |

34 | ||

35 | A sequence of digits is an unsigned decimal literal number. | |

36 | ||

37 | =item C<$foo> | |

38 | ||

39 | An alphanumeric name preceded by dollar sign refers to a Perl scalar | |

40 | variable. Only variables declared with C<my> or C<state> are supported. | |

41 | If the variable's value is not a native integer, it will be converted | |

42 | to an integer, by Perl's usual mechanisms, at the time it is evaluated. | |

43 | ||

44 | =item I<A> I<B> C<+> | |

45 | ||

46 | Sum of I<A> and I<B>. | |

47 | ||

48 | =item I<A> I<B> C<-> | |

49 | ||

50 | Difference of I<A> and I<B>, the result of subtracting I<B> from I<A>. | |

51 | ||

52 | =item I<A> I<B> C<*> | |

53 | ||

54 | Product of I<A> and I<B>. | |

55 | ||

56 | =item I<A> I<B> C</> | |

57 | ||

58 | Quotient when I<A> is divided by I<B>, rounded towards zero. | |

59 | Division by zero generates an exception. | |

60 | ||

61 | =item I<A> I<B> C<%> | |

62 | ||

63 | Remainder when I<A> is divided by I<B> with the quotient rounded towards zero. | |

64 | Division by zero generates an exception. | |

65 | ||

66 | =back | |

67 | ||

68 | Because the arithmetic operators all have fixed arity and are postfixed, | |

69 | there is no need for operator precedence, nor for a grouping operator | |

70 | to override precedence. This is half of the point of RPN. | |

71 | ||

72 | An RPN expression can also be interpreted in another way, as a sequence | |

73 | of operations on a stack, one operation per token. A literal or variable | |

74 | token pushes a value onto the stack. A binary operator pulls two items | |

75 | off the stack, performs a calculation with them, and pushes the result | |

76 | back onto the stack. The stack starts out empty, and at the end of the | |

77 | expression there must be exactly one value left on the stack. | |

78 | ||

79 | =cut | |

80 | ||

81 | package XS::APItest::KeywordRPN; | |

82 | ||

83 | { use 5.011001; } | |

84 | use warnings; | |

85 | use strict; | |

86 | ||

58e85f6b | 87 | our $VERSION = "0.001"; |

88e1f1a2 JV |
88 | |

89 | require XSLoader; | |

90 | XSLoader::load(__PACKAGE__, $VERSION); | |

91 | ||

92 | =head1 OPERATORS | |

93 | ||

94 | These are the operators being added to the Perl language. | |

95 | ||

96 | =over | |

97 | ||

98 | =item rpn(EXPRESSION) | |

99 | ||

100 | This construct is a Perl expression. I<EXPRESSION> must be an RPN | |

101 | arithmetic expression, as described above. The RPN expression is | |

102 | evaluated, and its value is returned as the value of the Perl expression. | |

103 | ||

104 | =item calcrpn VARIABLE { EXPRESSION } | |

105 | ||

106 | This construct is a complete Perl statement. (No semicolon should | |

107 | follow the closing brace.) I<VARIABLE> must be a Perl scalar C<my> | |

108 | variable, and I<EXPRESSION> must be an RPN arithmetic expression as | |

109 | described above. The RPN expression is evaluated, and its value is | |

110 | assigned to the variable. | |

111 | ||

112 | =back | |

113 | ||

114 | =head1 BUGS | |

115 | ||

116 | This module only performs arithmetic on native integers, and only a | |

117 | small subset of the arithmetic operations that Perl offers. This is | |

118 | due to it being intended only for demonstration and test purposes. | |

119 | ||

120 | The RPN parser is liable to leak memory when a parse error occurs. | |

121 | It doesn't leak on success, however. | |

122 | ||

123 | The linkage with Perl's lexer is liable to fail when an RPN expression | |

124 | is spread across multiple lines. | |

125 | ||

126 | =head1 SEE ALSO | |

127 | ||

128 | L<Devel::Declare>, | |

129 | L<perlapi/PL_keyword_plugin> | |

130 | ||

131 | =head1 AUTHOR | |

132 | ||

133 | Andrew Main (Zefram) <zefram@fysh.org> | |

134 | ||

135 | =head1 COPYRIGHT | |

136 | ||

137 | Copyright (C) 2009 Andrew Main (Zefram) <zefram@fysh.org> | |

138 | ||

139 | =head1 LICENSE | |

140 | ||

141 | This module is free software; you can redistribute it and/or modify it | |

142 | under the same terms as Perl itself. | |

143 | ||

144 | =cut | |

145 | ||

146 | 1; |