dbc 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,237 @@
1
+ # Copyright (c) 2004 Charles M Mills
2
+ # This document is licenced under The MIT Licence.
3
+ # THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
4
+ # See included LICENCE file.
5
+
6
+ require 'dbc/ctokenizer'
7
+ require 'dbc/ctype'
8
+ require 'dbc/ocl'
9
+
10
+ module DBC
11
+ NONE = 0
12
+ PRE = 1
13
+ ALL = 2
14
+
15
+ def DBC.valid_check_level?(c)
16
+ case c
17
+ when NONE, PRE, ALL
18
+ true
19
+ else
20
+ false
21
+ end
22
+ end
23
+
24
+ def DBC.get_ocl(str)
25
+ str =~ /\A\/\*\*[ \t]*[\r\n]+(.+)[ \t]*\*\/\Z/m
26
+ $1
27
+ end
28
+
29
+ class Cache < CTokenizer::LexerBase
30
+ def initialize(str, file=nil, line=1)
31
+ super(str, file, line)
32
+ @token_cache = CTokenizer::Cache.new(super.file, super.line)
33
+ end
34
+
35
+ def shift
36
+ t = super
37
+ @token_cache << t
38
+ t
39
+ end
40
+
41
+ def reset
42
+ cache = @token_cache
43
+ @token_cache = CTokenizer::Cache.new(self.file, self.line)
44
+ cache
45
+ end
46
+ end
47
+
48
+ def DBC.parse(source)
49
+ tokens = CTokenizer::SkipMacros.new(source)
50
+ ctype_parser = CType::Parser.new()
51
+
52
+ until tokens.empty?
53
+ context = ctype_parser.parse(tokens)
54
+ f_body = false
55
+ unless tokens.scope == 0
56
+ yield([], f_body)
57
+ until tokens.scope == 0 or tokens.empty?
58
+ # get back to group zero
59
+ tokens.shift
60
+ end
61
+ f_body = true
62
+ end
63
+ yield(context, f_body)
64
+ end
65
+ end # DBC.parse
66
+
67
+ def DBC.format_conditions(conditions)
68
+ outstr = ''
69
+ conditions.each do |type, label, conds|
70
+ outstr << case type
71
+ when 'pre' then '\\pre'
72
+ when 'post' then '\\post'
73
+ when 'inv' then '\\invariant'
74
+ end << ' '
75
+ if label and not label.empty?
76
+ outstr << label << ': '
77
+ end
78
+ outstr << "\\code\n" << conds << "\n\\endcode\n"
79
+ end
80
+ outstr
81
+ end
82
+
83
+ # kinda ugly...
84
+ def DBC.parse_docs(tokens)
85
+ tokens = CTokenizer::SkipMacros.new(tokens)
86
+ ctype_parser = CType::Parser.new()
87
+ outstr = ''
88
+
89
+ until tokens.empty?
90
+ t = tokens.shift
91
+ # note: comments don't affect start_of_line?
92
+ if t[0] == :COMMENT and tokens.start_of_line? and str = DBC.get_ocl(t[1])
93
+ context = nil
94
+ # take out context information
95
+ str.gsub!(/^[ \t]*context[ \t]+(.+)$/) do
96
+ if context
97
+ source.error("multiple contexts given: '#{context.to_s}' and '#{$1}'")
98
+ end
99
+ context = ctype_parser.parse($1 << ';')
100
+ context = context.first
101
+ '' # replace with an empty string
102
+ end
103
+ conditions = []
104
+ str.scan(/^[ \t]*(pre|post|inv)[ \t]*([^:]*):|\Z/) do
105
+ conditions.push([$1, $2]) if $1
106
+ end
107
+ statements = str.split(/^[ \t]*(?:pre|post|inv)[^:]*:|\Z/)
108
+ statements.shift # remove first element
109
+ conditions.zip(statements) do |cond, stmt|
110
+ cond.push(stmt)
111
+ end
112
+ # condition is an array of arrays like so:
113
+ # [ ['pre', 'msg', 'statment'], ['post', 'msg', 'stmt'], ...]
114
+
115
+ doc_str = ''
116
+ # open Doxygen tag
117
+ doc_str << '/*!'
118
+ if context
119
+ doc_str << if context.function?
120
+ '\\fn' << context.to_init_s << "\n"
121
+ else
122
+ context = context.to_s
123
+ if context =~ /\A(?:struct|union|enum)\W/
124
+ '\\' << context << "\n"
125
+ else
126
+ '\\typedef' << context << "\n"
127
+ end
128
+ end
129
+ end
130
+ doc_str << DBC.format_conditions(conditions) << '*/'
131
+ # if no context is given and we have function
132
+ # try to insert the tag after then next opening braket
133
+ if conditions.first[0] =~ /pre|post/ and not context
134
+ until tokens.empty?
135
+ t = tokens.shift
136
+ outstr << t[1]
137
+ break if t[1] == '{'
138
+ end
139
+ end
140
+ outstr << doc_str
141
+ else
142
+ outstr << t[1]
143
+ end
144
+ end
145
+ outstr
146
+ end
147
+
148
+ class Parser < CTokenizer::LexerBase
149
+ include CTokenizer::Scoped
150
+ def initialize(str, file=nil, line=1)
151
+ super(str, file, line)
152
+ @token_cache = CTokenizer::Cache.new(super.file, super.line)
153
+ @scope = 0
154
+ @macro = false
155
+ @start_line = true # begining of file
156
+ end
157
+
158
+ def shift
159
+ process_scope(@token_cache.empty? ? super : @token_cache.shift)
160
+ end
161
+
162
+ def empty?
163
+ @token_cache.empty? and super
164
+ end
165
+
166
+ def file
167
+ if @token_cache.empty?
168
+ super
169
+ else
170
+ @token_cache.file
171
+ end
172
+ end
173
+
174
+ def line
175
+ if @token_cache.empty?
176
+ super
177
+ else
178
+ @token_cache.line
179
+ end
180
+ end
181
+
182
+ end # Parser
183
+
184
+ class OCLParser < Parser
185
+
186
+ def initialize(str, file=nil, line=1)
187
+ super(str, file, line)
188
+ @conditions = {}
189
+ @ctype_parser = CType::Parser.new()
190
+ end
191
+
192
+ attr_reader :conditions
193
+
194
+ def shift
195
+ t = super
196
+ # note: comments don't affect start_of_line?
197
+ if t[0] == :COMMENT and start_of_line? and ocl = DBC.get_ocl(t[1])
198
+ parse_ocl(ocl)
199
+ end
200
+ t
201
+ end
202
+
203
+ private
204
+ def parse_ocl(str)
205
+ self.error("no context for previous contract") \
206
+ unless @token_cache.empty?
207
+ count = CTokenizer.line_count(str)
208
+ parser = OCL::Parser.new(str, self.file, self.line - count)
209
+ self.error("no conditions given") if parser.conditions.empty?
210
+
211
+ unless parser.context
212
+ @token_cache.reset(self.file, self.line)
213
+ # Use the Splitter to cache the tokens used by the type parser
214
+ splitter = CTokenizer::Splitter.new(@token_cache, @source)
215
+ splitter = CTokenizer::SkipMacros.new(splitter)
216
+ context = @ctype_parser.parse(splitter)
217
+ self.error("multiple contexts given") unless context.length == 1
218
+ parser.context = context.first
219
+ end
220
+
221
+ if parser.conditions.last.type =~ /\A(?:pre|post)/
222
+ # should be followed by a function
223
+ self.error("pre and post conditions must be in the context of a function") \
224
+ unless parser.context.function?
225
+ end
226
+
227
+ context_str = if parser.context.class == String
228
+ parser.context
229
+ else
230
+ parser.context.short_name
231
+ end
232
+ @conditions[context_str] = parser
233
+ end
234
+ end # OCLParser
235
+
236
+ end # DBC
237
+
@@ -0,0 +1,302 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by racc 1.4.4
4
+ # from racc grammer file "src/define.y".
5
+ #
6
+
7
+ require 'racc/parser'
8
+
9
+
10
+
11
+ require 'dbc/parameters'
12
+ require 'dbc/parseerrorhandler'
13
+
14
+
15
+ module Preprocessor
16
+
17
+ class Define < Racc::Parser
18
+
19
+ module_eval <<'..end src/define.y modeval..id6f1b6c1f3b', 'src/define.y', 75
20
+
21
+ def initialize(params, tokens)
22
+ if params and not params.class == Parameters
23
+ @params = Parameters.new
24
+ params.each { |p| @params << p }
25
+ else
26
+ @params = params
27
+ end
28
+ @value = tokens.to_s
29
+ end
30
+
31
+ #attr_reader :file, :line
32
+
33
+ def takes_args?
34
+ @params != nil and not @params.empty?
35
+ end
36
+
37
+ # get the value of the macro
38
+ # 1) substitute macro function parameters if any
39
+ # note function parameters should NOT be resolved
40
+ # 2) stringify macro function parameters
41
+ # 3) concat tokens using ## operator
42
+ # 4) (happens after call to tokens) repeat 1) for each identifier
43
+ def value(stack)
44
+ if takes_args?
45
+ args = @params.get_args(stack)
46
+ end
47
+ evaluate(args)
48
+ end
49
+
50
+ def to_s
51
+ @value
52
+ end
53
+
54
+ def inspect
55
+ "\#<#{self.class}:#{self.to_s}>"
56
+ end
57
+
58
+ protected
59
+
60
+ def evaluate(args)
61
+ str = @value
62
+ @q = []
63
+ until str.empty?
64
+ @q << case str
65
+ # this works because all spaces, comments and newlines were
66
+ # replaced by a single space by the preprocessor
67
+ when /\A[ \t]*##[ \t]*/o
68
+ str = $'
69
+ ['##', $&].freeze
70
+ when /\A#[ \t]*/o
71
+ str = $'
72
+ ['#', '#'].freeze
73
+ else
74
+ token, str = CTokenizer.split_token(str)
75
+ if (args and token[0] == :IDENTIFIER and idx = @params.index(token[1]))
76
+ [:PARAMETER, args[idx]].freeze
77
+ else
78
+ token
79
+ end
80
+ end # case
81
+ end # until
82
+ @q << [false, false]
83
+ do_parse
84
+ end
85
+
86
+ include ParseErrorHandler
87
+
88
+ def next_token
89
+ @q.shift
90
+ end
91
+
92
+ ..end src/define.y modeval..id6f1b6c1f3b
93
+
94
+ ##### racc 1.4.4 generates ###
95
+
96
+ racc_reduce_table = [
97
+ 0, 0, :racc_error,
98
+ 1, 15, :_reduce_none,
99
+ 1, 15, :_reduce_none,
100
+ 0, 17, :_reduce_3,
101
+ 1, 16, :_reduce_4,
102
+ 2, 16, :_reduce_5,
103
+ 1, 18, :_reduce_none,
104
+ 1, 18, :_reduce_none,
105
+ 1, 18, :_reduce_none,
106
+ 1, 19, :_reduce_none,
107
+ 3, 19, :_reduce_10,
108
+ 1, 22, :_reduce_none,
109
+ 1, 22, :_reduce_none,
110
+ 1, 22, :_reduce_none,
111
+ 1, 22, :_reduce_none,
112
+ 1, 22, :_reduce_none,
113
+ 1, 22, :_reduce_none,
114
+ 1, 22, :_reduce_none,
115
+ 1, 22, :_reduce_none,
116
+ 1, 22, :_reduce_none,
117
+ 2, 21, :_reduce_20,
118
+ 1, 23, :_reduce_none,
119
+ 1, 20, :_reduce_none ]
120
+
121
+ racc_reduce_n = 23
122
+
123
+ racc_shift_n = 27
124
+
125
+ racc_action_table = [
126
+ 5, 6, 8, 10, 12, 14, 16, 18, 1, 23,
127
+ 4, 5, 6, 8, 10, 12, 14, 16, 18, 1,
128
+ 1, 4, 6, 8, 10, 12, 14, 16, 18, 1,
129
+ 24, 26, 21 ]
130
+
131
+ racc_action_check = [
132
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
133
+ 0, 9, 9, 9, 9, 9, 9, 9, 9, 9,
134
+ 4, 9, 23, 23, 23, 23, 23, 23, 23, 23,
135
+ 21, 23, 7 ]
136
+
137
+ racc_action_pointer = [
138
+ -3, nil, nil, nil, 9, nil, nil, 32, nil, 8,
139
+ nil, nil, nil, nil, nil, -3, nil, nil, nil, nil,
140
+ nil, 30, nil, 18, nil, nil, nil ]
141
+
142
+ racc_action_default = [
143
+ -3, -21, -9, -18, -19, -22, -11, -23, -17, -1,
144
+ -12, -2, -13, -4, -14, -6, -15, -7, -16, -8,
145
+ -20, -23, -5, -23, 27, -10, -19 ]
146
+
147
+ racc_goto_table = [
148
+ 13, 7, 11, 9, 25, 20, nil, nil, nil, 22 ]
149
+
150
+ racc_goto_check = [
151
+ 4, 1, 3, 2, 8, 9, nil, nil, nil, 4 ]
152
+
153
+ racc_goto_pointer = [
154
+ nil, 1, 3, 2, 0, nil, nil, nil, -19, 1 ]
155
+
156
+ racc_goto_default = [
157
+ nil, nil, nil, nil, nil, 15, 17, 19, 2, 3 ]
158
+
159
+ racc_token_table = {
160
+ false => 0,
161
+ Object.new => 1,
162
+ :STRINGIFY => 2,
163
+ :SPACE => 3,
164
+ :SYMBOL => 4,
165
+ :UNKNOWN => 5,
166
+ :CHARACTER => 6,
167
+ :STRING => 7,
168
+ :FLOAT => 8,
169
+ :INTEGER => 9,
170
+ :IDENTIFIER => 10,
171
+ :PARAMETER => 11,
172
+ "##" => 12,
173
+ "#" => 13 }
174
+
175
+ racc_use_result_var = true
176
+
177
+ racc_nt_base = 14
178
+
179
+ Racc_arg = [
180
+ racc_action_table,
181
+ racc_action_check,
182
+ racc_action_default,
183
+ racc_action_pointer,
184
+ racc_goto_table,
185
+ racc_goto_check,
186
+ racc_goto_default,
187
+ racc_goto_pointer,
188
+ racc_nt_base,
189
+ racc_reduce_table,
190
+ racc_token_table,
191
+ racc_shift_n,
192
+ racc_reduce_n,
193
+ racc_use_result_var ]
194
+
195
+ Racc_token_to_s_table = [
196
+ '$end',
197
+ 'error',
198
+ 'STRINGIFY',
199
+ 'SPACE',
200
+ 'SYMBOL',
201
+ 'UNKNOWN',
202
+ 'CHARACTER',
203
+ 'STRING',
204
+ 'FLOAT',
205
+ 'INTEGER',
206
+ 'IDENTIFIER',
207
+ 'PARAMETER',
208
+ '"##"',
209
+ '"#"',
210
+ '$start',
211
+ 'target',
212
+ 'token_sequence',
213
+ 'empty_target',
214
+ 'token',
215
+ 'token_expression',
216
+ 'white_space',
217
+ 'stringify_parameter',
218
+ 'basic_token',
219
+ 'parameter']
220
+
221
+ Racc_debug_parser = false
222
+
223
+ ##### racc system variables end #####
224
+
225
+ # reduce 0 omitted
226
+
227
+ # reduce 1 omitted
228
+
229
+ # reduce 2 omitted
230
+
231
+ module_eval <<'.,.,', 'src/define.y', 23
232
+ def _reduce_3( val, _values, result )
233
+ result = ''
234
+ result
235
+ end
236
+ .,.,
237
+
238
+ module_eval <<'.,.,', 'src/define.y', 27
239
+ def _reduce_4( val, _values, result )
240
+ result = val[0].dup
241
+ result
242
+ end
243
+ .,.,
244
+
245
+ module_eval <<'.,.,', 'src/define.y', 28
246
+ def _reduce_5( val, _values, result )
247
+ result = val[0] << val[1]
248
+ result
249
+ end
250
+ .,.,
251
+
252
+ # reduce 6 omitted
253
+
254
+ # reduce 7 omitted
255
+
256
+ # reduce 8 omitted
257
+
258
+ # reduce 9 omitted
259
+
260
+ module_eval <<'.,.,', 'src/define.y', 39
261
+ def _reduce_10( val, _values, result )
262
+ result = val[0] + val[2]
263
+ result
264
+ end
265
+ .,.,
266
+
267
+ # reduce 11 omitted
268
+
269
+ # reduce 12 omitted
270
+
271
+ # reduce 13 omitted
272
+
273
+ # reduce 14 omitted
274
+
275
+ # reduce 15 omitted
276
+
277
+ # reduce 16 omitted
278
+
279
+ # reduce 17 omitted
280
+
281
+ # reduce 18 omitted
282
+
283
+ # reduce 19 omitted
284
+
285
+ module_eval <<'.,.,', 'src/define.y', 56
286
+ def _reduce_20( val, _values, result )
287
+ result = "\"#{val[1]}\""
288
+ result
289
+ end
290
+ .,.,
291
+
292
+ # reduce 21 omitted
293
+
294
+ # reduce 22 omitted
295
+
296
+ def _reduce_none( val, _values, result )
297
+ result
298
+ end
299
+
300
+ end # class Define
301
+
302
+ end # module Preprocessor