Class: Puppet::Pops::Parser::EppSupport::EppScanner
- Defined in:
- lib/puppet/pops/parser/epp_support.rb
Overview
A scanner specialized in processing text with embedded EPP (Embedded Puppet) tags. The scanner is initialized with a StringScanner which it mutates as scanning takes place. The intent is to use one instance of EppScanner per wanted scan, and this instance represents the state after the scan.
The scanner supports
-
scanning text until <%, <%-, <%=
-
while scanning text:
-
tokens <%% and %%> are translated to <% and %>, respectively, and is returned as text.
-
tokens <%# and %> (or ending with -%>) and the enclosed text is a comment and is not included in the returned text
-
text following a comment that ends with -%> gets trailing whitespace (up to and including a line break) trimmed and this whitespace is not included in the returned text.
-
-
The continuation #mode is set to one of:
-
‘:epp` - for a <% token
-
‘:expr` - for a <%= token
-
‘:text` - when there was no continuation mode (e.g. when input ends with text)
-
‘:error` - if the tokens are unbalanced (reaching the end without a closing matching token). An error message is then also available via the method #message.
-
Note that the intent is to use this specialized scanner to scan the text parts, when continuation mode is ‘:epp` or `:expr` the pp lexer should advance scanning (using the string scanner) until it reaches and consumes a `-%>` or ’%>´ token. If it finds a ‘-%> token it should pass this on as a `skip_leading` parameter when it performs the next #scan.
Instance Attribute Summary collapse
-
#issue ⇒ Object
readonly
An error issue if ‘mode == :error`, `nil` otherwise.
-
#mode ⇒ Object
readonly
The resulting mode after the scan.
-
#scanner ⇒ Object
readonly
The original scanner used by the lexer/container using EppScanner.
-
#skip_leading ⇒ Object
readonly
If the first scan should skip leading whitespace (typically detected by the pp lexer when the pp mode end-token is found (i.e. ‘-%>`) and then passed on to the scanner..
Instance Method Summary collapse
-
#initialize(scanner) ⇒ EppScanner
constructor
Creates an EppScanner based on a StringScanner that represents the state where EppScanner should start scanning.
-
#message ⇒ String
deprecated
Deprecated.
Use issue instead
-
#scan(skip_leading = false) ⇒ String?
Scans from the current position in the configured scanner, advances this scanner’s position until the end of the input, or to the first position after a mode switching token (‘<%`, `<%-` or `<%=`).
Constructor Details
#initialize(scanner) ⇒ EppScanner
Creates an EppScanner based on a StringScanner that represents the state where EppScanner should start scanning. The given scanner will be mutated (i.e. position moved) to reflect the EppScanner’s end state after a scan.
164 165 166 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 164 def initialize(scanner) @scanner = scanner end |
Instance Attribute Details
#issue ⇒ Object (readonly)
An error issue if ‘mode == :error`, `nil` otherwise.
154 155 156 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 154 def issue @issue end |
#mode ⇒ Object (readonly)
The resulting mode after the scan. The mode is one of ‘:text` (the initial mode), `:epp` embedded code (no output), `:expr` (embedded expression), or `:error`
151 152 153 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 151 def mode @mode end |
#scanner ⇒ Object (readonly)
The original scanner used by the lexer/container using EppScanner
145 146 147 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 145 def scanner @scanner end |
#skip_leading ⇒ Object (readonly)
If the first scan should skip leading whitespace (typically detected by the pp lexer when the pp mode end-token is found (i.e. ‘-%>`) and then passed on to the scanner.
159 160 161 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 159 def skip_leading @skip_leading end |
Instance Method Details
#message ⇒ String
Use issue instead
Here for backwards compatibility.
171 172 173 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 171 def @issue.nil? ? nil : @issue.format end |
#scan(skip_leading = false) ⇒ String?
Scans from the current position in the configured scanner, advances this scanner’s position until the end of the input, or to the first position after a mode switching token (‘<%`, `<%-` or `<%=`). Number of processed lines and continuation mode can be obtained via #lines, and #mode.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 181 def scan(skip_leading = false) @mode = :text @skip_leading = skip_leading return nil if scanner.eos? s = ''.dup until scanner.eos? part = @scanner.scan_until(/(<%)|\z/) if @skip_leading part.sub!(/^[ \t]*\r?(?:\n|\z)?/, '') @skip_leading = false end # The spec for %%> is to transform it into a literal %>. This is done here, as %%> otherwise would go # undetected in text mode. (i.e. it is not really necessary to escape %> with %%> in text mode unless # adding checks stating that a literal %> is illegal in text (unbalanced). # part.gsub!(/%%>/, '%>') s += part case @scanner.peek(1) when "" # at the end # if s ends with <% then this is an error (unbalanced <% %>) if s.end_with? "<%" @mode = :error @issue = Issues::EPP_UNBALANCED_EXPRESSION end return s when "-" # trim trailing whitespace on same line from accumulated s # return text and signal switch to pp mode @scanner.getch # drop the - s.sub!(/[ \t]*<%\z/, '') @mode = :epp return s when "%" # verbatim text # keep the scanned <%, and continue scanning after skipping one % # (i.e. do nothing here) @scanner.getch # drop the % to get a literal <% in the output when "=" # expression # return text and signal switch to expression mode # drop the scanned <%, and skip past -%>, or %>, but also skip %%> @scanner.getch # drop the = s.slice!(-2..-1) @mode = :expr return s when "#" # template comment # drop the scanned <%, and skip past -%>, or %>, but also skip %%> s.slice!(-2..-1) # unless there is an immediate termination i.e. <%#%> scan for the next %> that is not # preceded by a % (i.e. skip %%>) part = scanner.scan_until(/[^%]%>/) unless part @issue = Issues::EPP_UNBALANCED_COMMENT @mode = :error return s end # Trim leading whitespace on the same line when start was <%#- if part[1] == '-' s.sub!(/[ \t]*\z/, '') end @skip_leading = true if part.end_with?("-%>") # Continue scanning for more text else # Switch to pp after having removed the <% s.slice!(-2..-1) @mode = :epp return s end end end |