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
84 def initialize()
85   @lexer = Lexer2.new
86   @namestack = []
87   @definitions = []
88 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
238 def _parse()
239   begin
240     @yydebug = false
241     main = yyparse(@lexer,:scan)
242   end
243   return main
244 ensure
245   @lexer.clear
246   @namestack = []
247   @definitions = []
248 end
_reduce_none(val, _values, result) click to toggle source
     # File lib/puppet/pops/parser/eparser.rb
3162 def _reduce_none(val, _values, result)
3163   val[0]
3164 end
add_definition(definition) click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
176 def add_definition(definition)
177   @definitions << definition.model
178   definition
179 end
aryfy(o) click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
159 def aryfy(o)
160   o = [o] unless o.is_a?(Array)
161   o
162 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
46 def classname(name)
47   [namespace, name].join('::').sub(/^::/, '')
48 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
220 def create_empty_program()
221   locator = @lexer.locator
222   no_op = Factory.literal(nil)
223   # Create a synthetic NOOP token at EOF offset with 0 size. The lexer does not produce an EOF token that is
224   # visible to the grammar rules. Creating this token is mainly to reuse the positioning logic as it
225   # expects a token decorated with location information.
226   _, token = @lexer.emit_completed([:NOOP,'',0], locator.string.bytesize)
227   loc(no_op, token)
228   # Program with a Noop
229   program = Factory.PROGRAM(no_op, [], locator)
230   program
231 end
create_program(body) click to toggle source

Creates a program with the given body.

    # File lib/puppet/pops/parser/parser_support.rb
213 def create_program(body)
214   locator = @lexer.locator
215   Factory.PROGRAM(body, definitions, locator)
216 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
53 def error(semantic, message)
54   except = Puppet::ParseError.new(message)
55   if semantic.is_a?(LexerSupport::TokenValue)
56     except.file = semantic[:file];
57     except.line = semantic[:line];
58     except.pos = semantic[:pos];
59   else
60     locator = @lexer.locator
61     except.file = locator.file
62     if semantic.is_a?(Factory)
63       offset = semantic['offset']
64       unless offset.nil?
65         except.line = locator.line_for_offset(offset)
66         except.pos = locator.pos_on_line(offset)
67       end
68     end
69   end
70   raise except
71 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
155 def heredoc_loc(factory, start_locatable, end_locatable = nil)
156   factory.record_heredoc_position(start_locatable, end_locatable)
157 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
147 def loc(factory, start_locatable, end_locatable = nil)
148   factory.record_position(@lexer.locator, start_locatable, end_locatable)
149 end
namepop() click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
172 def namepop()
173   @namestack.pop
174 end
namespace() click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
164 def namespace
165   @namestack.join('::')
166 end
namestack(name) click to toggle source
    # File lib/puppet/pops/parser/parser_support.rb
168 def namestack(name)
169   @namestack << name
170 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
 92 def on_error(token,value,stack)
 93   if token == 0 # denotes end of file
 94     value_at = 'end of input'
 95   else
 96     value_at = "'#{value[:value]}'"
 97   end
 98   error = Issues::SYNTAX_ERROR.format(:where => value_at)
 99   error = "#{error}, token: #{token}" if @yydebug
100 
101   # Note, old parser had processing of "expected token here" - do not try to reinstate:
102   # The 'expected' is only of value at end of input, otherwise any parse error involving a
103   # start of a pair will be reported as expecting the close of the pair - e.g. "$x.each |$x {|", would
104   # report that "seeing the '{', the '}' is expected. That would be wrong.
105   # Real "expected" tokens are very difficult to compute (would require parsing of racc output data). Output of the stack
106   # could help, but can require extensive backtracking and produce many options.
107   #
108   # The lexer should handle the "expected instead of end of file for strings, and interpolation", other expectancies
109   # must be handled by the grammar. The lexer may have enqueued tokens far ahead - the lexer's opinion about this
110   # is not trustworthy.
111   #
112   file = nil
113   line = nil
114   pos  = nil
115   if token != 0
116     file = value[:file]
117     locator = value.locator
118     if locator.is_a?(Puppet::Pops::Parser::Locator::SubLocator)
119       # The error occurs when doing sub-parsing and the token must be transformed
120       # Transpose the local offset, length to global "coordinates"
121       global_offset, _ = locator.to_global(value.offset, value.length)
122       line = locator.locator.line_for_offset(global_offset)
123       pos = locator.locator.pos_on_line(global_offset)
124     else
125       line = value[:line]
126       pos  = value[:pos]
127     end
128   else
129     # At end of input, use what the lexer thinks is the source file
130     file = lexer.file
131   end
132   file = nil unless file.is_a?(String) && !file.empty?
133   raise Puppet::ParseErrorWithIssue.new(error, file, line, pos, nil, Issues::SYNTAX_ERROR.issue_code)
134 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
74 def parse_file(file)
75   unless Puppet::FileSystem.exist?(file)
76     unless file =~ /\.pp$/
77       file = file + ".pp"
78     end
79   end
80   @lexer.file = file
81   _parse
82 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
138 def parse_string(code, path = nil)
139   @lexer.lex_string(code, path)
140   _parse()
141 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
28 def token_text t
29   return t if t.nil?
30   if t.is_a?(Factory) && t.model_class <= Model::QualifiedName
31     t['value']
32   elsif t.is_a?(Model::QualifiedName)
33     t.value
34   else
35     # else it is a lexer token
36     t[:value]
37   end
38 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
184 def transform_calls(expressions)
185   # Factory transform raises an error if a non qualified name is followed by an argument list
186   # since there is no way that that can be transformed back to sanity. This occurs in situations like this:
187   #
188   #  $a = 10, notice hello
189   #
190   # where the "10, notice" forms an argument list. The parser builds an Array with the expressions and includes
191   # the comma tokens to enable the error to be reported against the first comma.
192   #
193   begin
194     Factory.transform_calls(expressions)
195   rescue Factory::ArgsToNonCallError => e
196     # e.args[1] is the first comma token in the list
197     # e.name_expr is the function name expression
198     if e.name_expr.is_a?(Factory) && e.name_expr.model_class <= Model::QualifiedName
199       error(e.args[1], _("attempt to pass argument list to the function '%{name}' which cannot be called without parentheses") % { name: e.name_expr['value'] })
200     else
201       error(e.args[1], _("illegal comma separated argument list"))
202     end
203   end
204 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
207 def transform_resource_wo_title(left, resource, lbrace_token, rbrace_token)
208   Factory.transform_resource_wo_title(left, resource, lbrace_token, rbrace_token)
209 end