Class: Scp

Inherits:
Object
  • Object
show all
Defined in:
lib/linmeric/Scopify.rb

Overview

This class manipulates a string representing an algebric expression underlining the higher priority operations putting them between brackets. Scp prepares strings to be parsed. It must work associated with Sizer. These rules are followed:

  • … = … => (…) = (…) (same with ‘>`)

  • a + b * c => a + (b * c) (same with ‘/`)

  • a ^ b => (a ^ (b))

  • <keyword>: <argument> => (<keyword>: <argument>)

Author

Massimiliano Dal Mas ([email protected])

License

Distributed under MIT license

Instance Method Summary collapse

Constructor Details

#initializeScp

Initializes a new counter



20
21
22
# File 'lib/linmeric/Scopify.rb', line 20

def initialize
  @i = 0 
end

Instance Method Details

#countObject

Returns the current value of the counter



154
155
156
# File 'lib/linmeric/Scopify.rb', line 154

def count()
  return @i
end

#insert_b(expr) ⇒ Object

Inserts a couple of brackets ‘()` before non-binary sum and diff. operators

  • argument: string to be checked and manipulated

  • returns: manipulated string



163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/linmeric/Scopify.rb', line 163

def insert_b(expr)
  @i = 0
  string = false
  while @i < expr.size 
    string = (expr[@i] == "\"") ? (string ? false : true) : (string)
    if (expr[@i] == '-' or expr[@i] == '+') and ((expr[@i - 1] == '(') or (@i == 0)) and !string then
      expr.insert @i, '()'
    end
    @i += 1
  end
  return expr
end

#scopify(expr) ⇒ Object

Main function that analyzes the string and puts the brackets where it is necessary.

  • argument: string to be manipulated

  • returns: manipulated string



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/linmeric/Scopify.rb', line 29

def scopify(expr)
  expr = insert_b(expr)
  @i         = 0
  n_expr     = ""
  last_empty = 0
  open_b     = 0
  open_p_b   = 0
  open_m_b   = 0
  eq         = false
  stack      = Array.new
  last_e     = Array.new
  state      = 0
  while @i < expr.size
    case expr[@i]
      # Each part between brackets is seen as a subexpression
      # and it is analyzed recoursively.
      when '('
        scp = Scp.new
        n_expr += expr[@i] + scp.scopify(extract(expr[(@i + 1)...expr.length])) 
        @i += scp.count  
      when /[\*\/]/
        # If there are open brackets of higher opertions
        # it closes them
        if open_m_b > 0
          n_expr += ')' * open_m_b
          last_empty = last_e.pop
          open_m_b = 0
          #open_b -= 1
        end
        if state == 2
          n_expr += ')' * open_p_b
          open_p_b = 0
          state = (stack.size > 0 ? stack.pop : 0)
        end
        # If it is not still analyzing a multiplication, it adds the brackets 
        # following the rules
        unless state == 1
          n_expr.insert last_empty, '(' 
          state = 1
          open_b += 1
        end
        n_expr += expr[@i]
        last_empty = n_expr.size # + 1
      when /[\+\-]/
        # higher priority operation brackets are closed
        # last_empty is shifted
        n_expr += ')' * open_p_b if open_p_b > 0
        n_expr += ')' * open_b if open_b > 0
        state = 0
        open_b = 0
        open_p_b = 0
        n_expr += expr[@i]
        last_empty = n_expr.size
      when /\^/
        # It begins to put between brackets the operation and its exponent
        if open_m_b > 0 then
          n_expr += ")" * open_m_b
          last_empty = last_e.pop
          #open_b -= 1
          open_m_b = 0
        end
        n_expr.insert last_empty, '(' unless state == 2
        last_empty += 1 unless state == 2
        n_expr += expr[@i] + (expr[@i+1] == '(' ? '' : '(')
        open_p_b += (expr[@i+1] == '(' ? 1 : (state == 2 ? 1:2))
        stack.push state unless state == 2
        state = 2
      when /\=/
        # The expression at the left of `=` is put between brackets
        # and a bracket at the right is opened
        # It closes previously opened brackets
        n_expr += ')' * open_p_b if open_p_b > 0
        n_expr += ')' * open_b   if open_b > 0
        n_expr += ')' * open_m_b if open_m_b >0
        open_b   = 0
        open_p_b = 0
        open_m_b = 0
        n_expr = '(' + n_expr + ')' + expr[@i]
        n_expr += '('
        last_empty = n_expr.size
        state = 0
        eq = true
      when /\>/
        n_expr += ')' * open_p_b if open_p_b > 0
        n_expr += ')' * open_b if open_b > 0
        open_b = 0
        open_p_b = 0
        n_expr = '(' + n_expr + ')' + expr[@i]
        last_empty = n_expr.size
      when /\:/
        n_expr.insert last_empty, '('
        n_expr += expr[@i]
        last_k = n_expr[(last_empty+1)...n_expr.size]
        open_m_b += 1 if  "mx:integ:as:from:".include? last_k
        last_e.pop if last_e.count > 0 and (last_k == "mx:" or last_k == "integ:")# or last_k == "solve:")
        last_e.push last_empty if last_k == "mx:" or last_k == "integ:"# or last_k == "solve:"
        last_empty = n_expr.size
        open_b += 1 unless "mx:integ:as:from:".include? last_k
      when /\"/
        n_expr += expr[@i]
        @i += 1
        n_expr += discard(expr)
        last_empty = n_expr.length
      when /\~/
        n_expr += ')' * open_p_b if open_p_b > 0
        n_expr += ')' * (open_b - 1 ) if open_b - 1 > 0
        open_p_b = 0
        open_b = 1
        state = (stack.size > 0 ? stack.pop : 0)
        n_expr += expr[@i]
        last_empty = n_expr.size 
      else
        n_expr += expr[@i]
    end
    @i += 1
  end
  # it closes all the opened brackets
  n_expr += ')' * open_m_b if open_m_b > 0
  n_expr += ')' * open_p_b if open_p_b > 0
  n_expr += ')' * open_b if open_b > 0
  n_expr += ')' if eq
  return n_expr
end