Class: Flott::Parser
Overview
The Flott::Parser class creates parser objects, that can be used to compile Flott template documents or files to Flott::Template instances.
Defined Under Namespace
Classes: Mode, RubyMode, State, TextMode
Constant Summary collapse
- ESCOPEN =
Regexp matching an escaped open square bracket like ‘[’.
/\\\[/
- INCOPEN =
- ^filename
/\[\^\s*([^\]]+?)\s*(-)?\]/
- PRIOPEN =
- =“foo<bar”
-
“foo<bar”
/\[=\s*/
- RAWOPEN =
- !“foo<bar”
-
“foo<bar”
/\[!\s*/
- COMOPEN =
- #comment
/\[#\s*/
- MINPRIOPEN =
Open succeded by minus deletes previous whitespaces until start of line.
/\[-=/
- MINRAWOPEN =
Open succeded by minus deletes previous whitespaces until start of line.
/\[-!/
- MINCOMOPEN =
Open succeded by minus deletes previous whitespaces until start of line.
/\[-#/
- MINOPEN =
Open succeded by minus deletes previous whitespaces until start of line.
/\[-/
- OPEN =
Regexp matching an open square bracket like ‘[’.
/\[/
- MINCLOSE =
Close preceded by minus deletes next CRLF.
/-\]/
- CLOSE =
Regexp matching an open square bracket like ‘]’.
/\]/
- ESCCLOSE =
Regexp matching an escaped closed square bracket like ‘]’.
/\\\]/
- TEXT =
Regexp matching general text, that doesn’t need special handling.
/([^-\\\]\[\{\}]+|-(?!\]))/
- ESC =
Regexp matching the escape character ‘'.
/\\/
- ESC_CLOSURE =
Regexp matching the escape character at least once.
/\\(\\*)/
- CURLY =
Regexp matching curly brackets ‘or ‘’.
/[{}]/
- CURLYOPEN =
Regexp matching open curly bracket like ‘{’.
/\{/
- CURLYCLOSE =
Regexp matching open curly bracket like ‘}’.
/\}/
- ESCAPE_MAP =
:stopdoc:
Hash.new { |h, c| raise "unknown character '#{c}'" }
- HTML_ESCAPE =
This Proc object escapes string, by substituting &<>“‘ with their respective html entities, and returns the result.
lambda do |string| if string.respond_to?(:to_str) string.to_str.gsub(/[&<>"']/) { |c| ESCAPE_MAP[c[0]] } else string = string.to_s string.gsub!(/[&<>"']/) { |c| ESCAPE_MAP[c[0]] } string end end
Instance Attribute Summary collapse
-
#parent ⇒ Object
Returns nil if this is the root parser, or a reference to the parent parser of this parser.
-
#rootdir ⇒ Object
readonly
Compute the rootdir of this parser (these parsers).
-
#scanner ⇒ Object
readonly
The StringScanner instance of this Parser object.
-
#workdir ⇒ Object
Returns the current work directory of this parser.
Class Method Summary collapse
-
.from_filename(filename) ⇒ Object
Creates a Parser object from filename, the workdir and _rootdir attributes are set to the directory the file is located in.
Instance Method Summary collapse
-
#compile ⇒ Object
Compiles the template source and returns a Proc object to be executed later.
-
#evaluate(env = Environment.new, &block) ⇒ Object
First compiles the source template and evaluates it in the environment env.
-
#fork(source, workdir, rootdir, filename) ⇒ Object
Fork another Parser to handle an included template.
-
#goto_ruby_mode ⇒ Object
Change parsing mode to RubyMode.
-
#goto_text_mode ⇒ Object
Change parsing mode to TextMode.
-
#include_template(filename) ⇒ Object
Include the template file with filename at the current place.
-
#initialize(source, workdir = nil, rootdir = nil, filename = nil) ⇒ Parser
constructor
Creates a Parser object.
-
#state ⇒ Object
Returns the shared state between all parsers that are parsing the current template and the included templates.
Methods included from FilenameMixin
Constructor Details
#initialize(source, workdir = nil, rootdir = nil, filename = nil) ⇒ Parser
Creates a Parser object. workdir is the directory, on which relative template inclusions are based. rootdir is the directory. On which absolute template inclusions (starting with ‘/’) are based. filename is the filename of this template (if any), which is important to track changes in the template file to trigger a reloading.
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 |
# File 'lib/flott.rb', line 679 def initialize(source, workdir = nil, rootdir = nil, filename = nil) if workdir check_secure_path(workdir) @workdir = File.(workdir) else @workdir = Dir.pwd end if rootdir check_secure_path(rootdir) @rootdir = File.(rootdir) else @rootdir = @workdir end sub_path?(@workdir, @rootdir) or raise SecurityViolation, "#{@workdir} isn't a sub path of '#{@rootdir}'" if filename check_secure_path(filename) @filename = File.(filename) sub_path?(@filename, @workdir) or raise SecurityViolation, "#{@filename} isn't a sub path of '#{@workdir}" end @ruby = RubyMode.new(self) @text = TextMode.new(self) @current_mode = @text @scanner = StringScanner.new(source) end |
Instance Attribute Details
#parent ⇒ Object
Returns nil if this is the root parser, or a reference to the parent parser of this parser.
726 727 728 |
# File 'lib/flott.rb', line 726 def parent @parent end |
#rootdir ⇒ Object (readonly)
Compute the rootdir of this parser (these parsers). Cache the result and return it.
730 731 732 |
# File 'lib/flott.rb', line 730 def rootdir @rootdir end |
#scanner ⇒ Object (readonly)
The StringScanner instance of this Parser object.
716 717 718 |
# File 'lib/flott.rb', line 716 def scanner @scanner end |
#workdir ⇒ Object
Returns the current work directory of this parser.
733 734 735 |
# File 'lib/flott.rb', line 733 def workdir @workdir end |
Class Method Details
.from_filename(filename) ⇒ Object
Creates a Parser object from filename, the workdir and _rootdir attributes are set to the directory the file is located in.
708 709 710 711 712 713 |
# File 'lib/flott.rb', line 708 def self.from_filename(filename) filename = File.(filename) workdir = File.dirname(filename) source = File.read(filename) new(source, workdir, workdir, filename) end |
Instance Method Details
#compile ⇒ Object
Compiles the template source and returns a Proc object to be executed later. This method raises a ParserError exception if source is not _Parser#wellformed?_.
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
# File 'lib/flott.rb', line 748 def compile @state = State.new state.compiled << [ "::Flott::Template.new \{ |__env__| __env__.instance_eval %q{\n", "@__rootdir__ = '#{rootdir}'\n", ] state.pathes << @filename if defined?(@filename) compile_inner state.compiled << "\n}\n}" source = state.compiled_string template = eval(source, nil, '(flott)') template.pathes = state.pathes template.source = source template rescue SyntaxError => e raise EvalError.wrap(e) end |
#evaluate(env = Environment.new, &block) ⇒ Object
First compiles the source template and evaluates it in the environment env. If no environment is given, a newly created environment is used.
977 978 979 980 981 |
# File 'lib/flott.rb', line 977 def evaluate(env = Environment.new, &block) env.instance_eval(&block) if block compile.evaluate(env) self end |
#fork(source, workdir, rootdir, filename) ⇒ Object
Fork another Parser to handle an included template.
781 782 783 784 785 |
# File 'lib/flott.rb', line 781 def fork(source, workdir, rootdir, filename) parser = self.class.new(source, workdir, rootdir, filename) parser.parent = self parser.compile_inner(@workdir != workdir) end |
#goto_ruby_mode ⇒ Object
Change parsing mode to RubyMode.
741 742 743 |
# File 'lib/flott.rb', line 741 def goto_ruby_mode @current_mode = @ruby end |
#goto_text_mode ⇒ Object
Change parsing mode to TextMode.
736 737 738 |
# File 'lib/flott.rb', line 736 def goto_text_mode @current_mode = @text end |
#include_template(filename) ⇒ Object
Include the template file with filename at the current place.
767 768 769 770 771 772 773 774 775 776 777 778 |
# File 'lib/flott.rb', line 767 def include_template(filename) filename = interpret_filename(filename) if File.readable?(filename) state.text2compiled state.pathes << filename source = File.read(filename) workdir = File.dirname(filename) fork(source, workdir, rootdir, filename) else raise CompileError, "Cannot open #{filename} for inclusion!" end end |
#state ⇒ Object
Returns the shared state between all parsers that are parsing the current template and the included templates.
720 721 722 |
# File 'lib/flott.rb', line 720 def state @state ||= parent.state end |