# begin: ragel =begin %%{ machine bel; include 'common.rl'; action string_end { trace('STRING string_end') completed = @string_opened && @string_closed chars = data[p_start...p_end] ast_node = string(utf8_string(chars), complete: true) @buffers[:string] = ast_node } action yield_string { trace('STRING yield_string') yield @buffers[:string] } action start_string { trace('STRING start_string') @string_opened = true p_start = p } action stop_string { trace('STRING stop_string') @string_closed = true p_end = p } action eof_string { trace('STRING eof_string') p_end = p chars = data[p_start...p_end] ast_node = string(utf8_string(chars), complete: false) @buffers[:string] = ast_node } action string_node_eof { trace('STRING string_node_eof') yield @buffers[:string] } action a_string_err { trace('STRING a_string_err') p_end = p chars = data[p_start...p_end] ast_node = string(utf8_string(chars), complete: false) @buffers[:string] = ast_node } action string_node_err { trace('STRING string_node_err') p_end = p chars = data[p_start...p_end] ast_node = string(utf8_string(chars), complete: false) yield ast_node } #single = # WS* SQ (NOT_SQESC | ESCAPED)* # >start_string # $eof(eof_string) # %stop_string # %string_end # SQ # ; double = WS* DQ (NOT_DQESC | ESCAPED)* >start_string $eof(eof_string) %stop_string %string_end DQ ; a_string = #(single | double) double $err(a_string_err) ; string_node := ( #single | double ) $err(string_node_err) @eof(string_node_eof) @yield_string ; }%% =end # end: ragel # ('\"' | ^(0 .. 31 | 34))* ^'\\"' require_relative '../ast/node' require_relative '../mixin/buffer' require_relative '../nonblocking_io_wrapper' require_relative '../tracer' module BELParser module Parsers module Common module String class << self MAX_LENGTH = 1024 * 128 # 128K def parse(content) return nil unless content Parser.new(content).each do |obj| yield obj end end end private class Parser include Enumerable include BELParser::Parsers::Buffer include BELParser::Parsers::AST::Sexp include BELParser::Parsers::Tracer def initialize(content) @content = content # begin: ragel %% write data; # end: ragel end def each @buffers = {} @incomplete = {} @string_opened = false @string_closed = false data = @content.unpack('C*') p_start = 0 p_end = 0 p = 0 pe = data.length eof = data.length # begin: ragel %% write init; %% write exec; # end: ragel end end end end end end if __FILE__ == $0 $stdin.each_line do |line| BELParser::Parsers::Common::String.parse(line) { |obj| puts obj.inspect } end end # vim: ft=ruby ts=2 sw=2: # encoding: utf-8