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 15 def fullscan_epp 16 result = [] 17 scan_epp {|token, value| result.push([token, value]) } 18 result 19 end
# File lib/puppet/pops/parser/epp_support.rb 60 def interpolate_epp(skip_leading=false) 61 scn = @scanner 62 ctx = @lexing_context 63 eppscanner = EppScanner.new(scn) 64 before = scn.pos 65 66 s = eppscanner.scan(skip_leading) 67 68 case eppscanner.mode 69 when :text 70 # Should be at end of scan, or something is terribly wrong 71 unless @scanner.eos? 72 lex_error(Issues::EPP_INTERNAL_ERROR, :error => 'template scanner returns text mode and is not and end of input') 73 end 74 if s 75 # s may be nil if scanned text ends with an epp tag (i.e. no trailing text). 76 enqueue_completed([:RENDER_STRING, s, scn.pos - before], before) 77 end 78 ctx[:epp_open_position] = nil 79 # do nothing else, scanner is at the end 80 81 when :error 82 lex_error(eppscanner.issue) 83 84 when :epp 85 # It is meaningless to render empty string segments, and it is harmful to do this at 86 # the start of the scan as it prevents specification of parameters with <%- ($x, $y) -%> 87 # 88 if s && s.length > 0 89 enqueue_completed([:RENDER_STRING, s, scn.pos - before], before) 90 end 91 # switch epp_mode to general (embedded) pp logic (non rendered result) 92 ctx[:epp_mode] = :epp 93 ctx[:epp_open_position] = scn.pos 94 95 when :expr 96 # It is meaningless to render an empty string segment 97 if s && s.length > 0 98 enqueue_completed([:RENDER_STRING, s, scn.pos - before], before) 99 end 100 enqueue_completed(TOKEN_RENDER_EXPR, before) 101 # switch mode to "epp expr interpolation" 102 ctx[:epp_mode] = :expr 103 ctx[:epp_open_position] = scn.pos 104 else 105 lex_error(Issues::EPP_INTERNAL_ERROR, :error => "Unknown mode #{eppscanner.mode} returned by template scanner") 106 end 107 nil 108 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 29 def scan_epp 30 # PERFORMANCE note: it is faster to access local variables than instance variables. 31 # This makes a small but notable difference since instance member access is avoided for 32 # every token in the lexed content. 33 # 34 scn = @scanner 35 ctx = @lexing_context 36 queue = @token_queue 37 38 lex_error(Issues::EPP_INTERNAL_ERROR, :error => 'No string or file given to lexer to process.') unless scn 39 40 ctx[:epp_mode] = :text 41 enqueue_completed([:EPP_START, nil, 0], 0) 42 43 interpolate_epp 44 45 # This is the lexer's main loop 46 until queue.empty? && scn.eos? do 47 token = queue.shift || lex_token 48 if token 49 yield [ ctx[:after] = token[0], token[1] ] 50 end 51 end 52 if ctx[:epp_open_position] 53 lex_error(Issues::EPP_UNBALANCED_TAG, {}, ctx[:epp_position]) 54 end 55 56 # Signals end of input 57 yield [false, false] 58 end