class Puppet::Pops::Parser::Parser

Supporting logic for the parser. This supporting logic has slightly different responsibilities compared to the original Puppet::Parser::Parser. It is only concerned with parsing.

Constants

Factory

Simplify access to the Model factory Note that the parser/parser support does not have direct knowledge about the Model. All model construction/manipulation is made by the Factory.

Racc_arg
Racc_debug_parser
Racc_token_to_s_table

Attributes

definitions[R]
lexer[RW]

Public Class Methods

new() click to toggle source
   # File lib/puppet/pops/parser/parser_support.rb
85 def initialize()
86   @lexer = Lexer2.new
87   @namestack = []
88   @definitions = []
89 end

Public Instance Methods

_parse() click to toggle source

Performs the parsing and returns the resulting model. The lexer holds state, and this is setup with {#parse_string}, or {#parse_file}.

@api private

    # File lib/puppet/pops/parser/parser_support.rb
239 def _parse()
240   begin
241     @yydebug = false
242     main = yyparse(@lexer,:scan)
243   end
244   return main
245 ensure
246   @lexer.clear
247   @namestack = []
248   @definitions = []
249 end
_reduce_none(val, _values, result) click to toggle source
     # File lib/puppet/pops/parser/eparser.rb
3177 def _reduce_none(val, _values, result)
3178   val[0]
3179 end
add_definition(definition) click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
177 def add_definition(definition)
178   @definitions << definition.model
179   definition
180 end
aryfy(o) click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
160 def aryfy(o)
161   o = [o] unless o.is_a?(Array)
162   o
163 end
classname(name) click to toggle source

Produces the fully qualified name, with the full (current) namespace for a given name.

This is needed because class bodies are lazily evaluated and an inner class' container(s) may not have been evaluated before some external reference is made to the inner class; its must therefore know its complete name before evaluation-time.

   # File lib/puppet/pops/parser/parser_support.rb
47 def classname(name)
48   [namespace, name].join('::').sub(/^::/, '')
49 end
create_empty_program() click to toggle source

Creates an empty program with a single No-op at the input's EOF offset with 0 length.

    # File lib/puppet/pops/parser/parser_support.rb
221 def create_empty_program()
222   locator = @lexer.locator
223   no_op = Factory.literal(nil)
224   # Create a synthetic NOOP token at EOF offset with 0 size. The lexer does not produce an EOF token that is
225   # visible to the grammar rules. Creating this token is mainly to reuse the positioning logic as it
226   # expects a token decorated with location information.
227   _, token = @lexer.emit_completed([:NOOP,'',0], locator.string.bytesize)
228   loc(no_op, token)
229   # Program with a Noop
230   program = Factory.PROGRAM(no_op, [], locator)
231   program
232 end
create_program(body) click to toggle source

Creates a program with the given body.

    # File lib/puppet/pops/parser/parser_support.rb
214 def create_program(body)
215   locator = @lexer.locator
216   Factory.PROGRAM(body, definitions, locator)
217 end
error(semantic, message) click to toggle source

Raises a Parse error with location information. Information about file is always obtained from the lexer. Line and position is produced if the given semantic is a Positioned object and have been given an offset.

   # File lib/puppet/pops/parser/parser_support.rb
54 def error(semantic, message)
55   except = Puppet::ParseError.new(message)
56   if semantic.is_a?(LexerSupport::TokenValue)
57     except.file = semantic[:file];
58     except.line = semantic[:line];
59     except.pos = semantic[:pos];
60   else
61     locator = @lexer.locator
62     except.file = locator.file
63     if semantic.is_a?(Factory)
64       offset = semantic['offset']
65       unless offset.nil?
66         except.line = locator.line_for_offset(offset)
67         except.pos = locator.pos_on_line(offset)
68       end
69     end
70   end
71   raise except
72 end
heredoc_loc(factory, start_locatable, end_locatable = nil) click to toggle source

Mark the factory wrapped heredoc model object with location information @return [Factory] the given factory @api private

    # File lib/puppet/pops/parser/parser_support.rb
156 def heredoc_loc(factory, start_locatable, end_locatable = nil)
157   factory.record_heredoc_position(start_locatable, end_locatable)
158 end
loc(factory, start_locatable, end_locatable = nil) click to toggle source

Mark the factory wrapped model object with location information @return [Factory] the given factory @api private

    # File lib/puppet/pops/parser/parser_support.rb
148 def loc(factory, start_locatable, end_locatable = nil)
149   factory.record_position(@lexer.locator, start_locatable, end_locatable)
150 end
namepop() click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
173 def namepop()
174   @namestack.pop
175 end
namespace() click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
165 def namespace
166   @namestack.join('::')
167 end
namestack(name) click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
169 def namestack(name)
170   @namestack << name
171 end
on_error(token,value,stack) click to toggle source

This is a callback from the generated parser (when an error occurs while parsing)

    # File lib/puppet/pops/parser/parser_support.rb
 93 def on_error(token,value,stack)
 94   if token == 0 # denotes end of file
 95     value_at = 'end of input'
 96   else
 97     value_at = "'#{value[:value]}'"
 98   end
 99   error = Issues::SYNTAX_ERROR.format(:where => value_at)
100   error = "#{error}, token: #{token}" if @yydebug
101 
102   # Note, old parser had processing of "expected token here" - do not try to reinstate:
103   # The 'expected' is only of value at end of input, otherwise any parse error involving a
104   # start of a pair will be reported as expecting the close of the pair - e.g. "$x.each |$x {|", would
105   # report that "seeing the '{', the '}' is expected. That would be wrong.
106   # Real "expected" tokens are very difficult to compute (would require parsing of racc output data). Output of the stack
107   # could help, but can require extensive backtracking and produce many options.
108   #
109   # The lexer should handle the "expected instead of end of file for strings, and interpolation", other expectancies
110   # must be handled by the grammar. The lexer may have enqueued tokens far ahead - the lexer's opinion about this
111   # is not trustworthy.
112   #
113   file = nil
114   line = nil
115   pos  = nil
116   if token != 0
117     file = value[:file]
118     locator = value.locator
119     if locator.is_a?(Puppet::Pops::Parser::Locator::SubLocator)
120       # The error occurs when doing sub-parsing and the token must be transformed
121       # Transpose the local offset, length to global "coordinates"
122       global_offset, _ = locator.to_global(value.offset, value.length)
123       line = locator.locator.line_for_offset(global_offset)
124       pos = locator.locator.pos_on_line(global_offset)
125     else
126       line = value[:line]
127       pos  = value[:pos]
128     end
129   else
130     # At end of input, use what the lexer thinks is the source file
131     file = lexer.file
132   end
133   file = nil unless file.is_a?(String) && !file.empty?
134   raise Puppet::ParseErrorWithIssue.new(error, file, line, pos, nil, Issues::SYNTAX_ERROR.issue_code)
135 end
parse_file(file) click to toggle source

Parses a file expected to contain pp DSL logic.

   # File lib/puppet/pops/parser/parser_support.rb
75 def parse_file(file)
76   unless Puppet::FileSystem.exist?(file)
77     unless file =~ /\.pp$/
78       file = file + ".pp"
79     end
80   end
81   @lexer.file = file
82   _parse
83 end
parse_string(code, path = nil) click to toggle source

Parses a String of pp DSL code.

    # File lib/puppet/pops/parser/parser_support.rb
139 def parse_string(code, path = nil)
140   @lexer.lex_string(code, path)
141   _parse()
142 end
token_text(t) click to toggle source

Returns the token text of the given lexer token, or nil, if token is nil

   # File lib/puppet/pops/parser/parser_support.rb
29 def token_text t
30   return t if t.nil?
31   if t.is_a?(Factory) && t.model_class <= Model::QualifiedName
32     t['value']
33   elsif t.is_a?(Model::QualifiedName)
34     t.value
35   else
36     # else it is a lexer token
37     t[:value]
38   end
39 end
transform_calls(expressions) click to toggle source

Transforms an array of expressions containing literal name expressions to calls if followed by an expression, or expression list

    # File lib/puppet/pops/parser/parser_support.rb
185 def transform_calls(expressions)
186   # Factory transform raises an error if a non qualified name is followed by an argument list
187   # since there is no way that that can be transformed back to sanity. This occurs in situations like this:
188   #
189   #  $a = 10, notice hello
190   #
191   # where the "10, notice" forms an argument list. The parser builds an Array with the expressions and includes
192   # the comma tokens to enable the error to be reported against the first comma.
193   #
194   begin
195     Factory.transform_calls(expressions)
196   rescue Factory::ArgsToNonCallError => e
197     # e.args[1] is the first comma token in the list
198     # e.name_expr is the function name expression
199     if e.name_expr.is_a?(Factory) && e.name_expr.model_class <= Model::QualifiedName
200       error(e.args[1], _("attempt to pass argument list to the function '%{name}' which cannot be called without parentheses") % { name: e.name_expr['value'] })
201     else
202       error(e.args[1], _("illegal comma separated argument list"))
203     end
204   end
205 end
transform_resource_wo_title(left, resource, lbrace_token, rbrace_token) click to toggle source

Transforms a LEFT followed by the result of attribute_operations, this may be a call or an invalid sequence

    # File lib/puppet/pops/parser/parser_support.rb
208 def transform_resource_wo_title(left, resource, lbrace_token, rbrace_token)
209   Factory.transform_resource_wo_title(left, resource, lbrace_token, rbrace_token)
210 end