class Vernacular::AST::ASTParser
Handles monkeying around with the `parser` gem to get it to handle the various modifications that users can configure `Vernacular` to perform.
Public Class Methods
parse(string)
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 23 def parse(string) parser.reset buffer = Parser::Base.send(:setup_source_buffer, '(string)', 1, string, @parser.default_encoding) parser.parse(buffer) end
parser()
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 30 def parser @parser ||= new.parser end
Public Instance Methods
parser()
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 8 def parser source = parser_source ast_modifiers.each do |modifier| modifier.parser_extensions.each do |parser_extension| source = extend_parser(source, parser_extension) end end write_parser(source) load 'vernacular/ast/parser.rb' Parser::Vernacular.new(builder) end
Private Instance Methods
ast_modifiers()
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 37 def ast_modifiers Vernacular.modifiers.grep(ASTModifier) end
builder()
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 41 def builder modifiers = ast_modifiers Class.new(Parser::Builders::Default) do modifiers.each do |modifier| modifier.builder_extensions.each do |builder_extension| define_method(builder_extension.method, &builder_extension.block) end end end.new end
compile_parser(filepath)
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 53 def compile_parser(filepath) output = PARSER_PATH exec_path = Gem.activate_bin_path('racc', 'racc', []) `#{exec_path} --superclass=Parser::Base -o #{output} #{filepath}` parser_name = "Ruby#{parser_version}" File.write(output, File.read(output).gsub(parser_name, 'Vernacular')) end
extend_parser(source, parser_extension)
click to toggle source
rubocop:disable Metrics/MethodLength
# File lib/vernacular/ast/ast_parser.rb, line 63 def extend_parser(source, parser_extension) needle = "#{parser_extension.symbol}:" pattern = /\A\s+#{needle}/ source.split("\n").each_with_object([]) do |line, edited| if line.match?(pattern) lhs, rhs = line.split(needle) edited << "#{lhs}#{needle} #{parser_extension.pattern}\n" \ "{\n#{parser_extension.code}\n}\n#{lhs}|#{rhs}" else edited << line end end.join("\n") end
parser_source()
click to toggle source
rubocop:enable Metrics/MethodLength
# File lib/vernacular/ast/ast_parser.rb, line 79 def parser_source filepath, = Parser::Base.method(:parse).source_location grammar_filepath = "../../parser/ruby#{parser_version}.y" File.read(File.expand_path(grammar_filepath, filepath)) end
parser_version()
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 85 def parser_version @parser_version ||= RUBY_VERSION.gsub(/\A(\d)\.(\d).+/, '\1\2') end
write_parser(source)
click to toggle source
# File lib/vernacular/ast/ast_parser.rb, line 89 def write_parser(source) file = Tempfile.new(['parser-', '.y']) file.write(source) compile_parser(file.path) ensure file.close file.unlink end