Class: Twig::Parser
- Inherits:
-
Object
- Object
- Twig::Parser
- Defined in:
- lib/twig/parser.rb
Instance Attribute Summary collapse
-
#block_stack ⇒ Object
readonly
Returns the value of attribute block_stack.
- #stream ⇒ TokenStream readonly
Instance Method Summary collapse
- #block?(name) ⇒ Boolean
- #current_token ⇒ Token
- #expression_parser ⇒ ExpressionParser
-
#initialize(environment) ⇒ Parser
constructor
A new instance of Parser.
- #parent=(parent) ⇒ Object
- #parse(stream, test = nil, drop_needle: false) ⇒ Object
- #peek_block_stack ⇒ Object
- #pop_block_stack ⇒ Object
- #pop_local_scope ⇒ Object
- #push_block_stack(name) ⇒ Object
- #push_local_scope ⇒ Object
- #set_block(name, value) ⇒ Object
- #subparse(test, drop_needle: false) ⇒ Node::Base
Constructor Details
#initialize(environment) ⇒ Parser
Returns a new instance of Parser.
10 11 12 |
# File 'lib/twig/parser.rb', line 10 def initialize(environment) @environment = environment end |
Instance Attribute Details
#block_stack ⇒ Object (readonly)
Returns the value of attribute block_stack.
7 8 9 |
# File 'lib/twig/parser.rb', line 7 def block_stack @block_stack end |
#stream ⇒ TokenStream (readonly)
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 |
# File 'lib/twig/parser.rb', line 6 class Parser attr_reader :stream, :block_stack # @param [Environment] environment def initialize(environment) @environment = environment end # @param [TokenStream] stream def parse(stream, test = nil, drop_needle: false) @stream = stream @parent = nil @blocks = {} @block_stack = [] @imported_symbols = [{}] body = subparse(test, drop_needle:) Node::Module.new(body, @parent, Node::Nodes.new(@blocks), stream.source) end # @param [Proc] test # @return [Node::Base] def subparse(test, drop_needle: false) lineno = current_token.lineno rv = AutoHash.new until stream.eof? case current_token.type when Token::TEXT_TYPE token = stream.next rv.add(Node::Text.new(token.value, token.lineno)) when Token::VAR_START_TYPE token = stream.next expr = expression_parser.parse_expression stream.expect(Token::VAR_END_TYPE) rv.add(Node::Print.new(expr, token.lineno)) when Token::BLOCK_START_TYPE stream.next token = current_token unless token.type == Token::NAME_TYPE raise Error::Syntax.new('A block must start with a tag name.', token.lineno, stream.source) end if test&.call(token) stream.next if drop_needle return rv.values.first if rv.length == 1 return Node::Nodes.new(rv, lineno) end # @todo Check that there is a token parser for this token value subparser = @environment.token_parser(token.value) unless subparser raise Error::Syntax.new("Unexpected '#{token.value}' tag.", token.lineno, stream.source) end stream.next subparser.parser = self node = subparser.parse(token) raise 'Cannot return nil from TokenParser' unless node node.tag = subparser.tag rv.add(node) else raise "Unable to parse token of type #{current_token.type}" end end Node::Nodes.new(rv) end # @return [Token] def current_token stream.current end # @return [ExpressionParser] def expression_parser @expression_parser ||= ExpressionParser.new(self, @environment) end def push_local_scope @imported_symbols.unshift({}) end def pop_local_scope @imported_symbols.shift end def peek_block_stack @block_stack[-1] end def pop_block_stack @block_stack.pop end def push_block_stack(name) @block_stack << name end def block?(name) @blocks.key?(name) end # @todo type value as BlockNode and also set it to a BodyNode def set_block(name, value) @blocks[name] = value end # @param [Node::Base] parent def parent=(parent) if @parent raise Error::Syntax.new('Cannot extends twice', parent.lineno, parent.source_context) end @parent = parent end end |
Instance Method Details
#block?(name) ⇒ Boolean
113 114 115 |
# File 'lib/twig/parser.rb', line 113 def block?(name) @blocks.key?(name) end |
#current_token ⇒ Token
84 85 86 |
# File 'lib/twig/parser.rb', line 84 def current_token stream.current end |
#expression_parser ⇒ ExpressionParser
89 90 91 |
# File 'lib/twig/parser.rb', line 89 def expression_parser @expression_parser ||= ExpressionParser.new(self, @environment) end |
#parent=(parent) ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/twig/parser.rb', line 123 def parent=(parent) if @parent raise Error::Syntax.new('Cannot extends twice', parent.lineno, parent.source_context) end @parent = parent end |
#parse(stream, test = nil, drop_needle: false) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/twig/parser.rb', line 15 def parse(stream, test = nil, drop_needle: false) @stream = stream @parent = nil @blocks = {} @block_stack = [] @imported_symbols = [{}] body = subparse(test, drop_needle:) Node::Module.new(body, @parent, Node::Nodes.new(@blocks), stream.source) end |
#peek_block_stack ⇒ Object
101 102 103 |
# File 'lib/twig/parser.rb', line 101 def peek_block_stack @block_stack[-1] end |
#pop_block_stack ⇒ Object
105 106 107 |
# File 'lib/twig/parser.rb', line 105 def pop_block_stack @block_stack.pop end |
#pop_local_scope ⇒ Object
97 98 99 |
# File 'lib/twig/parser.rb', line 97 def pop_local_scope @imported_symbols.shift end |
#push_block_stack(name) ⇒ Object
109 110 111 |
# File 'lib/twig/parser.rb', line 109 def push_block_stack(name) @block_stack << name end |
#push_local_scope ⇒ Object
93 94 95 |
# File 'lib/twig/parser.rb', line 93 def push_local_scope @imported_symbols.unshift({}) end |
#set_block(name, value) ⇒ Object
118 119 120 |
# File 'lib/twig/parser.rb', line 118 def set_block(name, value) @blocks[name] = value end |
#subparse(test, drop_needle: false) ⇒ Node::Base
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 |
# File 'lib/twig/parser.rb', line 29 def subparse(test, drop_needle: false) lineno = current_token.lineno rv = AutoHash.new until stream.eof? case current_token.type when Token::TEXT_TYPE token = stream.next rv.add(Node::Text.new(token.value, token.lineno)) when Token::VAR_START_TYPE token = stream.next expr = expression_parser.parse_expression stream.expect(Token::VAR_END_TYPE) rv.add(Node::Print.new(expr, token.lineno)) when Token::BLOCK_START_TYPE stream.next token = current_token unless token.type == Token::NAME_TYPE raise Error::Syntax.new('A block must start with a tag name.', token.lineno, stream.source) end if test&.call(token) stream.next if drop_needle return rv.values.first if rv.length == 1 return Node::Nodes.new(rv, lineno) end # @todo Check that there is a token parser for this token value subparser = @environment.token_parser(token.value) unless subparser raise Error::Syntax.new("Unexpected '#{token.value}' tag.", token.lineno, stream.source) end stream.next subparser.parser = self node = subparser.parse(token) raise 'Cannot return nil from TokenParser' unless node node.tag = subparser.tag rv.add(node) else raise "Unable to parse token of type #{current_token.type}" end end Node::Nodes.new(rv) end |