# begin: ragel
begin¶ ↑
%%{
machine bel; include 'function.rl'; include 'parameter.rl'; action term_init { trace('TERM term_init') @buffers[:term_stack] = [ term() ] } action inner_term_init { trace('TERM inner_term_init') @buffers[:term_stack] << term() } action term_fx { trace('TERM term_fx') new_term = @buffers[:term_stack][-1] << @buffers[:function] @buffers[:term_stack][-1] = new_term } action term_argument { trace('TERM term_argument') arg_node = argument(@buffers[:parameter]) new_term = @buffers[:term_stack][-1] << arg_node @buffers[:term_stack][-1] = new_term @buffers[:parameter] = nil } action fxbt { trace('TERM fxbt') function_string = @buffers[:function].identifier.string_literal fpc -= function_string.length + 1 fcall inner_term; } action fxret { trace('TERM fxret') inner_term = @buffers[:term_stack].pop arg_node = argument(inner_term) new_term = @buffers[:term_stack][-1] << arg_node @buffers[:term_stack][-1] = new_term fret; } action outer_term_end { trace('TERM outer_term_end') term_stack = @buffers[:term_stack] term_stack.each { |term| term.complete = true } } action eof_parameter_argument { trace('TERM eof_parameter_argument') @buffers[:term_stack][-1].complete = false yield @buffers[:term_stack][-1] } action yield_term_ast { yield @buffers[:term_stack][-1] } inner_term := a_function >inner_term_init SP* '(' @term_fx ( a_parameter %term_argument | a_function '(' @fxbt ) ( COMMA_DELIM ( a_parameter %term_argument | a_function '(' @fxbt ) )* ')' @fxret; outer_term = a_function >term_init SP* '(' @term_fx ( a_parameter %term_argument $eof(eof_parameter_argument) | a_function '(' @fxbt ) ( COMMA_DELIM ( a_parameter %term_argument $eof(eof_parameter_argument) | a_function '(' @fxbt ) )* ')'; term := outer_term %outer_term_end %yield_term_ast NL?;
}%%
end¶ ↑
# end: ragel
require_relative '../ast/node' require_relative '../mixin/buffer' require_relative '../nonblocking_io_wrapper' require_relative '../tracer'
module BELParser
module Parsers module Expression module Term 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 = {} stack = [] data = @content.unpack('C*') 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::Expression::Term.parse(line) { |obj| puts obj.inspect } end
end
# vim: ft=ruby ts=2 sw=2: # encoding: utf-8