module Puppet::Pops::Parser::EppSupport
Constants
- TOKEN_RENDER_EXPR
- TOKEN_RENDER_STRING
Public Instance Methods
Scans all of the content and returns it in an array Note that the terminating [false, false] token is included in the result.
# File lib/puppet/pops/parser/epp_support.rb 16 def fullscan_epp 17 result = [] 18 scan_epp {|token, value| result.push([token, value]) } 19 result 20 end
# File lib/puppet/pops/parser/epp_support.rb 61 def interpolate_epp(skip_leading=false) 62 scn = @scanner 63 ctx = @lexing_context 64 eppscanner = EppScanner.new(scn) 65 before = scn.pos 66 67 s = eppscanner.scan(skip_leading) 68 69 case eppscanner.mode 70 when :text 71 # Should be at end of scan, or something is terribly wrong 72 unless @scanner.eos? 73 lex_error(Issues::EPP_INTERNAL_ERROR, :error => 'template scanner returns text mode and is not and end of input') 74 end 75 if s 76 # s may be nil if scanned text ends with an epp tag (i.e. no trailing text). 77 enqueue_completed([:RENDER_STRING, s, scn.pos - before], before) 78 end 79 ctx[:epp_open_position] = nil 80 # do nothing else, scanner is at the end 81 82 when :error 83 lex_error(eppscanner.issue) 84 85 when :epp 86 # It is meaningless to render empty string segments, and it is harmful to do this at 87 # the start of the scan as it prevents specification of parameters with <%- ($x, $y) -%> 88 # 89 if s && s.length > 0 90 enqueue_completed([:RENDER_STRING, s, scn.pos - before], before) 91 end 92 # switch epp_mode to general (embedded) pp logic (non rendered result) 93 ctx[:epp_mode] = :epp 94 ctx[:epp_open_position] = scn.pos 95 96 when :expr 97 # It is meaningless to render an empty string segment 98 if s && s.length > 0 99 enqueue_completed([:RENDER_STRING, s, scn.pos - before], before) 100 end 101 enqueue_completed(TOKEN_RENDER_EXPR, before) 102 # switch mode to "epp expr interpolation" 103 ctx[:epp_mode] = :expr 104 ctx[:epp_open_position] = scn.pos 105 else 106 lex_error(Issues::EPP_INTERNAL_ERROR, :error => "Unknown mode #{eppscanner.mode} returned by template scanner") 107 end 108 nil 109 end
A block must be passed to scan. It will be called with two arguments, a symbol for the token, and an instance of LexerSupport::TokenValue PERFORMANCE NOTE: The TokenValue is designed to reduce the amount of garbage / temporary data and to only convert the lexer's internal tokens on demand. It is slightly more costly to create an instance of a class defined in Ruby than an Array or Hash, but the gain is much bigger since transformation logic is avoided for many of its members (most are never used (e.g. line/pos information which is only of value in general for error messages, and for some expressions (which the lexer does not know about).
# File lib/puppet/pops/parser/epp_support.rb 30 def scan_epp 31 # PERFORMANCE note: it is faster to access local variables than instance variables. 32 # This makes a small but notable difference since instance member access is avoided for 33 # every token in the lexed content. 34 # 35 scn = @scanner 36 ctx = @lexing_context 37 queue = @token_queue 38 39 lex_error(Issues::EPP_INTERNAL_ERROR, :error => 'No string or file given to lexer to process.') unless scn 40 41 ctx[:epp_mode] = :text 42 enqueue_completed([:EPP_START, nil, 0], 0) 43 44 interpolate_epp 45 46 # This is the lexer's main loop 47 until queue.empty? && scn.eos? do 48 token = queue.shift || lex_token 49 if token 50 yield [ ctx[:after] = token[0], token[1] ] 51 end 52 end 53 if ctx[:epp_open_position] 54 lex_error(Issues::EPP_UNBALANCED_TAG, {}, ctx[:epp_position]) 55 end 56 57 # Signals end of input 58 yield [false, false] 59 end