Class: Puppet::Pops::Parser::Parser
- Includes:
- Resource::TypeCollectionHelper
- Defined in:
- lib/puppet/pops/parser/parser_support.rb,
lib/puppet/pops/parser/eparser.rb
Overview
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.
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", "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", "LOW", "HIGH", "CALL", "LISTSTART", "MODULO", "TITLE_COLON", "CASE_COLON", "$start", "program", "statements", "epp_expression", "nil", "syntactic_statements", "syntactic_statement", "any_expression", "relationship_expression", "resource_expression", "expression", "higher_precedence", "expressions", "selector_entries", "call_function_expression", "primary_expression", "literal_expression", "variable", "call_method_with_lambda_expression", "collection_expression", "case_expression", "if_expression", "unless_expression", "definition_expression", "hostclass_expression", "node_definition_expression", "epp_render_expression", "function_definition", "array", "boolean", "default", "hash", "regex", "text_or_name", "number", "type", "undef", "name", "quotedtext", "endcomma", "lambda", "call_method_expression", "named_access", "lambda_parameter_list", "lambda_rest", "parameters", "if_part", "else", "unless_else", "case_options", "case_option", "case_colon", "selector_entry", "selector_entry_list", "at", "resourceinstances", "endsemi", "attribute_operations", "resourceinst", "title_colon", "collect_query", "optional_query", "attribute_operation", "attribute_name", "keyword", "classname", "parameter_list", "opt_statements", "stacked_classname", "classparent", "classnameordefault", "hostnames", "nodeparent", "hostname", "dotted_name", "parameter", "hashpairs", "hashpair", "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.
Puppet::Pops::Model::Factory
- Model =
Puppet::Pops::Model
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
- #aryfy(o) ⇒ Object
-
#classname(name) ⇒ Object
Produces the fully qualified name, with the full (current) namespace for a given name.
-
#create_program(body) ⇒ Object
If there are definitions that require initialization a Program is produced, else the body.
-
#doc(factory, doc_string) ⇒ Puppet::Pops::Model::Factory
private
Associate documentation with the factory wrapped model object.
-
#error(value, message, options = {}) ⇒ Object
Raises a Parse error.
- #heredoc_loc(factory, start_locateabke, end_locateable = nil) ⇒ Object
-
#initialize ⇒ Parser
constructor
A new instance of Parser.
-
#loc(factory, start_locateable, end_locateable = nil) ⇒ Puppet::Pops::Model::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 grammar (when an error occurs while parsing) TODO Picks up origin information from the lexer, probably needs this from the caller instead (for code strings, and when start line is not line 1 in a code string (or file), etc.).
-
#parse_file(file) ⇒ Object
Parses a file expected to contain pp DSL logic.
-
#parse_string(code) ⇒ 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) ⇒ Object
Transforms a LEFT followed by the result of attribute_operations, this may be a call or an invalid sequence.
Methods included from Resource::TypeCollectionHelper
Constructor Details
#initialize ⇒ Parser
Returns a new instance of Parser.
76 77 78 79 80 81 82 83 84 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 76 def initialize() # Since the parser is not responsible for importing (removed), and does not perform linking, # and there is no syntax that requires knowing if something referenced exists, it is safe # to assume that no environment is needed when parsing. (All that comes later). # @lexer = Puppet::Pops::Parser::Lexer2.new @namestack = [] @definitions = [] end |
Instance Attribute Details
#definitions ⇒ Object (readonly)
27 28 29 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 27 def definitions @definitions end |
#lexer ⇒ Object
26 27 28 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 26 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.
TODO: Drop support for parsing a ruby file this way (should be done where it is decided
which file to load/run (i.e. loaders), and initial file to run
TODO: deal with options containing origin (i.e. parsing a string from externally known location). TODO: should return the model, not a Hostclass
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 210 def _parse() begin @yydebug = false main = yyparse(@lexer,:scan) # #Commented out now because this hides problems in the racc grammar while developing # # TODO include this when test coverage is good enough. # rescue Puppet::ParseError => except # except.line ||= @lexer.line # except.file ||= @lexer.file # except.pos ||= @lexer.pos # raise except # rescue => except # raise Puppet::ParseError.new(except.message, @lexer.file, @lexer.line, @lexer.pos, except) end return main ensure @lexer.clear @namestack = [] @definitions = [] end |
#_reduce_none(val, _values, result) ⇒ Object
2620 2621 2622 |
# File 'lib/puppet/pops/parser/eparser.rb', line 2620 def _reduce_none(val, _values, result) val[0] end |
#add_definition(definition) ⇒ Object
177 178 179 180 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 177 def add_definition(definition) @definitions << definition.current definition end |
#aryfy(o) ⇒ Object
160 161 162 163 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 160 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.
45 46 47 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 45 def classname(name) [namespace, name].join("::").sub(/^::/, '') end |
#create_program(body) ⇒ Object
If there are definitions that require initialization a Program is produced, else the body
195 196 197 198 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 195 def create_program(body) locator = @lexer.locator Factory.PROGRAM(body, definitions, locator) end |
#doc(factory, doc_string) ⇒ Puppet::Pops::Model::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.
Associate documentation with the factory wrapped model object.
156 157 158 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 156 def doc factory, doc_string factory.doc = doc_string end |
#error(value, message, options = {}) ⇒ Object
Raises a Parse error.
56 57 58 59 60 61 62 63 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 56 def error(value, , = {}) except = Puppet::ParseError.new() except.line = [:line] || value[:line] except.file = [:file] || value[:file] # @lexer.file except.pos = [:pos] || value[:pos] # @lexer.pos raise except end |
#heredoc_loc(factory, start_locateabke, end_locateable = nil) ⇒ Object
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) ⇒ Puppet::Pops::Model::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.
the lexer produces :line for token, but no offset or length
Mark the factory wrapped model object with location information
145 146 147 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 145 def loc(factory, start_locateable, end_locateable = nil) factory.record_position(start_locateable, end_locateable) end |
#namepop ⇒ Object
173 174 175 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 173 def namepop() @namestack.pop end |
#namespace ⇒ Object
165 166 167 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 165 def namespace @namestack.join('::') end |
#namestack(name) ⇒ Object
169 170 171 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 169 def namestack(name) @namestack << name end |
#on_error(token, value, stack) ⇒ Object
This is a callback from the generated grammar (when an error occurs while parsing) TODO Picks up origin information from the lexer, probably needs this from the caller instead
(for code strings, and when start line is not line 1 in a code string (or file), etc.)
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 129 130 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 96 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 = "Syntax error at #{value_at}" # 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. # # if token == 0 && brace = @lexer.expected # error += "; expected '#{brace}'" # end except = Puppet::ParseError.new(error) if token != 0 path = value[:file] except.line = value[:line] except.pos = value[:pos] else # At end of input, use what the lexer thinks is the source file path = lexer.file end except.file = path if path.is_a?(String) && !path.empty? raise except end |
#parse_file(file) ⇒ Object
Parses a file expected to contain pp DSL logic.
66 67 68 69 70 71 72 73 74 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 66 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) ⇒ Object
make it possible to pass a given origin
Parses a String of pp DSL code.
135 136 137 138 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 135 def parse_string(code) @lexer.string = code _parse() end |
#token_text(t) ⇒ Object
Returns the token text of the given lexer token, or nil, if token is nil
30 31 32 33 34 35 36 37 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 30 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
185 186 187 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 185 def transform_calls(expressions) Factory.transform_calls(expressions) end |
#transform_resource_wo_title(left, resource) ⇒ Object
Transforms a LEFT followed by the result of attribute_operations, this may be a call or an invalid sequence
190 191 192 |
# File 'lib/puppet/pops/parser/parser_support.rb', line 190 def transform_resource_wo_title(left, resource) Factory.transform_resource_wo_title(left, resource) end |