require 'wlang/rulesets/ruleset_utils' require 'fileutils' module WLang class RuleSet # # Buffering ruleset, providing special tags to load/instantiate accessible files # and outputting instantiation results in other files. # # For an overview of this ruleset, see the wlang {specification file}[link://files/specification.html]. # module Buffering U=WLang::RuleSet::Utils # Default mapping between tag symbols and methods DEFAULT_RULESET = {'<<' => :input, '>>' => :output, '<<=' => :data_assignment, '<<+' => :input_inclusion} # Rule implementation of <<{wlang/uri} def self.input(parser, offset) uri, reached = parser.parse(offset, "wlang/uri") file = parser.template.file_resolve(uri, false) if File.file?(file) and File.readable?(file) [File.read(file), reached] else text = parser.parse(offset, "wlang/dummy")[0] parser.error(offset, "unable to apply input rule <<{#{text}}, not a file or not readable (#{file})") end end # Rule implementation of >>{wlang/uri} def self.output(parser, offset) uri, reached = parser.parse(offset, "wlang/uri") file = parser.template.file_resolve(uri, false) dir = File.dirname(file) if File.writable?(dir) or not(File.exists?(dir)) FileUtils.mkdir_p(dir) unless File.exists?(dir) File.open(file, "w") do |file| text, reached = parser.parse_block(reached, nil, file) end ["", reached] else text = parser.parse(offset, "wlang/dummy")[0] parser.error(offset, "unable to apply output rule >>{#{text}}, not a writable directory (#{file})") end end # Rule implementation of <<={wlang/uri as x}{...} def self.data_assignment(parser, offset) uri, reached = parser.parse(offset, "wlang/uri") # decode expression decoded = U.decode_uri_as(uri) parser.syntax_error(offset) if decoded.nil? file = parser.template.file_resolve(decoded[:uri], false) if File.file?(file) and File.readable?(file) data = WLang::load_data(file) # handle two different cases if parser.has_block?(reached) parser.branch_scope(decoded[:variable] => data) { parser.parse_block(reached) } else parser.scope_define(decoded[:variable], data) ["", reached] end else text = parser.parse(offset, "wlang/dummy")[0] parser.error(offset, "unable to apply data-assignment rule <<={#{text}} (#{file}), not a file or not readable (#{file})") end end # Rule implementation of <<+{wlang/uri with ...} def self.input_inclusion(parser, offset) uri, reached = parser.parse(offset, "wlang/uri") # decode the expression decoded = U.expr(:uri, ["share", :share, false], ["using", :using, false], ["with", :with, false]).decode(uri, parser) parser.syntax_error(offset) if decoded.nil? # Look for share and context shared = decoded[:share].nil? ? :none : decoded[:share] context = U.context_from_using_and_with(decoded, parser) # Resolve the file by delegation to the parser file = parser.file_resolve(decoded[:uri]) # Go for it if File.file?(file) and File.readable?(file) parser.branch(:template => parser.file_template(file), :offset => 0, :shared => shared, :scope => context) { instantiated, forget = parser.instantiate [instantiated, reached] } else text = parser.parse(offset, "wlang/dummy")[0] parser.error(offset, "unable to apply input-inclusion rule <<+{#{text}}, not a file or not readable (#{file})") end end end # module Buffering end end