function mgfffortemplate::getVariable, name, found=found
compile_opt strictarr
found = 0B
if (size(name, /type) ne 7) then return, -1L
if (strupcase(name) eq strupcase(self.name)) then begin
found = 1B
return, *self.value
endif else return, -1L
end
pro mgfffortemplate::setVariable, value
compile_opt strictarr
*self.value = value
end
pro mgfffortemplate::cleanup
compile_opt strictarr
ptr_free, self.value
end
function mgfffortemplate::init, name, value
compile_opt strictarr
self.name = name
self.value = ptr_new(value)
return, 1L
end
pro mgfffortemplate__define
compile_opt strictarr
define = { mgfffortemplate, $
name: '', $
value: ptr_new() $
}
end
function mgffcompoundtemplate::getVariable, name, found=found
compile_opt strictarr
on_error, 2
if (size(name, /type) ne 7) then begin
found = 0B
return, -1L
endif
if (obj_valid(self.template1)) then begin
val = self.template1->getVariable(name, found=found)
endif else found = 0B
if (found) then begin
return, val
endif else begin
if (size(*self.template2, /type) eq 11) then begin
if (obj_valid(*self.template2)) then begin
val = (*self.template2)->getVariable(name, found=found)
return, found ? val : -1L
endif else begin
found = 0B
return, -1L
endelse
endif else if (size(*self.template2, /type) eq 8) then begin
ind = where(tag_names(*self.template2) eq strupcase(name), count)
if (count eq 0) then begin
found = 0B
return, -1L
endif else begin
found = 1B
return, (*self.template2).(ind[0])
endelse
endif
endelse
end
pro mgffcompoundtemplate::cleanup
compile_opt strictarr
ptr_free, self.template2
end
function mgffcompoundtemplate::init, template1, template2
compile_opt strictarr
on_error, 2
if (size(template1, /type) ne 11) then begin
message, 'invalid type for template1: ' + size(template1, /tname)
endif
type = size(template2, /type)
if (type ne 8 && type ne 11) then begin
message, 'invalid type for template2: ' + size(template2, /tname)
endif
self.template1 = template1
self.template2 = ptr_new(template2)
return, 1
end
pro mgffcompoundtemplate__define
compile_opt strictarr
define = { mgffcompoundtemplate, $
template1: obj_new(), $
template2: ptr_new() $
}
end
pro mgfftemplate::_printf, lun, data, _extra=e
compile_opt strictarr
on_error, 2
if (lun eq -3) then return else begin
if (n_elements(data) gt 1) then begin
if (size(data, /type) eq 10) then begin
for i = 0L, n_elements(data) - 1L do begin
self->_printf, lun, (*data)[i], _extra=e
endfor
endif else begin
printf, lun, transpose(data), _extra=e
endelse
endif else begin
if (size(data, /type) eq 10) then begin
self->_printf, lun, *data, _extra=e
endif else begin
printf, lun, data, _extra=e
endelse
endelse
endelse
end
pro mgfftemplate::_process_if, mgfftemplate$variables, mgfftemplate$output_lun
compile_opt strictarr, logical_predicate
on_error, 2
mgfftemplate$expression = ''
mgfftemplate$post_delim = ''
while (strpos(mgfftemplate$post_delim, '%]') eq -1) do begin
mgfftemplate$expression += ' ' + self.tokenizer->next(post_delim=mgfftemplate$post_delim)
endwhile
mgfftemplate$delimiters = '"'' +-*/=^<>|&?:.[]{}()#~,'
mgfftemplate$vars = strsplit(mgfftemplate$expression, $
mgfftemplate$delimiters, $
/extract, $
count=mgfftemplate$nvars)
for i = 0, mgfftemplate$nvars - 1L do begin
mgfftemplate$result = self->_getVariable(mgfftemplate$variables, $
mgfftemplate$vars[i], $
found=mgfftemplate$varFound)
if (mgfftemplate$varFound) then begin
(scope_varfetch(mgfftemplate$vars[i], /enter)) = mgfftemplate$result
endif
endfor
mgfftemplate$result = execute('mgfftemplate$condition = ' + mgfftemplate$expression, 1, 1)
if (mgfftemplate$result) then begin
mgfftemplate$new_output_lun = mgfftemplate$condition ? mgfftemplate$output_lun : -3
endif else mgfftemplate$new_output_lun = -3
self->_process_tokens, mgfftemplate$variables, mgfftemplate$new_output_lun, $
else_clause=mgfftemplate$else_clause
if (keyword_set(mgfftemplate$else_clause)) then begin
if (mgfftemplate$result) then begin
mgfftemplate$new_output_lun = ~mgfftemplate$condition ? mgfftemplate$output_lun : -3
endif else mgfftemplate$new_output_lun = mgfftemplate$output_lun
self->_process_tokens, mgfftemplate$variables, mgfftemplate$new_output_lun
endif
end
pro mgfftemplate::_process_foreach, variables, output_lun
compile_opt strictarr
on_error, 2
loopVariable = self.tokenizer->next()
in = self.tokenizer->next(post_delim=post_delim)
loopVariable = strtrim(loopVariable, 2)
self->_process_variable, '', variables, output_lun, $
value=array, post_delim=post_delim, $
found=found
if (~keyword_set(found) && (output_lun ne -3L)) then begin
message, 'FOR loop array expression not found'
endif
if (output_lun eq -3) then array = ''
ofor = obj_new('MGffForTemplate', loopVariable, array[0])
ocompound = obj_new('MGffCompoundTemplate', ofor, variables)
pos = self.tokenizer->savePos()
for i = 0L, n_elements(array) - 1L do begin
ofor->setVariable, array[i]
self.tokenizer->restorePos, pos
self->_process_tokens, ocompound, output_lun
endfor
obj_destroy, [ofor, ocompound]
end
pro mgfftemplate::_copyFile, filename, output_lun, spaces=spaces
compile_opt strictarr
error = 0L
catch, error
if (error ne 0L) then begin
catch, /cancel
free_lun, insertLun
return
endif
openr, insertLun, filename, /get_lun
line = ''
while (~eof(insertLun)) do begin
readf, insertLun, line
self->_printf, output_lun, spaces + line
endwhile
free_lun, insertLun
end
pro mgfftemplate::_process_include, variables, output_lun, spaces=spaces
compile_opt strictarr
on_error, 2
filenameVariable = self.tokenizer->next()
if (output_lun eq -3) then return
filename = self->_getVariable(variables, filenameVariable, found=found)
line = self.tokenizer->getCurrentLine(number=lineNumber)
if (~found) then begin
message, 'variable ' + filenameVariable + ' not found on line ' $
+ strtrim(lineNumber, 2) + ' of ' + self.templateFilename $
+ ': ', $
/informational, /noname, /continue
message, line, /noname
endif
if (size(filename, /type) ne 7) then begin
message, 'Variable ' + filenameVariable + ' must be a string on line ' $
+ strtrim(lineNumber, 2) + ' of ' + self.templateFilename $
+ ': ', $
/informational, /noname, /continue
message, line, /noname
endif
if (~file_test(filename)) then begin
message, 'filename ' + filename + ' not found on line ' $
+ strtrim(lineNumber, 2) + ' of ' + self.templateFilename $
+ ': ', $
/informational, /noname, /continue
message, line, /noname
endif
self->_copyFile, filename, output_lun, spaces=spaces
end
pro mgfftemplate::_process_include_template, variables, output_lun, spaces=spaces
compile_opt strictarr
on_error, 2
filenameVariable = self.tokenizer->next()
if (output_lun eq -3) then return
filename = self->_getVariable(variables, filenameVariable, found=found)
line = self.tokenizer->getCurrentLine(number=lineNumber)
if (~found) then begin
message, 'variable ' + filenameVariable + ' not found on line ' $
+ strtrim(lineNumber, 2) + ' of ' + self.templateFilename $
+ ': ', $
/informational, /noname, /continue
message, line, /noname
endif
if (size(filename, /type) ne 7) then begin
message, 'Variable ' + filenameVariable + ' must be a string on line ' $
+ strtrim(lineNumber, 2) + ' of ' + self.templateFilename $
+ ': ', $
/informational, /noname, /continue
message, line, /noname
endif
if (~file_test(filename)) then begin
message, 'filename ' + filename + ' not found on line ' $
+ strtrim(lineNumber, 2) + ' of ' + self.templateFilename $
+ ': ', $
/informational, /noname, /continue
message, line, /noname
endif
oinclude = obj_new('MGffTemplate', filename, spaces=spaces)
oinclude->process, variables, lun=output_lun
obj_destroy, oinclude
end
pro mgfftemplate::_process_insert, output_lun, spaces=spaces
compile_opt strictarr
on_error, 2
filename = self.tokenizer->next()
cd, current=origDir
cd, self.includeRoot
filename = file_expand_path(filename)
cd, origDir
if (~file_test(filename)) then begin
message, 'filename ' + filename + ' not found', /noname
endif
openr, insertLun, filename, /get_lun
line = ''
while (~eof(insertLun)) do begin
readf, insertLun, line
self->_printf, output_lun, spaces + line
endwhile
free_lun, insertLun
end
pro mgfftemplate::_process_scope, variables, output_lun
compile_opt strictarr
on_error, 2
varname = self.tokenizer->next()
ovars = self->_getVariable(variables, varname, found=found)
if (~found) then begin
line = self.tokenizer->getCurrentLine(number=line_number)
message, 'variable ' + varname + ' not found on line ' $
+ strtrim(line_number, 2) + ' of ' + self.templateFilename $
+ ': ', $
/informational, /noname, /continue
message, line, /noname
endif
if (size(ovars, /type) ne 11) then begin
self->_process_tokens, variables, output_lun
endif else begin
ocompound = obj_new('MGffCompoundTemplate', ovars, variables)
self->_process_tokens, ocompound, output_lun
obj_destroy, ocompound
endelse
end
function mgfftemplate::_getVariable, variables, name, found=found
compile_opt strictarr
error = 0L
catch, error
if (error ne 0L) then begin
catch, /cancel
found = 0B
return, -1L
endif
case size(variables, /type) of
8 : begin
ind = where(tag_names(variables) eq strupcase(name), count)
found = count gt 0
return, found ? variables.(ind[0]) : -1L
end
11 : begin
result = variables->getVariable(name, found=found)
return, result
end
else : begin
found = 0B
return, -1L
end
endcase
end
pro mgfftemplate::_process_variable, mgfftemplate$expression, $
mgfftemplate$variables, $
mgfftemplate$output_lun, $
post_delim=mgfftemplate$post_delim, $
value=mgfftemplate$value, $
found=mgfftemplate$result
compile_opt strictarr, logical_predicate
on_error, 2
if (mgfftemplate$output_lun eq -3L) then return
while (strpos(mgfftemplate$post_delim, '%]') eq -1) do begin
mgfftemplate$expression += ' ' + self.tokenizer->next(post_delim=mgfftemplate$post_delim)
endwhile
mgfftemplate$delimiters = '"'' +-*/=^<>|&?:.[]{}()#~,'
mgfftemplate$vars = strsplit(mgfftemplate$expression, $
mgfftemplate$delimiters, $
/extract, $
count=mgfftemplate$nvars)
for mgfftemplate$i = 0L, mgfftemplate$nvars - 1L do begin
mgfftemplate$result = self->_getVariable(mgfftemplate$variables, $
mgfftemplate$vars[mgfftemplate$i], $
found=mgfftemplate$varFound)
if (mgfftemplate$varFound) then begin
(scope_varfetch(mgfftemplate$vars[mgfftemplate$i], /enter)) = mgfftemplate$result
endif
endfor
mgfftemplate$result = execute('mgfftemplate$value = ' + mgfftemplate$expression, 1, 1)
if (mgfftemplate$result) then begin
if (~arg_present(mgfftemplate$value)) then begin
self->_printf, mgfftemplate$output_lun, mgfftemplate$value, format='(A, $)'
endif
endif else begin
mgfftemplate$line = self.tokenizer->getCurrentLine(number=mgfftemplate$lineNumber)
message, 'invalid expression "' + mgfftemplate$expression + '" on line ' $
+ strtrim(mgfftemplate$lineNumber, 2) + ' of ' + self.templateFilename $
+ ' (error = ' + !error_state.msg + ')'
endelse
end
pro mgfftemplate::_process_tokens, variables, output_lun, $
else_clause=else_clause
compile_opt strictarr
on_error, 2
while (~self.tokenizer->done()) do begin
token = self.tokenizer->next(pre_delim=pre_delim, newline=newline, $
post_delim=post_delim)
if (newline) then begin
self->_printf, output_lun, string(10B) + self.spaces, format='(A, $)'
endif
if (strpos(pre_delim, '[%') ne -1) then begin
n_spaces = strpos(pre_delim, '[') - strpos(pre_delim, ']') - 1L
spaces = n_spaces le 0 ? '' : string(bytarr(n_spaces) + 32B)
self->_printf, output_lun, spaces, format='(A, $)'
command = strtrim(token, 2)
case strlowcase(command) of
'foreach' : self->_process_foreach, variables, output_lun
'if' : self->_process_if, variables, output_lun
'include' : self->_process_include, variables, output_lun, spaces=spaces
'include_template' : begin
self->_process_include_template, variables, output_lun, spaces=spaces
end
'insert' : self->_process_insert, output_lun, spaces=spaces
'scope' : self->_process_scope, variables, output_lun
'end' : return
'else' : begin
else_clause = 1
return
end
else : begin
self->_process_variable, command, variables, output_lun, $
post_delim=post_delim
end
endcase
endif else if (strtrim(pre_delim, 2) eq '%]') then begin
n_spaces = strlen(pre_delim) - strpos(pre_delim, ']') - 1L
spaces = n_spaces le 0 ? '' : string(bytarr(n_spaces) + 32B)
self->_printf, output_lun, spaces + token, format='(A, $)'
endif else begin
self->_printf, output_lun, pre_delim + token, format='(A, $)'
endelse
endwhile
end
pro mgfftemplate::process, variables, output_filename, lun=output_lun
compile_opt strictarr
on_error, 2
if (n_elements(output_lun) eq 0) then begin
openw, output_lun, output_filename, /get_lun
self->_process_tokens, variables, output_lun
free_lun, output_lun
endif else begin
self->_process_tokens, variables, output_lun
endelse
end
pro mgfftemplate::reset
compile_opt strictarr
self.tokenizer->reset
end
pro mgfftemplate::cleanup
compile_opt strictarr
obj_destroy, self.tokenizer
end
function mgfftemplate::init, template_filename, spaces=spaces, $
string_array=stringArray
compile_opt strictarr
on_error, 2
if (n_params() ne 1) then message, 'template filename parameter required'
self.templateFilename = keyword_set(stringArray) $
? 'string input' $
: template_filename
if (keyword_set(stringArray)) then begin
cd, current=currentDir
self.includeRoot = currentDir
endif else begin
self.includeRoot = file_dirname(template_filename)
endelse
self.spaces = n_elements(spaces) eq 0 ? '' : spaces
self.tokenizer = obj_new('MGffTokenizer', template_filename, $
pattern='(\[\%)|(\%\])| ', string_array=stringArray)
return, 1
end
pro mgfftemplate__define
compile_opt strictarr
define = { MGffTemplate, $
templateFilename: '', $
includeRoot: '', $
tokenizer: obj_new(), $
spaces: '' $
}
end