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 84 def initialize() 85 @lexer = Lexer2.new 86 @namestack = [] 87 @definitions = [] 88 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 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
# File lib/puppet/pops/parser/eparser.rb 3162 def _reduce_none(val, _values, result) 3163 val[0] 3164 end
# File lib/puppet/pops/parser/parser_support.rb 176 def add_definition(definition) 177 @definitions << definition.model 178 definition 179 end
# File lib/puppet/pops/parser/parser_support.rb 159 def aryfy(o) 160 o = [o] unless o.is_a?(Array) 161 o 162 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 46 def classname(name) 47 [namespace, name].join('::').sub(/^::/, '') 48 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 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
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
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
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
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
# File lib/puppet/pops/parser/parser_support.rb 172 def namepop() 173 @namestack.pop 174 end
# File lib/puppet/pops/parser/parser_support.rb 164 def namespace 165 @namestack.join('::') 166 end
# File lib/puppet/pops/parser/parser_support.rb 168 def namestack(name) 169 @namestack << name 170 end
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
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
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
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
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
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