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
|
# File 'lib/langscan/c.rb', line 38
def scan_unsorted(input, &block)
pm = LangScan::PairMatcher.new(3,2,2,2)
pm.define_intertoken_fragment :space, 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.define_pair :preproc, :preproc_beg, "#", :preproc_end, "\n"
pm.parse(LangScan::C::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 fun.type == :ident && IdentType[fun.text] == :ident
if (outer = pair.outer) && pair.outmost.pair_type == :paren
elsif outer &&
outer.pair_type == :preproc &&
2 <= outer.after_open_length &&
outer.around_open(1).type == :ident && /\Adefine\z/ =~ outer.around_open(1).text &&
outer.around_open(2) == pair.around_open(-1)
if pair.around_open(-1).end_byteno == pair.open_token.beg_byteno
fun.type = :fundef
end
elsif !outer ||
(!outer.outer && outer.pair_type == :brace &&
2 <= outer.before_open_length &&
outer.around_open(-2).type == :ident && /\Aextern\z/ =~ outer.around_open(-2).text &&
outer.around_open(-1).type == :string && /\A"C"\z/ =~ outer.around_open(-1).text)
if 2 <= pair.before_open_length &&
pair.around_open(1).type == :punct && pair.around_open(1).text == '(' &&
pair.around_close(-1).type == :punct && pair.around_close(-1).text == ')' &&
pair.around_open(-2).type == :ident && IdentType[pair.around_open(-2).text] == :ident
pair.around_open(-2).type = :fundecl
elsif 1 <= pair.after_close_length &&
pair.around_close(1).type == :punct && /\A;\z/ =~ pair.around_close(1).text
fun.type = :fundecl
elsif 1 <= pair.after_close_length &&
((pair.around_close(1).type == :punct && /\A\{\z/ =~ pair.around_close(1).text) || (pair.around_close(1).type == :ident))
fun.type = :fundef
else
fun.type = :funcall
end
else
if /\Adefined\z/ =~ fun.text &&
(outer = pair.outer) &&
!outer.outer &&
outer.pair_type == :preproc &&
1 <= outer.after_open_length &&
/\Aif\z/ =~ outer.around_open(1).text
else
fun.type = :funcall
end
end
end
end
end
}
end
|