Module: LangScan::D

Defined in:
lib/langscan/d.rb,
ext/langscan/d/d/d.c

Defined Under Namespace

Classes: Tokenizer

Constant Summary collapse

DEFAULT_ALLOW_TEMPLATE_PARAMETERS =
3
Keywords =
%w(
  abstract alias align asm assert auto bit body break byte
  case cast catch cdouble cent cfloat char class const continue creal
  dchar debug default delegate delete deprecated do double
  else enum export extern false final finally float for foreach function
  goto idouble if ifloat import in inout int interface invariant ireal is
  long mixin module new null out override package pragma private protected
  public real return short static struct super switch synchronized
  template this ~this throw true try typedef typeid typeof ubyte
  ucent uint ulong union unittest ushort version void volatile
  wchar while with
)
KeywordsHash =
{}
Types =
%w(bool char double float int long short void)
TypesHash =
{}
IdentType =
Hash.new(:ident)

Class Method Summary collapse

Class Method Details

.abbrevObject



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

def abbrev
  "d"
end

.each_fragment(input) ⇒ Object

for debug



191
192
193
194
195
196
# File 'lib/langscan/d.rb', line 191

def D.each_fragment(input)
  tokenizer = LangScan::D::Tokenizer.new(input)
  while t = tokenizer.get_token
    yield t
  end
end

.extnamesObject



30
31
32
# File 'lib/langscan/d.rb', line 30

def extnames
  [".d"]
end

.get_funtype(o) ⇒ Object



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
# File 'lib/langscan/d.rb', line 77

def get_funtype(o)
  return :fundecl if (!o)

  return :funcall if (o.pair_def[1] != '{')

  l = o.around_open(-1)

  return :fundecl if (!l || l.type == :classdef)

  lt = l.text

  if (lt == 'in' || lt == 'out' || lt == 'body' || lt == 'unittest')
    return :funcall
  end

  if (lt == ')')
    i = -2
    while (o.around_open(i) && o.around_open(i).text != '(')
      i -= 1
    end

    # mismatched paren not reached, this is if or for or...
    return :funcall if (!o.around_open(i))

    l2 = o.around_open(i-1)
    # this is if or for or...
    return :funcall if (!l2)

    l2t = l2.text

    if (l2t != 'version' && l2t != 'extern' && l2t != 'debug' && l2t != 'pragma')
      l3 = o.around_open(i-2)
      return :fundecl if (l3 && l3.text == 'template')

      return :funcall
    end

  end

  get_funtype(o.outer)
end

.is_fplike?(pair) ⇒ Boolean

Returns:

  • (Boolean)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/langscan/d.rb', line 62

def is_fplike?(pair)
  if pair.around_open(1) && pair.around_open(1).text == '*'
    pair.around_close(1) && pair.around_close(1).text == '('
    # type (*arg)());
    return true
  end

  t = pair.around_open(-2)
  if (t && (t.text == 'delegate' || t.text == 'function'))
    return true
  end

  return false
end

.is_fun?(fun) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/langscan/d.rb', line 34

def is_fun?(fun)
  fun.type == :ident && IdentType[fun.text] == :ident
end

.is_fundef?(pair) ⇒ Boolean

Returns:

  • (Boolean)


38
39
40
41
42
# File 'lib/langscan/d.rb', line 38

def is_fundef?(pair)
  1 <= pair.after_close_length &&
    (pair.around_close(1).type == :punct &&
       /\A\{\z/ =~ pair.around_close(1).text)
end

.is_new?(pair) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
59
60
# File 'lib/langscan/d.rb', line 53

def is_new?(pair)
  t = pair.around_open(-2)
  if (t && (t.text == 'new'))
    return true
  end

  return false
end

.is_template?(pair) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
48
49
50
51
# File 'lib/langscan/d.rb', line 44

def is_template?(pair)
  t = pair.around_open(-2)
  if (t && (t.text == 'template'))
    return true
  end

  return false
end

.nameObject



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

def name
  "D"
end

.scan(input, atp = DEFAULT_ALLOW_TEMPLATE_PARAMETERS, &block) ⇒ Object

LangScan::D.scan iterates over D program. It yields for each element which is interested by gonzui.



122
123
124
125
# File 'lib/langscan/d.rb', line 122

def scan(input, atp = DEFAULT_ALLOW_TEMPLATE_PARAMETERS, &block)
  sorter = PairMatcher.fragmentsorter(block)
  scan_unsorted(input, atp, &sorter)
end

.scan_unsorted(input, atp = DEFAULT_ALLOW_TEMPLATE_PARAMETERS, &block) ⇒ Object



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
160
161
162
163
164
165
# File 'lib/langscan/d.rb', line 127

def scan_unsorted(input, atp = DEFAULT_ALLOW_TEMPLATE_PARAMETERS, &block)
  before_num = 3 + atp * 2
  before_num = 4 if (before_num < 4)

  pm = LangScan::PairMatcher.new(before_num,2,2,2)
  pm.define_intertoken_fragment :space, nil
  pm.define_intertoken_fragment :preproc, nil
  pm.define_intertoken_fragment :comment, nil
  pm.define_pair :paren, :punct, "(", :punct, ")"
  pm.define_pair :brace, :punct, "{", :punct, "}"
  pm.define_pair :bracket, :punct, "[", :punct, "]"
  pm.parse(LangScan::D::Tokenizer.new(input), lambda {|f|
    if f.type == :ident
      f.type = IdentType[f.text]
    end
    yield f
  }) {|pair|
    if pair.pair_type == :paren
      if 1 <= pair.before_open_length
        fun = pair.around_open(-1)
        if is_fun?(fun)
          # ident(...)
          if is_new?(pair)
            fun.type = :classref
          elsif is_template?(pair)
            fun.type = :moduledef
          elsif is_fplike?(pair)
          elsif is_fundef?(pair)
            # name(...) { ... }
            fun.type = :fundef
          else
            outer = pair.outer
            fun.type = get_funtype(outer)
          end
        end
      end
    end
  }
end