stats_package_syntax_file_generator 1.1.3 → 1.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/syntax_file/controller.rb +221 -213
- data/lib/syntax_file/maker.rb +96 -91
- data/lib/syntax_file/maker_rddi.rb +55 -55
- data/lib/syntax_file/maker_sas.rb +205 -204
- data/lib/syntax_file/maker_spss.rb +144 -143
- data/lib/syntax_file/maker_stata.rb +211 -211
- data/lib/syntax_file/maker_sts.rb +120 -120
- data/lib/syntax_file/value.rb +16 -15
- data/lib/syntax_file/variable.rb +41 -40
- data/tests/setup.rb +8 -8
- data/tests/tc_maker.rb +1 -1
- data/tests/tc_maker_stata.rb +1 -1
- metadata +13 -12
data/lib/syntax_file/maker.rb
CHANGED
@@ -4,123 +4,128 @@
|
|
4
4
|
# https://github.com/mnpopcenter/stats_package_syntax_file_generator
|
5
5
|
|
6
6
|
module SyntaxFile
|
7
|
-
|
7
|
+
class Maker
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
attr_reader :sfc, :syntax_type
|
10
|
+
attr_accessor :cmd_end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def initialize (sfc, syntax_type)
|
13
|
+
@sfc = sfc
|
14
|
+
@syntax_type = syntax_type
|
15
|
+
@cmd_end = ''
|
16
|
+
end
|
17
17
|
|
18
|
-
# Syntax terminator.
|
19
18
|
|
20
|
-
|
21
|
-
[@cmd_end, blank]
|
22
|
-
end
|
19
|
+
# Syntax terminator.
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
def syntax_end
|
22
|
+
[ @cmd_end, blank ]
|
23
|
+
end
|
27
24
|
|
28
|
-
|
25
|
+
def blank
|
26
|
+
''
|
27
|
+
end
|
29
28
|
|
30
|
-
def q(s)
|
31
|
-
'"' + s.to_s.gsub('"', '""') + '"'
|
32
|
-
end
|
33
29
|
|
34
|
-
|
35
|
-
var.is_string_var ? q(v) : v.to_s
|
36
|
-
end
|
30
|
+
# Quoting methods.
|
37
31
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
# - String variable: zero-pad the value if it looks like an integer.
|
42
|
-
v = val_orig.to_s
|
43
|
-
return v unless var.is_string_var
|
44
|
-
return v unless v =~ /^\-?\d+$/
|
45
|
-
sprintf('%0' + var.width.to_s + 'i', v.to_i)
|
46
|
-
end
|
32
|
+
def q (s)
|
33
|
+
'"' + s.to_s.gsub('"', '""') + '"'
|
34
|
+
end
|
47
35
|
|
48
|
-
|
36
|
+
def val_q (var, v)
|
37
|
+
var.is_string_var ? q(v) : v.to_s
|
38
|
+
end
|
49
39
|
|
50
|
-
|
51
|
-
|
52
|
-
|
40
|
+
def val_as_s (var, val_orig)
|
41
|
+
# Write a value in a syntax file varies by variable type:
|
42
|
+
# - Numeric variable: simply return the value as a string.
|
43
|
+
# - String variable: zero-pad the value if it looks like an integer.
|
44
|
+
v = val_orig.to_s
|
45
|
+
return v unless var.is_string_var
|
46
|
+
return v unless v =~ /^\-?\d+$/
|
47
|
+
sprintf('%0' + var.width.to_s + 'i', v.to_i)
|
48
|
+
end
|
53
49
|
|
54
|
-
def label_segments(label, max_length)
|
55
|
-
# Takes a string and a max length.
|
56
|
-
# Returns the array of strings that results from chopping the
|
57
|
-
# original string into segments no longer than max length.
|
58
|
-
# This is needed because some stats packages have max line lengths.
|
59
|
-
label = label.to_s
|
60
|
-
return [label] if label.length <= max_length
|
61
|
-
label = String.new(label)
|
62
|
-
r = []
|
63
|
-
r.push(label.slice!(0, max_length)) while label.length > 0
|
64
|
-
r
|
65
|
-
end
|
66
50
|
|
67
|
-
|
68
|
-
# The function takes a sprintf format, two lists (a, b), and
|
69
|
-
# two strings (the assignment and concatenation operators used
|
70
|
-
# by the stats package). The purpose of the function is to handle
|
71
|
-
# long values and labels for stats packages that have a max syntax
|
72
|
-
# line length. See unit tests for an illustration.
|
73
|
-
r = []
|
74
|
-
r.push(sprintf(fmt, a.shift, op_c, '')) while a.size > 1
|
75
|
-
r.push(sprintf(fmt, a.shift, op_a, b.shift))
|
76
|
-
r.push(sprintf(fmt, '', op_c, b.shift)) while b.size > 0
|
77
|
-
r
|
78
|
-
end
|
51
|
+
# Methods to deal with long labels.
|
79
52
|
|
80
|
-
|
53
|
+
def label_trunc (label, limit)
|
54
|
+
label.to_s[0,limit]
|
55
|
+
end
|
81
56
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
57
|
+
def label_segments (label, max_length)
|
58
|
+
# Takes a string and a max length.
|
59
|
+
# Returns the array of strings that results from chopping the
|
60
|
+
# original string into segments no longer than max length.
|
61
|
+
# This is needed because some stats packages have max line lengths.
|
62
|
+
label = label.to_s
|
63
|
+
return [label] if label.length <= max_length
|
64
|
+
label = String.new(label)
|
65
|
+
r = []
|
66
|
+
r.push( label.slice!(0,max_length) ) while label.length > 0
|
67
|
+
r
|
68
|
+
end
|
69
|
+
|
70
|
+
def weave_label_segments (fmt, a, b, op_a, op_c)
|
71
|
+
# The function takes a sprintf format, two lists (a, b), and
|
72
|
+
# two strings (the assignment and concatenation operators used
|
73
|
+
# by the stats package). The purpose of the function is to handle
|
74
|
+
# long values and labels for stats packages that have a max syntax
|
75
|
+
# line length. See unit tests for an illustration.
|
76
|
+
r = []
|
77
|
+
r.push(sprintf(fmt, a.shift, op_c, '' )) while a.size > 1
|
78
|
+
r.push(sprintf(fmt, a.shift, op_a, b.shift))
|
79
|
+
r.push(sprintf(fmt, '', op_c, b.shift)) while b.size > 0
|
80
|
+
r
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Helper methods for values and their labels.
|
85
|
+
|
86
|
+
def labelable_values (var)
|
87
|
+
# For non-string variables, only values that look
|
88
|
+
# like integers can be labeled.
|
89
|
+
return var.values if var.is_string_var
|
90
|
+
var.values.find_all { |val| val.value.to_s =~ /^\-?\d+$/ }
|
91
|
+
end
|
92
|
+
|
93
|
+
def max_value_length (var, val_list)
|
94
|
+
return 0 if val_list.empty?
|
95
|
+
val_list.map { |val| val_as_s(var, val.value).length }.max
|
96
|
+
end
|
88
97
|
|
89
|
-
def max_value_length(var, val_list)
|
90
|
-
return 0 if val_list.empty?
|
91
|
-
val_list.map { |val| val_as_s(var, val.value).length }.max
|
92
|
-
end
|
93
98
|
|
94
|
-
|
99
|
+
# Methods for comments at the start or end of the syntax file.
|
95
100
|
|
96
|
-
|
97
|
-
|
98
|
-
|
101
|
+
def comments_start
|
102
|
+
# Comments not needed unless syntax file is for the web app.
|
103
|
+
return [] unless @sfc.caller == 'web_app'
|
99
104
|
|
100
|
-
|
105
|
+
return [
|
101
106
|
'NOTE: You need to set the Stata working directory to the path',
|
102
107
|
'where the data file is located.',
|
103
|
-
|
104
|
-
|
105
|
-
|
108
|
+
] if @syntax_type == 'stata'
|
109
|
+
|
110
|
+
return [
|
106
111
|
"NOTE: To load data, you must download both the extract's data and the DDI",
|
107
112
|
"and also set the working directory to the folder with these files (or change the path below).",
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
113
|
+
] if @syntax_type == 'rddi'
|
114
|
+
|
115
|
+
cmd = (@syntax_type == 'sas') ? 'libname' : 'cd'
|
116
|
+
result = [
|
112
117
|
"NOTE: You need to edit the `#{cmd}` command to specify the path to the directory",
|
113
118
|
'where the data file is located. For example: "C:\ipums_directory".'
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
118
|
-
result
|
119
|
+
]
|
120
|
+
if @syntax_type == 'sas'
|
121
|
+
result << "Edit the `filename` command similarly to include the full path (the directory and the data file name)."
|
119
122
|
end
|
123
|
+
result
|
124
|
+
end
|
120
125
|
|
121
|
-
|
122
|
-
|
123
|
-
|
126
|
+
def comments_end
|
127
|
+
[]
|
128
|
+
end
|
124
129
|
|
125
|
-
|
130
|
+
end
|
126
131
|
end
|
@@ -1,55 +1,55 @@
|
|
1
|
-
# This file is part of the Minnesota Population Center's stats_package_syntax_file_generator project.
|
2
|
-
# For copyright and licensing information, see the NOTICE and LICENSE files
|
3
|
-
# in this project's top-level directory, and also on-line at:
|
4
|
-
# https://github.com/mnpopcenter/stats_package_syntax_file_generator
|
5
|
-
|
6
|
-
module SyntaxFile
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
comments_start,
|
16
|
-
check_pkg,
|
17
|
-
syn_df,
|
18
|
-
comments_end,
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
lines.map { |ln| '# ' + ln },
|
35
|
-
blank,
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
'if (!require("ipumsr")) stop("Reading IPUMS data into R requires the ipumsr package. It can be installed using the following command: install.packages(\'ipumsr\')")',
|
42
|
-
''
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
'ddi <- read_ipums_ddi(' + q(ddi_file) + ')',
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
1
|
+
# This file is part of the Minnesota Population Center's stats_package_syntax_file_generator project.
|
2
|
+
# For copyright and licensing information, see the NOTICE and LICENSE files
|
3
|
+
# in this project's top-level directory, and also on-line at:
|
4
|
+
# https://github.com/mnpopcenter/stats_package_syntax_file_generator
|
5
|
+
|
6
|
+
module SyntaxFile
|
7
|
+
class MakerRDDI < Maker
|
8
|
+
|
9
|
+
def initialize (sfc, syntax_type)
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def syntax
|
14
|
+
r = [
|
15
|
+
comments_start,
|
16
|
+
check_pkg,
|
17
|
+
syn_df,
|
18
|
+
comments_end,
|
19
|
+
]
|
20
|
+
r.flatten
|
21
|
+
end
|
22
|
+
|
23
|
+
def comments_start
|
24
|
+
convert_to_comments(super)
|
25
|
+
end
|
26
|
+
|
27
|
+
def comments_end
|
28
|
+
convert_to_comments(super)
|
29
|
+
end
|
30
|
+
|
31
|
+
def convert_to_comments (lines)
|
32
|
+
return [] if lines.empty?
|
33
|
+
[
|
34
|
+
lines.map { |ln| '# ' + ln },
|
35
|
+
blank,
|
36
|
+
].flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_pkg
|
40
|
+
[
|
41
|
+
'if (!require("ipumsr")) stop("Reading IPUMS data into R requires the ipumsr package. It can be installed using the following command: install.packages(\'ipumsr\')")',
|
42
|
+
''
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
def syn_df
|
47
|
+
ddi_file = @sfc.data_file_name.chomp[0...-3] + 'xml'
|
48
|
+
[
|
49
|
+
'ddi <- read_ipums_ddi(' + q(ddi_file) + ')',
|
50
|
+
'data <- read_ipums_micro(ddi)',
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -4,27 +4,27 @@
|
|
4
4
|
# https://github.com/mnpopcenter/stats_package_syntax_file_generator
|
5
5
|
|
6
6
|
module SyntaxFile
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
7
|
+
class MakerSAS < Maker
|
8
|
+
|
9
|
+
def initialize (sfc, syntax_type)
|
10
|
+
super
|
11
|
+
m = @sfc.max_var_name_length
|
12
|
+
@var_loc_format = " %-#{m}s "
|
13
|
+
@var_lab_format = " %-#{m}s %s %s"
|
14
|
+
@fmt_link_format = " %-#{m}s %s."
|
15
|
+
@bignum_int_format = " %-#{m}s %d."
|
16
|
+
@bignum_dec_format = " %-#{m}s %d.%d"
|
17
|
+
@cmd_end = ';'
|
18
|
+
@label_max_leng = 256
|
19
|
+
@segment_max_leng = 100
|
20
|
+
@sas_library_handle = 'IPUMS'
|
21
|
+
@sas_file_handle = 'ASCIIDAT'
|
22
|
+
@sas_fmt_suffix = '_f'
|
23
|
+
@sas_data_file_name = @sas_library_handle + '.' + @sfc.data_file_name_stem
|
24
|
+
end
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
def syntax
|
27
|
+
r = [
|
28
28
|
comments_start,
|
29
29
|
syn_libname,
|
30
30
|
syn_filename,
|
@@ -36,270 +36,271 @@ module SyntaxFile
|
|
36
36
|
syn_fmt_big_nums,
|
37
37
|
syn_run,
|
38
38
|
comments_end,
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
]
|
40
|
+
r.flatten!
|
41
|
+
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
def comments_start
|
44
|
+
convert_to_comments(super)
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
def comments_end
|
48
|
+
convert_to_comments(super)
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def convert_to_comments (lines)
|
52
|
+
return [] if lines.empty?
|
53
|
+
[
|
54
54
|
'/*',
|
55
55
|
lines.map { |ln| ' ' + ln },
|
56
56
|
'*/',
|
57
57
|
blank,
|
58
|
-
|
59
|
-
|
58
|
+
].flatten
|
59
|
+
end
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
def syn_libname
|
62
|
+
'libname ' + @sas_library_handle + ' ' + q(@sfc.data_dir_name) + @cmd_end
|
63
|
+
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
def syn_filename
|
66
|
+
'filename ' + @sas_file_handle + ' ' + q(@sfc.data_file_name) + @cmd_end
|
67
|
+
end
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
def syn_val_labs
|
70
|
+
var_list = @sfc.get_vars_with_values
|
71
|
+
return [] if var_list.empty?
|
72
|
+
r = [
|
73
73
|
syn_proc_format,
|
74
74
|
blank,
|
75
75
|
syn_val_labs_for_var_list(var_list),
|
76
76
|
syn_run,
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
]
|
78
|
+
r.flatten!
|
79
|
+
end
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
def syn_proc_format
|
82
|
+
'proc format cntlout = ' + @sas_data_file_name + @sas_fmt_suffix + @cmd_end
|
83
|
+
end
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
def syn_val_labs_for_var_list (var_list)
|
86
|
+
r = []
|
87
|
+
var_list.each do |var|
|
88
88
|
r.push syn_val_labs_for_var_start(var)
|
89
89
|
r.push syn_val_labs_for_var(var)
|
90
90
|
r.push syntax_end
|
91
|
-
end
|
92
|
-
r.flatten!
|
93
91
|
end
|
92
|
+
r.flatten!
|
93
|
+
end
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
def syn_val_labs_for_var_start (var)
|
96
|
+
'value' +
|
97
|
+
(var.is_string_var ? ' $ ' : ' ') +
|
98
|
+
var.name +
|
99
|
+
@sas_fmt_suffix
|
100
|
+
end
|
101
101
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
102
|
+
def syn_val_labs_for_var (var)
|
103
|
+
val_list = labelable_values(var)
|
104
|
+
return [] if val_list.empty?
|
105
|
+
m = max_value_length(var, val_list)
|
106
|
+
m = m + 2 if var.is_string_var
|
107
|
+
m = @segment_max_leng + 2 if m > @segment_max_leng + 2
|
108
|
+
fmt = " %-#{m}s %s %s"
|
109
|
+
r = val_list.collect { |val| syn_val_lab_for_val(var, val, fmt) }
|
110
|
+
r.flatten!
|
111
|
+
end
|
112
112
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
def syn_val_lab_for_val (var, val, fmt)
|
114
|
+
lab = label_trunc(val.label, @label_max_leng)
|
115
|
+
lab = val.value if lab.nil? || (lab.strip.length == 0)
|
116
|
+
vs = val_as_s(var, val.value)
|
117
|
+
val_segments = label_segments(vs, @segment_max_leng).map { |s| val_q(var, s) }
|
118
|
+
lab_segments = label_segments(lab, @segment_max_leng).map { |s| q(s) }
|
119
|
+
weave_label_segments(fmt, val_segments, lab_segments, '=', ' ')
|
120
|
+
end
|
121
121
|
|
122
|
-
|
123
|
-
|
124
|
-
|
122
|
+
def syn_run
|
123
|
+
[ 'run' + @cmd_end, blank ]
|
124
|
+
end
|
125
125
|
|
126
|
-
|
127
|
-
|
126
|
+
def syn_df
|
127
|
+
r = [
|
128
128
|
syn_df_start,
|
129
129
|
syn_df_infile,
|
130
130
|
blank,
|
131
131
|
@sfc.data_structure == 'hier' ? syn_dfh : syn_dfr,
|
132
|
-
|
133
|
-
|
134
|
-
|
132
|
+
]
|
133
|
+
r.flatten!
|
134
|
+
end
|
135
135
|
|
136
|
-
|
137
|
-
|
138
|
-
|
136
|
+
def syn_df_start
|
137
|
+
'data ' + @sas_data_file_name + @cmd_end
|
138
|
+
end
|
139
139
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
140
|
+
def syn_df_infile
|
141
|
+
# The LRECL specification is needed because the default behavior on some
|
142
|
+
# operating systems is to truncate records to 256 columns.
|
143
|
+
c = @sfc.last_column_used
|
144
|
+
'infile ' + @sas_file_handle + ' pad missover lrecl=' + c.to_s + @cmd_end
|
145
|
+
end
|
146
146
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
147
|
+
def syn_dfr
|
148
|
+
r = syn_input(@sfc.variables)
|
149
|
+
r.push blank
|
150
|
+
r
|
151
|
+
end
|
152
152
|
|
153
|
-
|
154
|
-
|
153
|
+
def syn_input (var_list)
|
154
|
+
r = [
|
155
155
|
'input',
|
156
156
|
syn_var_locations(var_list),
|
157
157
|
@cmd_end,
|
158
|
-
|
159
|
-
|
160
|
-
|
158
|
+
]
|
159
|
+
r.flatten!
|
160
|
+
end
|
161
161
|
|
162
|
-
|
163
|
-
|
164
|
-
sprintf(@var_loc_format, v.name) +
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
162
|
+
def syn_var_locations (var_list)
|
163
|
+
var_list.collect { |v|
|
164
|
+
sprintf( @var_loc_format, v.name ) +
|
165
|
+
(v.is_string_var ? '$ ' : ' ') +
|
166
|
+
v.column_locations_as_s +
|
167
|
+
implied_decimal_fmt(v)
|
168
|
+
}
|
169
|
+
end
|
170
170
|
|
171
|
-
|
172
|
-
|
171
|
+
def syn_dfh
|
172
|
+
r = [
|
173
173
|
syn_dfh_retain,
|
174
174
|
syn_dfh_rec_type_block,
|
175
175
|
blank,
|
176
176
|
syn_dfh_if_blocks,
|
177
|
-
|
178
|
-
|
179
|
-
|
177
|
+
]
|
178
|
+
r.flatten!
|
179
|
+
end
|
180
180
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
181
|
+
def syn_dfh_retain
|
182
|
+
return [] unless @sfc.rectangularize
|
183
|
+
var_list = non_last_non_common_vars
|
184
|
+
return [] if var_list.size == 0
|
185
|
+
r = [
|
186
186
|
'retain',
|
187
187
|
var_list.map { |var| ' ' + var.name },
|
188
188
|
syntax_end,
|
189
|
-
|
190
|
-
|
191
|
-
|
189
|
+
]
|
190
|
+
r.flatten!
|
191
|
+
end
|
192
192
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
193
|
+
def syn_dfh_rec_type_block
|
194
|
+
r = syn_input( [@sfc.record_type_var])
|
195
|
+
r[1] = r[1] + ' @'
|
196
|
+
r
|
197
|
+
end
|
198
198
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
199
|
+
def syn_dfh_if_blocks
|
200
|
+
if_cmd = 'if'
|
201
|
+
r = []
|
202
|
+
@sfc.record_types.each do |rt|
|
203
203
|
r.push(
|
204
|
-
|
205
|
-
|
206
|
-
|
204
|
+
syn_dfh_if_start(if_cmd, rt),
|
205
|
+
syn_input( @sfc.get_vars_by_record_type(rt) ),
|
206
|
+
syn_dfh_if_end(rt)
|
207
207
|
)
|
208
208
|
if_cmd = 'else if'
|
209
|
-
end
|
210
|
-
r.flatten!
|
211
209
|
end
|
210
|
+
r.flatten!
|
211
|
+
end
|
212
212
|
|
213
|
-
|
214
|
-
|
215
|
-
|
213
|
+
def syn_dfh_if_start (if_cmd, rt)
|
214
|
+
rt_var = @sfc.record_type_var
|
215
|
+
r = [
|
216
216
|
if_cmd,
|
217
217
|
@sfc.record_type_var.name,
|
218
218
|
'=',
|
219
219
|
val_q(rt_var, val_as_s(rt_var, rt)),
|
220
220
|
'then do' + @cmd_end,
|
221
|
-
|
222
|
-
|
223
|
-
|
221
|
+
]
|
222
|
+
r.join(' ')
|
223
|
+
end
|
224
224
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
225
|
+
def syn_dfh_if_end (rt)
|
226
|
+
r = []
|
227
|
+
r.push 'output' + @cmd_end if (not @sfc.rectangularize) or @sfc.is_last_record_type(rt)
|
228
|
+
r.push 'end' + @cmd_end
|
229
|
+
r.push blank
|
230
|
+
r
|
231
|
+
end
|
232
232
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
233
|
+
def syn_var_labs
|
234
|
+
var_list = @sfc.get_vars_with_var_labels
|
235
|
+
return [] if var_list.empty?
|
236
|
+
r = [
|
237
237
|
'label',
|
238
238
|
var_list.map { |var| syn_var_lab_for_var(var) },
|
239
239
|
syntax_end,
|
240
|
-
|
241
|
-
|
242
|
-
|
240
|
+
]
|
241
|
+
r.flatten!
|
242
|
+
end
|
243
243
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
244
|
+
def syn_var_lab_for_var (var)
|
245
|
+
lab = label_trunc(var.label, @label_max_leng)
|
246
|
+
lab_segments = label_segments(lab, @segment_max_leng).map { |s| q(s) }
|
247
|
+
weave_label_segments(@var_lab_format, [var.name], lab_segments, '=', ' ')
|
248
|
+
end
|
249
249
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
250
|
+
def syn_fmt_big_nums
|
251
|
+
big_num_vars = @sfc.get_big_nums
|
252
|
+
return [] if big_num_vars.empty?
|
253
|
+
r = [
|
254
254
|
'format',
|
255
255
|
syn_fmt_big_nums_for_var_list(big_num_vars),
|
256
256
|
syntax_end,
|
257
|
-
|
258
|
-
|
259
|
-
|
257
|
+
]
|
258
|
+
r.flatten!
|
259
|
+
end
|
260
260
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
end
|
268
|
-
end
|
261
|
+
def syn_fmt_big_nums_for_var_list (var_list)
|
262
|
+
var_list.map do |v|
|
263
|
+
if v.implied_decimals > 0
|
264
|
+
sprintf @bignum_dec_format, v.name, v.width + 1, v.implied_decimals
|
265
|
+
else
|
266
|
+
sprintf @bignum_int_format, v.name, v.width
|
269
267
|
end
|
268
|
+
end
|
269
|
+
end
|
270
270
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
271
|
+
|
272
|
+
def syn_fmt_link
|
273
|
+
var_list = @sfc.get_vars_with_values
|
274
|
+
return [] if var_list.empty?
|
275
|
+
r = [
|
275
276
|
'format',
|
276
277
|
syn_fmt_link_for_var_list(var_list),
|
277
278
|
syntax_end,
|
278
|
-
|
279
|
-
|
280
|
-
|
279
|
+
]
|
280
|
+
r.flatten!
|
281
|
+
end
|
281
282
|
|
282
|
-
|
283
|
-
|
283
|
+
def syn_fmt_link_for_var_list (var_list)
|
284
|
+
var_list.map { |v|
|
284
285
|
sprintf @fmt_link_format, v.name, v.name + @sas_fmt_suffix
|
285
|
-
|
286
|
-
|
286
|
+
}
|
287
|
+
end
|
287
288
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
289
|
+
def implied_decimal_fmt (var)
|
290
|
+
return '' if var.is_string_var or var.implied_decimals == 0
|
291
|
+
return ' .' + var.implied_decimals.to_s
|
292
|
+
end
|
292
293
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
294
|
+
def non_last_non_common_vars
|
295
|
+
# Returns a list of variables, excluding:
|
296
|
+
# - variables from the last record type
|
297
|
+
# - common variables
|
298
|
+
var_list = @sfc.rec_types_except_last.map do |rt|
|
298
299
|
vars = @sfc.get_vars_by_record_type(rt)
|
299
300
|
vars.find_all { |var| not var.is_common_var }
|
300
|
-
end
|
301
|
-
var_list.flatten!
|
302
301
|
end
|
302
|
+
var_list.flatten!
|
303
|
+
end
|
303
304
|
|
304
|
-
|
305
|
+
end
|
305
306
|
end
|