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 %> respetively 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.
162 163 164 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 162 def initialize(scanner) @scanner = scanner end |
Instance Attribute Details
#issue ⇒ Object (readonly)
An error issue if ‘mode == :error`, `nil` otherwise.
152 153 154 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 152 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`
149 150 151 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 149 def mode @mode end |
#scanner ⇒ Object (readonly)
The original scanner used by the lexer/container using EppScanner
143 144 145 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 143 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.
157 158 159 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 157 def skip_leading @skip_leading end |
Instance Method Details
#message ⇒ String
Use issue instead
Here for backwards compatibility.
169 170 171 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 169 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.
179 180 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 |
# File 'lib/puppet/pops/parser/epp_support.rb', line 179 def scan(skip_leading=false) @mode = :text @skip_leading = skip_leading return nil if scanner.eos? s = "" 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 else mode = :epp 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 # Always trim leading whitespace on the same line when there is a comment s.sub!(/[ \t]*\z/, '') @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 |