stats_package_syntax_file_generator 1.1.3 → 1.1.6
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.
- 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
|