Class: Puppet::Pops::Parser::Parser
- Defined in:
- lib/puppet/pops/parser/parser_support.rb,
lib/puppet/pops/parser/eparser.rb
Overview
It is only concerned with parsing.
Direct Known Subclasses
Constant Summary collapse
- Racc_arg =
[ racc_action_table, racc_action_check, racc_action_default, racc_action_pointer, racc_goto_table, racc_goto_check, racc_goto_default, racc_goto_pointer, racc_nt_base, racc_reduce_table, racc_token_table, racc_shift_n, racc_reduce_n, racc_use_result_var ]
- Racc_token_to_s_table =
[ "$end", "error", "STRING", "DQPRE", "DQMID", "DQPOST", "WORD", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "SYMBOL", "FARROW", "COMMA", "TRUE", "FALSE", "EQUALS", "APPENDS", "DELETES", "LESSEQUAL", "NOTEQUAL", "DOT", "COLON", "LLCOLLECT", "RRCOLLECT", "QMARK", "WSLPAREN", "LPAREN", "RPAREN", "ISEQUAL", "GREATEREQUAL", "GREATERTHAN", "LESSTHAN", "IF", "ELSE", "DEFINE", "ELSIF", "VARIABLE", "CLASS", "INHERITS", "NODE", "BOOLEAN", "NAME", "SEMIC", "CASE", "DEFAULT", "AT", "ATAT", "LCOLLECT", "RCOLLECT", "CLASSREF", "NOT", "OR", "AND", "UNDEF", "PARROW", "PLUS", "MINUS", "TIMES", "DIV", "LSHIFT", "RSHIFT", "UMINUS", "MATCH", "NOMATCH", "REGEX", "IN_EDGE", "OUT_EDGE", "IN_EDGE_SUB", "OUT_EDGE_SUB", "IN", "UNLESS", "PIPE", "LAMBDA", "SELBRACE", "NUMBER", "HEREDOC", "SUBLOCATE", "RENDER_STRING", "RENDER_EXPR", "EPP_START", "EPP_END", "EPP_END_TRIM", "FUNCTION", "TYPE", "PRIVATE", "ATTR", "APPLICATION_R", "CONSUMES_R", "PRODUCES_R", "SITE_R", "APPLICATION", "PRODUCES", "CONSUMES", "SITE", "LOW", "HIGH", "LISTSTART", "SPLAT", "MODULO", "$start", "program", "statements", "epp_expression", "syntactic_statements", "syntactic_statement", "assignment", "relationship", "assignments", "resource", "expression", "attribute_operations", "additional_resource_bodies", "resource_bodies", "endsemi", "endcomma", "resource_body", "primary_expression", "capability_mapping", "call_function_expression", "bracketed_expression", "selector_entries", "expressions", "variable", "call_method_with_lambda_expression", "collection_expression", "case_expression", "if_expression", "unless_expression", "definition_expression", "application_expression", "hostclass_expression", "node_definition_expression", "site_definition_expression", "epp_render_expression", "function_definition", "type_alias", "type_definition", "reserved_word", "array", "hash", "regex", "quotedtext", "type", "call_function_start", "lambda", "call_method_expression", "named_access", "lambda_parameter_list", "opt_return_type", "lambda_rest", "parameters", "if_part", "else", "unless_else", "case_options", "case_option", "options_statements", "nil", "selector_entry", "selector_entry_list", "collect_query", "optional_query", "attribute_operation", "attribute_name", "keyword", "classname", "parameter_list", "opt_statements", "capability_kw", "stacked_classname", "classparent", "classnameordefault", "hostnames", "nodeparent", "hostname", "dotted_name", "name_or_number", "parameter", "untyped_parameter", "typed_parameter", "regular_parameter", "splat_parameter", "parameter_type", "optional_statements", "collection_entries", "hashpairs", "hashpair", "collection_entry", "collection_entry_keyword", "string", "dq_string", "heredoc", "dqpre", "dqrval", "dqpost", "dqmid", "text_expression", "dqtail", "sublocated_text", "epp_parameters_list", "epp_end" ]
- Racc_debug_parser =
false- 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.
Model::Factory
Instance Attribute Summary collapse
- #definitions ⇒ Object readonly
- #lexer ⇒ Object
Instance Method Summary collapse
-
#_parse ⇒ Object
private
Performs the parsing and returns the resulting model.
- #_reduce_none(val, _values, result) ⇒ Object
- #add_definition(definition) ⇒ Object
- #add_mapping(produces) ⇒ Object
- #aryfy(o) ⇒ Object
-
#classname(name) ⇒ Object
Produces the fully qualified name, with the full (current) namespace for a given name.
-
#create_empty_program ⇒ Object
Creates an empty program with a single No-op at the input’s EOF offset with 0 length.
-
#create_program(body) ⇒ Object
Creates a program with the given body.
-
#error(semantic, message) ⇒ Object
Raises a Parse error with location information.
-
#heredoc_loc(factory, start_locateabke, end_locateable = nil) ⇒ Factory
private
Mark the factory wrapped heredoc model object with location information.
-
#initialize ⇒ Parser
constructor
A new instance of Parser.
-
#loc(factory, start_locateable, end_locateable = nil) ⇒ Factory
private
Mark the factory wrapped model object with location information.
- #namepop ⇒ Object
- #namespace ⇒ Object
- #namestack(name) ⇒ Object
-
#on_error(token, value, stack) ⇒ Object
This is a callback from the generated parser (when an error occurs while parsing).
-
#parse_file(file) ⇒ Object
Parses a file expected to contain pp DSL logic.
-
#parse_string(code, path = '') ⇒ Object
Parses a String of pp DSL code.
-
#token_text(t) ⇒ Object
Returns the token text of the given lexer token, or nil, if token is nil.
-
#transform_calls(expressions) ⇒ Object
Transforms an array of expressions containing literal name expressions to calls if followed by an expression, or expression list.
-
#transform_resource_wo_title(left, resource, lbrace_token, rbrace_token) ⇒ Object
Transforms a LEFT followed by the result of attribute_operations, this may be a call or an invalid sequence.
Constructor Details
Instance Attribute Details
#definitions ⇒ Object (readonly)
25 26 27 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 25 def definitions @definitions end |
#lexer ⇒ Object
24 25 26 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 24 def lexer @lexer end |
Instance Method Details
#_parse ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Performs the parsing and returns the resulting model. The lexer holds state, and this is setup with #parse_string, or #parse_file.
237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 237 def _parse() begin @yydebug = false main = yyparse(@lexer,:scan) end return main ensure @lexer.clear @namestack = [] @definitions = [] end |
#_reduce_none(val, _values, result) ⇒ Object
3236 3237 3238 |
# File 'lib/puppet/pops/parser/eparser.rb', line 3236 def _reduce_none(val, _values, result) val[0] end |
#add_definition(definition) ⇒ Object
170 171 172 173 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 170 def add_definition(definition) @definitions << definition.current definition end |
#add_mapping(produces) ⇒ Object
175 176 177 178 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 175 def add_mapping(produces) # The actual handling of mappings happens in PopsBridge add_definition(produces) end |
#aryfy(o) ⇒ Object
153 154 155 156 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 153 def aryfy(o) o = [o] unless o.is_a?(Array) o end |
#classname(name) ⇒ Object
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.
43 44 45 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 43 def classname(name) [namespace, name].join('::').sub(/^::/, '') end |
#create_empty_program ⇒ Object
Creates an empty program with a single No-op at the input’s EOF offset with 0 length.
219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 219 def create_empty_program() locator = @lexer.locator no_op = Factory.literal(nil) # Create a synthetic NOOP token at EOF offset with 0 size. The lexer does not produce an EOF token that is # visible to the grammar rules. Creating this token is mainly to reuse the positioning logic as it # expects a token decorated with location information. token_sym, token = @lexer.emit_completed([:NOOP,'',0], locator.string.bytesize) loc(no_op, token) # Program with a Noop program = Factory.PROGRAM(no_op, [], locator) program end |
#create_program(body) ⇒ Object
Creates a program with the given body.
212 213 214 215 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 212 def create_program(body) locator = @lexer.locator Factory.PROGRAM(body, definitions, locator) end |
#error(semantic, message) ⇒ Object
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.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 50 def error(semantic, ) except = Puppet::ParseError.new() if semantic.is_a?(LexerSupport::TokenValue) except.file = semantic[:file]; except.line = semantic[:line]; except.pos = semantic[:pos]; else semantic = semantic.current() if semantic.is_a?(Factory) # Adapt the model so it is possible to get location information. # The model may not have been added to the source tree, so give it the lexer's locator # directly instead of searching for the root Program where the locator is normally stored. # if semantic.is_a?(Model::Positioned) adapter = Adapters::SourcePosAdapter.adapt(semantic) adapter.locator = @lexer.locator else adapter = nil end except.file = @lexer.locator.file except.line = adapter.line if adapter except.pos = adapter.pos if adapter end raise except end |
#heredoc_loc(factory, start_locateabke, end_locateable = nil) ⇒ Factory
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Mark the factory wrapped heredoc model object with location information
149 150 151 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 149 def heredoc_loc(factory, start_locateabke, end_locateable = nil) factory.record_heredoc_position(start_locatable, end_locatable) end |
#loc(factory, start_locateable, end_locateable = nil) ⇒ Factory
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Mark the factory wrapped model object with location information
141 142 143 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 141 def loc(factory, start_locateable, end_locateable = nil) factory.record_position(start_locateable, end_locateable) end |
#namepop ⇒ Object
166 167 168 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 166 def namepop() @namestack.pop end |
#namespace ⇒ Object
158 159 160 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 158 def namespace @namestack.join('::') end |
#namestack(name) ⇒ Object
162 163 164 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 162 def namestack(name) @namestack << name end |
#on_error(token, value, stack) ⇒ Object
This is a callback from the generated parser (when an error occurs while parsing)
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 95 def on_error(token,value,stack) if token == 0 # denotes end of file value_at = 'end of file' else value_at = "'#{value[:value]}'" end error = Issues::SYNTAX_ERROR.format(:where => value_at) error = "#{error}, token: #{token}" if @yydebug # Note, old parser had processing of "expected token here" - do not try to reinstate: # The 'expected' is only of value at end of input, otherwise any parse error involving a # start of a pair will be reported as expecting the close of the pair - e.g. "$x.each |$x {|", would # report that "seeing the '{', the '}' is expected. That would be wrong. # Real "expected" tokens are very difficult to compute (would require parsing of racc output data). Output of the stack # could help, but can require extensive backtracking and produce many options. # # The lexer should handle the "expected instead of end of file for strings, and interpolation", other expectancies # must be handled by the grammar. The lexer may have enqueued tokens far ahead - the lexer's opinion about this # is not trustworthy. # file = nil line = nil pos = nil if token != 0 file = value[:file] line = value[:line] pos = value[:pos] else # At end of input, use what the lexer thinks is the source file file = lexer.file end file = nil unless file.is_a?(String) && !file.empty? raise Puppet::ParseErrorWithIssue.new(error, file, line, pos, nil, issue_code = Issues::SYNTAX_ERROR.issue_code) end |
#parse_file(file) ⇒ Object
Parses a file expected to contain pp DSL logic.
77 78 79 80 81 82 83 84 85 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 77 def parse_file(file) unless Puppet::FileSystem.exist?(file) unless file =~ /\.pp$/ file = file + ".pp" end end @lexer.file = file _parse() end |
#parse_string(code, path = '') ⇒ Object
Parses a String of pp DSL code.
132 133 134 135 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 132 def parse_string(code, path = '') @lexer.lex_string(code, path) _parse() end |
#token_text(t) ⇒ Object
Returns the token text of the given lexer token, or nil, if token is nil
28 29 30 31 32 33 34 35 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 28 def token_text t return t if t.nil? t = t.current if t.respond_to?(:current) return t.value if t.is_a? Model::QualifiedName # else it is a lexer token t[:value] end |
#transform_calls(expressions) ⇒ Object
Transforms an array of expressions containing literal name expressions to calls if followed by an expression, or expression list
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 183 def transform_calls(expressions) # Factory transform raises an error if a non qualified name is followed by an argument list # since there is no way that that can be transformed back to sanity. This occurs in situations like this: # # $a = 10, notice hello # # where the "10, notice" forms an argument list. The parser builds an Array with the expressions and includes # the comma tokens to enable the error to be reported against the first comma. # begin Factory.transform_calls(expressions) rescue Factory::ArgsToNonCallError => e # e.args[1] is the first comma token in the list # e.name_expr is the function name expression if e.name_expr.is_a?(Model::QualifiedName) error(e.args[1], "attempt to pass argument list to the function '#{e.name_expr.value}' which cannot be called without parentheses") else error(e.args[1], "illegal comma separated argument list") end end end |
#transform_resource_wo_title(left, resource, lbrace_token, rbrace_token) ⇒ Object
Transforms a LEFT followed by the result of attribute_operations, this may be a call or an invalid sequence
206 207 208 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 206 def transform_resource_wo_title(left, resource, lbrace_token, rbrace_token) Factory.transform_resource_wo_title(left, resource, lbrace_token, rbrace_token) end |