OSDN Git Service

fix minus with parenthesis bug
[mint/mint-lib.git] / lib / mint / builder / expression_tree.rb
1 # -*- coding: utf-8 -*-
2
3 module Mint
4
5   class ExpressionNode # :nodoc:
6     attr_reader :left, :right, :operator
7     attr_accessor :minus, :parenthesis
8     def initialize(left, right)
9       @left     = left
10       @right    = right
11       @operator = :unknown
12
13       @minus       = false
14       @parenthesis = false
15     end
16     def to_s
17       show to_s_local
18     end
19     def to_latex
20       show to_latex_local
21     end
22     def naked
23       result = self.dup
24       result.parenthesis = false
25       result
26     end
27     private
28     def to_s_local
29       "#{left} #{operator} #{right}"
30     end
31     def to_latex_local
32       "#{left.to_latex} #{operator} #{right.to_latex}"
33     end
34     def show(string)
35       return "(-(#{string}))" if minus
36       return "(#{string})" if parenthesis
37       string
38     end
39   end
40
41   class AdditionNode < ExpressionNode # :nodoc:
42     def initialize(left, right)
43       super
44       @operator = :+
45     end
46   end
47
48   class SubtractionNode < ExpressionNode # :nodoc:
49     def initialize(left, right)
50       super
51       @operator = :-
52     end
53     def to_s_local
54       "#{left} #{operator} #{right}"
55     end
56   end
57
58   class MultipleNode < ExpressionNode # :nodoc:
59     def initialize(left, right)
60       super
61       @operator = :*
62     end
63     def to_latex_local
64       # FIXME: too dirty
65       if right.instance_of?(LiteralNode) ||
66          right.instance_of?(RootNode)    ||
67          right.instance_of?(FactorialNode)
68
69         unless right.to_s.match(/\A[-\.\d]+\z/)
70           return "#{left.to_latex}#{right.to_latex}"
71         end
72       end
73       "#{left.to_latex} \\times #{right.to_latex}"
74     end
75   end
76
77   class DivisionNode < ExpressionNode # :nodoc:
78     def initialize(left, right)
79       super
80       @operator = :div
81     end
82     def to_latex_local
83       "#{left.to_latex} \\div #{right.naked.to_latex}"
84     end
85   end
86
87   class FractionNode < ExpressionNode # :nodoc:
88     def initialize(left, right)
89       super
90       @operator = :/
91     end
92     def to_latex_local
93       "\\frac{#{left.to_latex}}{#{right.naked.to_latex}}"
94     end
95   end
96
97   class LiteralNode # :nodoc:
98     attr_accessor :value, :minus, :parenthesis
99     def initialize(value)
100       @value = value
101
102       @minus       = false
103       @parenthesis = false
104     end
105     def to_s
106       show to_s_local
107     end
108     def to_latex
109       show to_latex_local
110     end
111     def naked
112       result = self.dup
113       result.parenthesis = false
114       result
115     end
116     private
117     def to_s_local
118       @value.to_s
119     end
120     def to_latex_local
121       @value.to_s
122     end
123     def show(string)
124       return "-#{string}"   if minus
125       return "(#{string})"  if parenthesis
126       return "(-#{string})" if minus && parenthesis
127       string
128     end
129   end
130
131   class DecimalNode < LiteralNode # :nodoc:
132     attr_accessor :value
133     def initialize(value)
134       @value = value
135     end
136     def to_s_local
137       round_n(value.to_f, 3).to_s
138     end
139
140     private
141     def round_n(num, nth)
142       result = num * (10 ** nth)
143       (result.round() * (10 ** -nth)).to_f
144     end
145   end
146
147   class FactorialNode < LiteralNode # :nodoc:
148     attr_reader :value, :power
149     def initialize(value, power)
150       super value
151       @power = power
152     end
153     def to_s_local
154       "#{value}^#{power}"
155     end
156     def to_latex_local
157       return to_s if value.instance_of?(String)
158       "#{value.to_latex}^#{power.to_latex}"
159     end
160   end
161
162   class RootNode < LiteralNode # :nodoc:
163     attr_accessor :minus
164     attr_reader :value
165     def to_s_local
166       "sqrt(#{value})"
167     end
168     def to_latex_local
169       "\\sqrt{#{value}}"
170     end
171   end
172 end
173