-
Notifications
You must be signed in to change notification settings - Fork 0
/
parseutil.def
271 lines (247 loc) · 7.94 KB
/
parseutil.def
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
include: macros_parse/indentation.def
include: macros_parse/include.def
include: macros_parse/macros.def
include: macros_parse/subcode.def
include: macros_parse/template.def
include: macros_parse/default_page.def
include: macros_parse/hacks.def
include: macros_parse/debug.def
include: macros_util/path.def
include: macros_util/ogdl.def
include: macros_util/debug.def
include: perl/indentations.def
page: parseutil
type: pm
output_dir: lib/MyDef
package: MyDef::parseutil
1;
#----------------------------------------
fncode: import_data($file)
my $def={
"pages"=>{}, # pages hash
"pagelist"=>[], # pages list
# "codes"=>{}, # merged at end
"macros"=>{},
};
$call find_file
$call @parse_init
# ----
import_file($file, $def, "main")
$call load_standard_includes
$while 1
$if @includes
my $file=shift(@includes)
import_file($file, $def, "include")
$elif @standard_includes
my $file=shift(@standard_includes)
import_file($file, $def, "standard_include")
$else
last
# ----
$call @post_parsing
return $def;
# -----------------------------
subcode: find_file
$if $file=~/([^\/]+)\.def/
$def->{_defname}=$1
$def->{_deffile}=find_file($file)
$else
$def->{_defname}="default"
$if $file=~/(.*)\//
$def->{_srcdir}=$1
unshift @path, $1
#------------------------------
fncode: import_file($f, $def, $file_type)
$call @debug_import
#---- import a single def file, update @include-----
my $plines=get_lines($f);
$if !$plines
return
push @$plines, "END" # needed to flush indentations
# ------------------------
$call @import_file_init
&call parse_loop
$call get_multiline_comment
$call get_indentation, filter
$call @check_indent
$call parse_switch
$call @import_file_finish
# ------------------------
subcode: check_indent
$call check_end_codeindent
$if $(in_code)
$call get_source_indent, $curindent
$call update_source_pos
$call get_source_dedent, $curindent
subcode: parse_switch
$if $line=~/^\w+code:/ && $(top_scope)
$call subcode_start
$call start_code_indent, code, $curindent+1, $t_code
$elif $line=~/^macros:/ && $(top_scope)
$call macros_start
$call start_code_indent, macro, $curindent+1, $macros
$elif $line=~/^template:/ && $(top_scope)
$call grab_template
$elif $line=~/^output_dir:\s*(.+)/
$MyDef::var->{output_dir}=$1
$call @parse_switch_include
$elif $curindent==0 and $line=~/^page:\s*(.*)/ -> $t
$call start_page
$elif $curindent==0 and $line=~/^DEBUG\s*(.*)/
parse_DEBUG($1)
$elif $(in_code)
$if $line=~/^\$template\s+(.+)/
my $name = parse_template($def, $1)
$line = "\$call $name"
$call @push_line_to_source
$elif $(in_macro)
$call process_macros
$else
# $print codetype:$codetype, codeindent:$codeindent [$line]
subcode: parse_loop
# sub-used in parsing multi-line comments and grabing templates/resources
$(allow_recurse:2)
$while $cur_line < @$plines
my $line = $plines->[$cur_line]
$cur_line++
BLOCK
subcode: grab_template
my @grab
$if $line =~ /^template:\s*(\w+)/
$call add_subcode, \@grab, "template", $1
$else
warn "parseutil: template missing name\n"
my $grab_indent=$curindent
&call parse_loop
$call get_indentation, template
$if $line eq ""
push @grab, $line
$elif $curindent>$grab_indent
push @grab, ' 'x($curindent-$grab_indent-1) . $line
$else
last
$cur_line--
#----------------------------------------
subcode: start_page
$call @abort_default_page
my ($pagename, $frame)
$call parse_page_line
$call new_page
$call start_code_indent, page, 1, $page
$if $file_type eq "main"
$call add_page
$call @check_page_macros
$call jump_to_main_code
$call start_code_indent, code, 1, $_t
# ------------------------
subcode: parse_page_line
$if $t=~/([\w\-\$\.]+),\s*(\w.*|-)/
$pagename=$1;
$frame=$2;
$if $frame=~/^from\s+(\S+)/
$frame= parse_template($def, $1)
$elif $t=~/([\w\-\$\.]+)/
$pagename=$1;
subcode: new_page
my $page={_pagename=>$pagename}
$if $frame
$page->{_frame}=$frame
subcode: check_page_macros
my $sp
&call parse_loop
$if $line=~/^(\s+)(?:#|(\w+):\s*(.*))/
$if !$sp
$sp=$1
$elif $sp ne $1
last
my ($k, $v)=($2,$3)
$if $k=~/^(macros|\w+code|template)$/
last
$call add_macro
$else
$if $line=~/^$/
# skip the first empty line
$cur_line++
last
$cur_line--
subcode: add_macro
expand_macro(\$v, $macros);
$page->{$k}=$v;
#----------------------------------------
#-- used here and macros_parse/hacks.def: dupe_page
subcode: add_page
# ---- insert into pages
$call @check_duplicate
$pages->{$pagename}=$page;
push @$pagelist, $pagename
subcode: check_duplicate
$if $pages->{$pagename}
my $t=$pagename;
my $j=0;
$while $pages->{$pagename}
$j++;
$pagename=$t.$j;
#----------------------------------------
subcode:: import_file_init
my $cur_file=$f
my $cur_line=0
my $line_skipped=0
my @last_multiline_comments # in case it's function doc
subcode: get_multiline_comment
# multiline_comments, Note: we are more strict than the C comments.
$if $line=~/^\s*\/\*/
@last_multiline_comments = ($line)
$if $line !~ /\*\/\s*$/
&call parse_loop
push @last_multiline_comments, $line
$if $line=~/\*\/\s*$/
last
$line_skipped=1
next
$elif @last_multiline_comments and $line!~/^fncode:/
undef @last_multiline_comments
subcode: get_indentation(filter)
$if $line=~/^\s*$/
# sometime empty lines are significant, passes on, where compileutil will filter
$line="NEWLINE?"
$elif $line=~/^(\s*)(.*)/
# get current indentation and stripping starting spaces
# ref: deflib/perl/indentations.def
my $indent=get_indent($1)
$line=$2
$(if:filter=filter)
$call filter_comment
$curindent=$indent
subcode: filter_comment
$if $line=~/^#(?!(define|undef|include|line|error|pragma|if|ifdef|ifndef|elif|else|endif)\b)/
# Leading # with exclusions
$if $line=~/^#\\n/
$line="NEWLINE?"
$elif $indent != $curindent
$line="NOOP"
$else
$line_skipped=1
next
$else
# Trim the tail
$line=~s/\s+$//
# Tail # need spaces before and after!
$line=~s/\s+#\s.*$//
#---- utils ------------------------------------
fncode: get_lines($file)
$if ref($file) eq "ARRAY"
return $file
$elif $file eq "-pipe"
my @lines=<STDIN>
return \@lines
$else
my $filename=find_file($file)
$if $filename
my @lines
&call open_r, $filename
$if /^# cut ----+\s*$/
last
$else
push @lines, $_
return \@lines;
return undef