Module: LangScan::Eiffel

Defined in:
lib/langscan/eiffel.rb

Defined Under Namespace

Classes: Eof

Constant Summary collapse

Pattern =
[
  [:comment, '--.*'],
  [:character, "'%.'"],
  [:character, "'[^%]'"],
  [:string, '""'],
  [:string, '"', '[^%]"'],
  [:floating, '(?:\\d[\\d_]*)?\\.(?:\\d[\\d_]*)?(?:[eE][+-]?(?:\\d[\\d_]*))?'],
  [:integer, '\\d[\\d_]*'],
  [:ident, "[a-zA-Z]\\w*"],
  [:punct, '[()]'],
  [:punct, '[!$*+-/^~=<>{}\\[\\];:,\\.@\\\\]+'],  # rough.
]
Types =
%w(INTEGER REAL DOUBLE CHARACTER BOOLEAN)
Keywords =
%w(alias all and as check class creation debug deferred do
else elseif end ensure expanded export external feature from
frozen if implies indexing infix inherit inspect invariant is
like local loop not obsolete old once or prefix redefine
rename require rescue retry select separate then undefine
until variant when xor
BIT Current False Precursor Result Strip True Unique)
IdentType =
Hash.new(:ident)

Class Method Summary collapse

Class Method Details

.abbrevObject



22
23
24
# File 'lib/langscan/eiffel.rb', line 22

def abbrev
  "eiffel"
end

.back_token(tkns, i, type, name) ⇒ Object



88
89
90
91
# File 'lib/langscan/eiffel.rb', line 88

def back_token(tkns, i, type, name)
  i -= 1 while (i >= 0 && !check_token(tkns, i, type, name))
  i
end

.check_token(tkns, index, type, name = nil) ⇒ Object

Raises:



56
57
58
59
60
# File 'lib/langscan/eiffel.rb', line 56

def check_token(tkns, index, type, name = nil)
  t = tkns[index]
  raise Eof.new if !t
  return t.type == type && (!name || t.text == name)
end

.check_token_next(tkns, index, step, type, name = nil) ⇒ Object



70
71
72
73
# File 'lib/langscan/eiffel.rb', line 70

def check_token_next(tkns, index, step, type, name = nil)
  index = go_next(tkns, index, step)
  check_token(tkns, index, type, name)
end

.check_token_prev(tkns, index, step, type, name = nil) ⇒ Object



83
84
85
86
# File 'lib/langscan/eiffel.rb', line 83

def check_token_prev(tkns, index, step, type, name = nil)
  index = go_prev(tkns, index, step)
  check_token(tkns, index, type, name)
end

.extnamesObject



26
27
28
# File 'lib/langscan/eiffel.rb', line 26

def extnames
  [".e"]
end

.go_next(tkns, index, step) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/langscan/eiffel.rb', line 62

def go_next(tkns, index, step)
  for i in 0...step
    index += 1
    index += 1 while (check_token(tkns, index, :comment))
  end
  index
end

.go_prev(tkns, index, step) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/langscan/eiffel.rb', line 75

def go_prev(tkns, index, step)
  for i in 0...step
    index -= 1
    index -= 1 while (check_token(tkns, index, :comment))
  end
  index
end

.nameObject



18
19
20
# File 'lib/langscan/eiffel.rb', line 18

def name
  "Eiffel"
end

.scan(input, &block) ⇒ Object



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
152
153
154
155
156
157
158
159
# File 'lib/langscan/eiffel.rb', line 93

def scan(input, &block)
  tkns = Array.new
  scanner = EasyScanner.new(Pattern, Types, Keywords)
  scanner.scan(input) do |f|
    if f.type == :ident
      f.type = IdentType[f.text.downcase]
    elsif f.type == :floating && f.text == '.'
      f.type = :punct
    end
    tkns << f
  end

  begin
    i = 0
    while (i < tkns.size)
      if (check_token(tkns, i, :punct, ')'))
        j = back_token(tkns, i-1, :punct, '(')
        j = go_prev(tkns, j, 1)
        if (j >= 0 && check_token(tkns, j, :ident))
          if (check_token_next(tkns, i, 1, :keyword, 'is') ||
              check_token_next(tkns, i, 1, :punct, ':'))
            tkns[j].type = :fundef
            i += 1 while (!check_token(tkns, i, :keyword))
          else
            tkns[j].type = :funcall
          end
        end
      elsif (check_token(tkns, i, :keyword, 'is'))
        if (check_token_next(tkns, i, 1, :keyword, 'do') ||
            check_token_next(tkns, i, 1, :keyword, 'local') ||
            check_token_next(tkns, i, 1, :keyword, 'require') ||
            check_token_next(tkns, i, 1, :keyword, 'once') ||
            check_token_next(tkns, i, 1, :keyword, 'external'))
          if (check_token_prev(tkns, i, 3, :ident) &&
              check_token_prev(tkns, i, 2, :punct, ':') &&
              (check_token_prev(tkns, i, 1, :ident) ||
               check_token_prev(tkns, i, 1, :type)))
            tkns[go_prev(tkns, i, 3)].type = :fundef
          elsif (check_token_prev(tkns, i, 1, :ident))
            tkns[go_prev(tkns, i, 1)].type = :fundef
          end
        end
      elsif (check_token(tkns, i, :keyword, 'class'))
        if (check_token_next(tkns, i, 1, :ident))
          tkns[go_next(tkns, i, 1)].type = :classdef
        end
      elsif (check_token(tkns, i, :keyword, 'rename'))
        while (check_token_next(tkns, i, 1, :ident) &&
               check_token_next(tkns, i, 2, :keyword, 'as') &&
               check_token_next(tkns, i, 3, :ident))
          tkns[i = go_next(tkns, i, 3)].type = :fundef
          i = go_next(tkns, i, 1)
          break if (!check_token(tkns, i, :punct, ','))
        end
      end

      i += 1

    end
  rescue Eof
  end

  tkns.each do |f|
    yield f
  end

end