Class: Rigrate::Parser

Inherits:
Object
  • Object
show all
Includes:
Migration
Defined in:
lib/rigrate/parser.rb

Defined Under Namespace

Modules: LexStatus, StringType, TokenType Classes: Token

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Migration

#data_source, #join, #migrate, #minus, #self_eval, #union

Instance Attribute Details

#tokensObject

Returns the value of attribute tokens.



32
33
34
# File 'lib/rigrate/parser.rb', line 32

def tokens
  @tokens
end

Instance Method Details

#full_parse(tks) ⇒ Object

private



127
128
129
130
131
# File 'lib/rigrate/parser.rb', line 127

def full_parse(tks)
  while tks.size > 0
    parse_rs_or_migrate_exp(tks)
  end
end

#get_token_type(str) ⇒ Object



266
267
268
# File 'lib/rigrate/parser.rb', line 266

def get_token_type(str)
  TokenType.const_get(str.strip.upcase) 
end

#is_a_token?(str) ⇒ Boolean

Returns:

  • (Boolean)


262
263
264
# File 'lib/rigrate/parser.rb', line 262

def is_a_token?(str)
  TokenType.constants.include? str.strip.upcase.to_sym
end

#lex(str) ⇒ Object

load script str -> tokens

TODO there is a bug need to fixed, when comment str include FROM key word will praser error.


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
# File 'lib/rigrate/parser.rb', line 37

def lex(str)
  status = LexStatus::INIT
  @tokens = []
  t_token = ''
  t_sub_token = ''
  string_type = StringType::DOUBLE_QUOTE
  char_arr = str.chars
  loop do
    c = char_arr.shift

    if c == nil
      token = Token.new TokenType::RUBY_STR, t_token
      @tokens << token
      break
    end

    if status == LexStatus::IN_KEYWORD && c =~ /\s/
      if is_a_token?(t_token)
        @tokens << (Token.new get_token_type(t_token), t_token)
        t_token = ''
        t_sub_token = ''
        status = LexStatus::INIT
        next
      else
        status = LexStatus::IN_RUBY_CODE
      end
    end

    if status != LexStatus::IN_RUBY_CODE && status != LexStatus::IN_RUBY_STR
      (status = LexStatus::INIT && next) if c =~ /\s/
    end

    t_token << c
    t_sub_token << c

    if status == LexStatus::IN_RUBY_CODE ||
      status == LexStatus::IN_KEYWORD
      if c == '"'
        string_type = StringType::DOUBLE_QUOTE
        status = LexStatus::IN_RUBY_STR
        next
      elsif c == "'"
        string_type = StringType::SINGLE_QUOTE
        status = LexStatus::IN_RUBY_STR
        next
      end
    end

    if status == LexStatus::IN_RUBY_STR
      is_matched = false
      if (string_type == StringType::DOUBLE_QUOTE && c == '"') ||
         (string_type == StringType::SINGLE_QUOTE && c == "'")
        is_matched = true
      end
      
      if is_matched && t_token[-1] != "\\"
        status = LexStatus::IN_RUBY_CODE
      elsif c =~ /\s/
        t_sub_token = ''
      end
    end

    if status == LexStatus::IN_RUBY_CODE && c =~ /\s/
      if is_a_token? t_sub_token
        token = Token.new TokenType::RUBY_STR, t_token.sub(/#{t_sub_token}$/, '')
        @tokens << token
        token = Token.new get_token_type(t_sub_token), t_sub_token
        @tokens << token

        status = LexStatus::INIT
        t_token = ''
      end

      t_sub_token = ''
    end

    if status == LexStatus::INIT
      status = LexStatus::IN_KEYWORD
    end
  end

  self
end

#parse_condition_exp(tks) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/rigrate/parser.rb', line 214

def parse_condition_exp(tks)
  token = tks.shift
  return if token.nil?

  if token.type == TokenType::ON
    v1 = parse_rs_exp(tks)

    if v1.nil?
      raise ParserError.new("ON expression should end with a [RUBY_STR]")
    end
  else
    tks.unshift token
    return
  end

  v1
end

#parse_migrate_exp(tks) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/rigrate/parser.rb', line 146

def parse_migrate_exp(tks)
  token = tks.shift

  if token.type == TokenType::FROM
    v1 = parse_operate_exp(tks)

    sub_token = tks.shift
    if sub_token.type == TokenType::TO
      v2 = parse_rs_exp(tks)
      v3 = parse_condition_exp(tks)
      v4 = parse_using_exp(tks)
      migrate(v1, v2, v3, v4)

      # sub_token_1 = tks.shift

      # if not sub_token_1.nil?

      #   if sub_token_1.type == TokenType::ON

      #     cond = tks.shift

      #     migrate(v1, v2, cond)

      #   else

      #     tks.unshift sub_token_1

      #     migrate(v1, v2)

      #   end

      # else

      #   migrate(v1, v2)

      # end

    else
      raise ParserError.new("Syntax Error: need TO expression")
    end
  end
end

#parse_operate_exp(tks) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/rigrate/parser.rb', line 177

def parse_operate_exp(tks)
  v1 = parse_rs_exp(tks)

  while true
    token = tks.shift
    if token.type != TokenType::UNION &&
       token.type != TokenType::JOIN &&
       token.type != TokenType::MINUS
      tks.unshift token
      break
    end

    v2 = parse_rs_exp(tks)
    if token.type == TokenType::UNION
      v1 = union(v1, v2)
    elsif token.type == TokenType::MINUS
      v1 = minus(v1, v2) 
    elsif token.type == TokenType::JOIN
      sub_token = tks.shift

      if not sub_token.nil?
        if sub_token.type == TokenType::ON
          cond = tks.shift
          v1 = join(v1, v2, cond.value)
        else
          tks.unshift sub_token
          v1 = join(v1, v2)
        end
      else
        v1 = join(v1, v2)
      end
    end
  end

  v1
end

#parse_rs_exp(tks) ⇒ Object

TODO return value should change



251
252
253
254
255
256
257
258
259
260
# File 'lib/rigrate/parser.rb', line 251

def parse_rs_exp(tks)
  token = tks.shift
  return if token.nil?

  if token.type == TokenType::RUBY_STR
    return token.value
  else
    raise ParserError.new("Invalid Syntax")
  end
end

#parse_rs_or_migrate_exp(tks) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/rigrate/parser.rb', line 133

def parse_rs_or_migrate_exp(tks)
  token = tks.shift

  if token.type == TokenType::RUBY_STR
    v1 = self_eval token.value
  else
    tks.unshift token
    v1 = parse_migrate_exp(tks)
  end

  v1
end

#parse_using_exp(tks) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/rigrate/parser.rb', line 232

def parse_using_exp(tks)
  token = tks.shift
  return if token.nil?

  if token.type == TokenType::USING
    v1 = parse_rs_exp(tks)

    if v1.nil?
      raise ParserError.new("USING expression should end with a [RUBY_STR]")
    end
  else
    tks.unshift token
    return
  end

  v1
end

#parsingObject



121
122
123
# File 'lib/rigrate/parser.rb', line 121

def parsing
  full_parse tokens.dup
end