dbc 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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