Class: TPPlus::Scanner

Inherits:
Object
  • Object
show all
Defined in:
lib/tp_plus/scanner.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeScanner

Returns a new instance of Scanner.



3
4
# File 'lib/tp_plus/scanner.rb', line 3

def initialize
end

Instance Attribute Details

#colObject (readonly)

Returns the value of attribute col.



6
7
8
# File 'lib/tp_plus/scanner.rb', line 6

def col
  @col
end

#linenoObject (readonly)

Returns the value of attribute lineno.



6
7
8
# File 'lib/tp_plus/scanner.rb', line 6

def lineno
  @lineno
end

#tok_colObject (readonly)

Returns the value of attribute tok_col.



7
8
9
# File 'lib/tp_plus/scanner.rb', line 7

def tok_col
  @tok_col
end

#tok_lineObject (readonly)

Returns the value of attribute tok_line.



7
8
9
# File 'lib/tp_plus/scanner.rb', line 7

def tok_line
  @tok_line
end

Instance Method Details

#isDigit?(ch) ⇒ Boolean

Returns:

  • (Boolean)


39
40
41
42
43
44
45
46
47
48
# File 'lib/tp_plus/scanner.rb', line 39

def isDigit?(ch)
  return false if ch == -1

  case ch
  when '0','1','2','3','4','5','6','7','8','9'
    return true
  else
    return false
  end
end

#isLetter?(ch) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/tp_plus/scanner.rb', line 50

def isLetter?(ch)
  return false if ch == -1

  case ch
  when 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
       'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
       '_'
    return true
  else
    return false
  end
end

#nextObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/tp_plus/scanner.rb', line 23

def next
  if @rdOffset < @src.length
    @offset = @rdOffset
    @ch = @src[@rdOffset]
    if @ch == "\n"
      @lineno += 1
      @col = 0
    end
    @rdOffset += 1
    @col += 1
  else
    @offset = @src.length
    @ch = -1
  end
end

#next_tokenObject

return token



140
141
142
143
144
145
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
176
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/tp_plus/scanner.rb', line 140

def next_token
  self.skipWhitespace

  @tok_line = @lineno
  @tok_col = @col

  tok = nil
  lit = ""
  ch = @ch

  if isLetter?(ch)
    lit = self.scanIdentifier
    if @ch == '['
      tok = TPPlus::Token.lookup_data(lit)
    elsif lit == "DIV"
      tok = :DIV
    else
      # keywords are longer than 1 char, avoid lookup otherwise
      if lit.length > 1
        if @prevDot
          case lit
          when "gp1","gp2","gp3","gp4","gp5"
            tok = :GROUP
          else
            tok = TPPlus::Token.lookup(lit)
          end
        else
          tok = TPPlus::Token.lookup(lit)
        end
      else
        tok = :WORD
      end
    end
  elsif isDigit?(ch)
    tok, lit = self.scanNumber
  else
    self.next # always make progress
    case ch
    when -1
      return nil
    when '='
      if @ch == '='
        tok = :EEQUAL
        self.next
      else
        tok = :EQUAL
      end
    when ':'
      if @ch == "="
        tok = :ASSIGN
        self.next
      else
        tok = :COLON
      end
    when "<"
      if @ch == "="
        tok = :LTE
        self.next
      elsif @ch == ">"
        tok = :NOTEQUAL
        self.next
      else
        tok = :LT
      end
    when ">"
      if @ch == "="
        tok = :GTE
        self.next
      else
        tok = :GT
      end
    when "+"
      tok = :PLUS
    when "-"
      tok = :MINUS
    when "*"
      tok = :STAR
    when "/"
      tok = :SLASH
    when "&"
      if @ch == "&"
        tok = :AND
        self.next
      elsif isLetter?(@ch)
        tok = :ADDRESS
        lit = self.scanIdentifier
      else
        tok = :ILLEGAL
      end
    when "|"
      if @ch == "|"
        tok = :OR
        self.next
      else
        tok = :ILLEGAL
      end
    when "%"
      tok = :MOD
    when ";"
      tok = :SEMICOLON
    when "."
      if self.isDigit?(@ch)
        tok, lit = self.scanReal
      else
        tok = :DOT
      end
    when "!"
      if @ch == "="
        tok = :NOTEQUAL
        self.next
      else
        tok = :BANG
      end
    when "\"", "'"
      tok = :STRING
      lit = self.scanString(ch)
    when "#"
      tok = :COMMENT
      lit = self.scanComment
    when "@"
      tok = :LABEL
      lit = self.scanLabel
    when '('
      tok = :LPAREN
    when ')'
      tok = :RPAREN
    when ','
      tok = :COMMA
    when '['
      tok = :LBRACK
    when ']'
      tok = :RBRACK
    when '{'
      tok = :LBRACE
    when '}'
      tok = :RBRACE
    when "\n"
      tok = :NEWLINE
    else
      tok = :ILLEGAL
      lit = ch
    end
  end

  if tok == :DOT
    @prevDot = true
  else
    @prevDot = false
  end

  return [tok, lit]
end

#scan_setup(src) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/tp_plus/scanner.rb', line 8

def scan_setup(src)
  @src = src
  @lineno = 1
  @ch = " "
  @offset = 0
  @col = 0
  @rdOffset = 0
  @prevDot = false # for groups

  @tok_line = 0
  @tok_col = 0

  self.next
end

#scanCommentObject



109
110
111
112
113
114
115
116
# File 'lib/tp_plus/scanner.rb', line 109

def scanComment
  offs = @offset-1 # opening # already consumed
  while @ch != "\n" && @ch != -1
    self.next
  end

  return @src[offs,(@offset-offs)]
end

#scanIdentifierObject



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/tp_plus/scanner.rb', line 69

def scanIdentifier
  offs = @offset
  while isLetter?(@ch) || isDigit?(@ch)
    self.next
  end

  # allow one ? or ! at end
  if @ch == '?' || @ch == '!'
    self.next
  end

  return @src[offs,(@offset-offs)]
end

#scanLabelObject



130
131
132
133
134
135
136
137
# File 'lib/tp_plus/scanner.rb', line 130

def scanLabel
  offs = @offset
  while self.isLetter?(@ch)
    self.next
  end

  return @src[offs, (@offset-offs)]
end

#scanNumberObject



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/tp_plus/scanner.rb', line 92

def scanNumber
  offs = @offset
  while self.isDigit?(@ch)
    self.next
  end
  if @ch == '.'
    self.next
    while self.isDigit?(@ch)
      self.next
    end

    return [:REAL, @src[offs,(@offset-offs)].to_f]
  else
    return [:DIGIT, @src[offs,(@offset-offs)].to_i]
  end
end

#scanRealObject



83
84
85
86
87
88
89
90
# File 'lib/tp_plus/scanner.rb', line 83

def scanReal
  offs = @offset-1
  while self.isDigit?(@ch)
    self.next
  end

  return [:REAL, @src[offs,(@offset-offs)].to_f]
end

#scanString(type) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
# File 'lib/tp_plus/scanner.rb', line 118

def scanString(type)
  offs = @offset
  while @ch != type && @ch != -1
    self.next
  end

  # consume close
  self.next

  return @src[offs, (@offset-offs-1)] # -1 to remove trailing " or '
end

#skipWhitespaceObject



63
64
65
66
67
# File 'lib/tp_plus/scanner.rb', line 63

def skipWhitespace
  while @ch == ' ' || @ch == "\t" || @ch == "\r"
    self.next
  end
end