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.
- data/bin/dbcparse.rb +281 -0
- data/lib/dbc/ctokenizer.rb +379 -0
- data/lib/dbc/ctype.rb +2397 -0
- data/lib/dbc/dbc.rb +237 -0
- data/lib/dbc/define.rb +302 -0
- data/lib/dbc/expand_function.rb +132 -0
- data/lib/dbc/ocl.rb +2166 -0
- data/lib/dbc/parameters.rb +400 -0
- data/lib/dbc/parseerrorhandler.rb +19 -0
- data/lib/dbc/preprocessor.rb +1790 -0
- data/lib/dbc/searchpath.rb +40 -0
- metadata +49 -0
data/lib/dbc/dbc.rb
ADDED
@@ -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
|
+
|
data/lib/dbc/define.rb
ADDED
@@ -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
|