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
Attributes
Public Class Methods
# File lib/puppet/pops/parser/parser_support.rb 85 def initialize() 86 @lexer = Lexer2.new 87 @namestack = [] 88 @definitions = [] 89 end
Public Instance Methods
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
# File lib/puppet/pops/parser/eparser.rb 3177 def _reduce_none(val, _values, result) 3178 val[0] 3179 end
# File lib/puppet/pops/parser/parser_support.rb 177 def add_definition(definition) 178 @definitions << definition.model 179 definition 180 end
# File lib/puppet/pops/parser/parser_support.rb 160 def aryfy(o) 161 o = [o] unless o.is_a?(Array) 162 o 163 end
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
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
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
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
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
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
# File lib/puppet/pops/parser/parser_support.rb 173 def namepop() 174 @namestack.pop 175 end
# File lib/puppet/pops/parser/parser_support.rb 165 def namespace 166 @namestack.join('::') 167 end
# File lib/puppet/pops/parser/parser_support.rb 169 def namestack(name) 170 @namestack << name 171 end
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
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
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
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
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
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