rsec-0.4.2/ 0000755 0001751 0001750 00000000000 13176057521 011503 5 ustar mmoll mmoll rsec-0.4.2/rsec.gemspec 0000644 0001751 0001750 00000003564 13176057521 014014 0 ustar mmoll mmoll #########################################################
# This file has been automatically generated by gem2tgz #
#########################################################
# -*- encoding: utf-8 -*-
# stub: rsec 0.4.2 ruby lib
Gem::Specification.new do |s|
s.name = "rsec".freeze
s.version = "0.4.2"
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
s.authors = ["NS".freeze]
s.date = "2016-09-25"
s.description = "Easy and extreme fast dynamic PEG parser combinator.".freeze
s.extra_rdoc_files = ["readme.rdoc".freeze]
s.files = ["bench/bench.rb".freeze, "bench/little.rb".freeze, "bench/profile.rb".freeze, "examples/arithmetic.rb".freeze, "examples/bnf.rb".freeze, "examples/c_minus.rb".freeze, "examples/hello.scm".freeze, "examples/little_markdown.rb".freeze, "examples/nasm_manual.rb".freeze, "examples/s_exp.rb".freeze, "examples/scheme.rb".freeze, "examples/slow_json.rb".freeze, "lib/rsec.rb".freeze, "lib/rsec/helpers.rb".freeze, "lib/rsec/parser.rb".freeze, "lib/rsec/parsers/join.rb".freeze, "lib/rsec/parsers/misc.rb".freeze, "lib/rsec/parsers/prim.rb".freeze, "lib/rsec/parsers/repeat.rb".freeze, "lib/rsec/parsers/seq.rb".freeze, "lib/rsec/utils.rb".freeze, "license.txt".freeze, "readme.rdoc".freeze, "test/helpers.rb".freeze, "test/test_branch.rb".freeze, "test/test_examples.rb".freeze, "test/test_join.rb".freeze, "test/test_lookahead.rb".freeze, "test/test_misc.rb".freeze, "test/test_one_of.rb".freeze, "test/test_pattern.rb".freeze, "test/test_prim.rb".freeze, "test/test_repeat.rb".freeze, "test/test_rsec.rb".freeze, "test/test_seq.rb".freeze]
s.homepage = "http://rsec.herokuapp.com".freeze
s.required_ruby_version = Gem::Requirement.new(">= 1.9.1".freeze)
s.rubygems_version = "2.5.2.1".freeze
s.summary = "Extreme Fast Parser Combinator for Ruby".freeze
end
rsec-0.4.2/test/ 0000755 0001751 0001750 00000000000 13176057521 012462 5 ustar mmoll mmoll rsec-0.4.2/test/test_seq.rb 0000644 0001751 0001750 00000002205 13176057521 014635 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestSeq < TC
def test_seq
p = seq('a', 'b', 'c')
ase ['a','b','c'], p.parse('abc')
ase INVALID, p.parse('a')
ase INVALID, p.parse('b')
ase INVALID, p.parse('c')
ase INVALID, p.parse('bc')
ase INVALID, p.parse('ab')
end
def test_seq_
p = seq_('abc', 'ef', 'vv')
ase %w[abc ef vv], p.parse("abc ef vv")
p = seq_('abc', 'ef', 'vv', skip: /\s+/)
ase %w[abc ef vv], p.parse("abc ef vv")
ase INVALID, p.parse("abcef vv")
end
def test_seq_mix
p = seq('e', seq_('a','b','c'), 'd')
ase ['e', ['a','b','c'], 'd'], p.parse('eabcd')
end
def test_seq_one
p = seq('a', 'b', 'c')[1]
ase 'b', p.parse('abc')
p = seq('abc', /\s*/, 'd')[2]
ase 'd', p.parse('abc d')
end
def test_seq_one_
p = seq_('a', 'b', 'c')[1]
ase 'b', p.parse('a bc')
p = seq_('abc', /\s*/, 'd')[2]
ase 'd', p.parse('abc d')
end
def test_fall
p = 'a'.r >> 'b'
ase 'b', p.parse!('ab')
p = p << 'c'
ase 'b', p.parse!('abc')
p = p._?
ase ['b'], p.eof.parse!('abc')
ase [], p.eof.parse!('')
end
end
rsec-0.4.2/test/test_rsec.rb 0000644 0001751 0001750 00000000421 13176057521 014777 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestRsec < TC
def test_try_skip_pattern
p = Rsec.try_skip_pattern 'abc'.r
ase Rsec::SkipPattern, p.class
p = Rsec.try_skip_pattern 'abc'.r.until
ase Rsec::SkipUntilPattern, p.class
end
end
rsec-0.4.2/test/test_repeat.rb 0000644 0001751 0001750 00000002216 13176057521 015327 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestRepeat < TC
def test_maybe
[:_?, :maybe].each do |m|
p = seq('v', 'q').send m
ase [], p.parse('')
ase INVALID, p.eof.parse('v')
ase [['v', 'q']], p.parse('vq')
# with map block
p = seq('v', 'q').maybe {|x| x.empty? ? 'bad' : 'good' }
ase 'good', p.parse('vq')
end
end
def test_multiply
p = ('ce'.r * 3).eof
ase ['ce','ce','ce'], (p.parse 'cecece')
ase INVALID, (p.parse 'cece')
ase INVALID, (p.parse 'cececece')
p = ('ce'.r * 0).eof
ase [], (p.parse '')
ase INVALID, (p.parse 'ce')
end
def test_range
p = ('ce'.r * (2..3)).eof
ase INVALID, (p.parse 'ce')
ase ['ce','ce'], (p.parse 'cece')
ase INVALID, (p.parse 'cececece')
end
def test_inf
p = ('ce'.r * (3..-1)).eof
ase INVALID,
(p.parse 'cece')
ase ['ce','ce','ce'],
(p.parse 'cecece')
ase ['ce','ce','ce','ce','ce'],
(p.parse 'cecececece')
end
def test_star
p = '*'.r.star
ase [], p.parse('')
ase %w[* * *], p.parse('***')
end
end
rsec-0.4.2/test/test_prim.rb 0000644 0001751 0001750 00000003163 13176057521 015020 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestPrim < TC
def test_floating
[:double].each do |ty|
p = prim ty
ase INVALID, p.parse('d')
ase 3.2e5.round, p.parse('+3.2e5').round
ase INVALID, p.parse(' 4.8')
p = prim ty, allowed_sign: ''
ase 1.5e-3.round(4), p.parse('1.5E-3').round(4)
ase INVALID, p.parse('+3.0')
p = prim ty, allowed_sign: '-'
ase (-5.0).round, p.parse('-5').round
ase INVALID, p.parse('-')
ase INVALID, p.parse('+5')
ase 5.0.round, p.parse('5').round
# with map block
p = prim(ty){|x| x * 2 }
ase 100.0.round, p.parse('50').round
end
end
def test_hex_floating
return # NOTE Ruby 1.9.3 removed Float() from hex values
[:hex_double].each do |ty|
p = prim ty
ase Float('0x3.2').round(4), p.parse('0x3.2').round(4)
# with map block
p = prim(ty){|x| x - 0.1 }
ase (Float('0x3.2') - 0.1).round(4), p.parse('0x3.2').round(4)
end
end
def test_integer
[:int32, :unsigned_int32, :int64, :unsigned_int64].each do |ty|
p = prim ty
ase 432, p.parse('432')
p = prim ty, base: 4
ase '120'.to_i(4), p.parse('120')
p = prim ty, base: 35
ase '1ax'.to_i(35), p.parse('1ax')
end
p = prim :int32, allowed_signs: '-'
ase INVALID, p.parse('+12')
ase INVALID, p.parse('123333333333333333333333333333333333')
ase INVALID, p.parse('-')
ase -49, p.parse('-49')
assert_raise RuntimeError do
prim :unsigned_int32, allowed_signs: '+-'
end
end
end
rsec-0.4.2/test/test_pattern.rb 0000644 0001751 0001750 00000001737 13176057521 015533 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestPattern < TC
def test_create
p1 = 'x'.r
asp 'x', p1
p1 = 'abc'.r
asp 'abc', p1
asr do
p1.eof.parse! 'abcd'
end
ase INVALID, p1.eof.parse('abcd')
asr do
p1.eof.parse! 'xabc'
end
ase INVALID, p1.eof.parse('xabc')
# with map block
p = 'x'.r{ 'y' }
ase INVALID, p.parse('y')
ase 'y', p.parse('x')
end
def test_until
p = 'ef'.r.until
asp 'xef', p
asp "x\nef", p
p = 'e'.r.until
asp 'xe', p
asp "x\ne", p
# with map block
p = 'e'.r.until{|s| s*2}
ase 'xexe', p.parse('xe')
end
def test_word
p = word('abc')
ase INVALID, p.parse('abcd')
ase INVALID, seq_(p, 'd').parse('abcd')
ase 'abc', p.parse('abc')
ase ['abc', 'd'], seq_(p, 'd').parse('abc d')
end
def test_symbol
p = symbol('*')
ase '*', p.parse(' * ')
end
end
rsec-0.4.2/test/test_one_of.rb 0000644 0001751 0001750 00000001416 13176057521 015315 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestOneOf < TC
def test_one_of
p = one_of('abcd')
ase 'c', p.parse('c')
ase INVALID, p.parse('e')
p = one_of('+=')
ase '=', p.parse('=')
begin
p = one_of('')
assert false, "should raise exception for empty string"
rescue
end
# with map block
p = one_of('x+'){|v| v * 2}
ase '++', p.parse('+')
end
def test_one_of_
p = one_of_('abcd')
ase 'a', p.parse('a')
ase INVALID, p.parse('e')
ase 'd', p.parse(' d ')
ase 'a', p.parse(' a')
ase 'c', p.parse('c ')
assert_raise(ArgumentError) {
p = one_of_('')
}
# with map block
p = one_of_('w'){'v'}
ase 'v', p.parse('w')
end
end
rsec-0.4.2/test/test_misc.rb 0000644 0001751 0001750 00000002255 13176057521 015005 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestMisc < TC
def test_lazy
p1 = nil
p2 = lazy{p1}
p1 = '3'.r
asp '3', p2
p1 = '4'.r
asp '3', p2
p2 = lazy{p7} # don't have to define p7 before lazy
p7 = '5'.r
asp '5',p2
end
def test_eof
p = ''.r.eof
asp '', p
ase INVALID, p.parse('a')
p = seq('a', 'b').eof
ase INVALID, p.parse('abc')
ase ['a', 'b'], p.parse('ab')
end
def test_cache
p1 = seq('a', seq('b', 'c'))
p = seq(p1.cached, 'd')
ase [['a',['b','c']],'d'], p.parse('abcd')
# with map block
p = seq(p1.cached{ 'mapped' }, 'd')
ase ['mapped', 'd'], p.parse('abcd')
end
def test_map
p = /\w/.r.map{|n| n*2}
ase 'bb', p.parse('b')
ase INVALID, p.parse('.')
end
def test_fail
p = 'v'.r.fail 'omg!'
p.eof.parse! 'u'
assert false, "should raise syntax error"
rescue Rsec::SyntaxError => e
assert e.to_s.index 'omg!'
end
def test_fail_with_block
p = 'v'.r.fail('omg!'){ 'should fail' }
p.eof.parse! 'u'
assert false, "should raise syntax error"
rescue Rsec::SyntaxError => e
assert e.to_s.index 'omg!'
end
end
rsec-0.4.2/test/test_lookahead.rb 0000644 0001751 0001750 00000000704 13176057521 015776 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestLookAhead < TC
def test_lookahead
p1 = 'a'.r & 'b'
p2 = /\w/.r
p = seq(p1, p2)
ase ['a', 'b'], p.parse('ab')
ase INVALID, p.parse('ac')
p1 = 'a'.r ^ 'b'
p = seq(p1, p2)
ase ['a', 'c'], p.parse('ac')
ase INVALID, p.parse('ab')
end
def test_negative_lookahead
p = 'a'.r ^ 'b'
ase 'a', p.parse('ac')
ase INVALID, p.parse('ab')
end
end
rsec-0.4.2/test/test_join.rb 0000644 0001751 0001750 00000002613 13176057521 015007 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestJoin < TC
def test_join
p0 = /\w{1,3}/.r.join '+'
ase ['abc'], p0.eof.parse('abc')
ase ['a','+','bc','+','d'], p0.parse('a+bc+d')
ase INVALID, p0.eof.parse('a+ bc+d')
ase INVALID, p0.eof.parse('a+b+')
p1 = seq(/[a-z]{1,3}/, '3')[0].join seq(/\s/.r, '+', /\s/)[1]
ase ['abc'], p1.eof.parse('abc3')
ase %w[a + bc + d], p1.parse('a3 + bc3 + d3')
ase INVALID, p1.eof.parse('a+b+')
end
def test_nest_join
p = 'a'.r.join(/\s*\*\s*/.r).join(/\s*\+\s*/.r)
ase [['a'], ' + ', ['a', ' * ', 'a'], ' +', ['a']], p.parse('a + a * a +a')
end
def test_join_with_mapping_block
p = 'a'.r.join('+'){|res| res.grep /\+/ }
ase ['+', '+'], p.parse('a+a+a')
ase [], p.parse('a')
end
def test_join_even
p = 'a'.r.join('+').even
ase %w[a a a], p.parse('a+a+a')
ase %w[a], p.parse('a')
ase INVALID, p.eof.parse('a+')
ase INVALID, p.parse('b')
ase INVALID, p.parse('')
end
def test_join_odd
p = 'a'.r.join('+').odd
ase %w[+ +], p.parse('a+a+a')
ase [], p.parse('a')
ase INVALID, p.parse('')
ase INVALID, p.parse('+')
ase INVALID, p.parse('b')
end
def test_nest_join_even_odd
p = 'a'.r.join('+').odd.join('*')
ase [['+'], '*', []], p.parse('a+a*a')
p = 'a'.r.join('+').even.join('*')
ase [['a','a'], '*', ['a']], p.parse('a+a*a')
end
end
rsec-0.4.2/test/test_examples.rb 0000644 0001751 0001750 00000001516 13176057521 015667 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
$:.unshift "#{File.dirname __FILE__}/../examples"
require "arithmetic"
require "s_exp"
class TestExamples < TC
def initialize *xs
super(*xs)
@a = arithmetic()
@s_exp = s_exp()
end
def test_arithmetic
# step by step
s = '1'
ase eval(s), @a.parse(s)
s = '3+ 2'
ase eval(s), @a.parse(s)
s = '5-2*1'
ase eval(s), @a.parse(s)
s = '(2)'
ase eval(s), @a.parse(s)
s = '1+(2- (3+ 4))/5 * 2*4 +1'
ase eval(s), @a.parse(s)
end
def test_s_exp
res = @s_exp.parse! '(a 3 4.3 (add 1 3) (minus (multi 4 5)))'
expected = ['a', 3.0, 4.3, ['add', 1, 3], ['minus', ['multi', 4, 5]]]
ase expected, res
res = @s_exp.parse! '(a (3) ce2 (add 1 3))'
expected = ['a', 3.0, 'ce2', ['add', 1, 3]]
ase expected, res
end
end
rsec-0.4.2/test/test_branch.rb 0000644 0001751 0001750 00000000455 13176057521 015307 0 ustar mmoll mmoll require "#{File.dirname(__FILE__)}/helpers.rb"
class TestBranch < TC
def test_branch
p = 'a'.r | /\d+/ | seq('c', 'd')
ase ['c','d'], p.parse('cd')
ase '3', p.parse('3')
ase INVALID, p.parse('c')
p = 'x'.r | 'y'
ase INVALID, p.parse('')
ase 'y', p.parse('y')
end
end
rsec-0.4.2/test/helpers.rb 0000644 0001751 0001750 00000000634 13176057521 014454 0 ustar mmoll mmoll # coding: utf-8
$:.unshift "#{File.dirname(__FILE__)}/../lib"
require "rsec"
include Rsec::Helpers
require "test/unit"
TC = Test::Unit::TestCase
class TC
INVALID = Rsec::INVALID
end
module Test::Unit::Assertions
alias ase assert_equal
def asr
assert_raise(Rsec::SyntaxError) { yield }
end
# assert parse returns s
def asp s, p
assert_equal(s, p.parse(s))
end
end
rsec-0.4.2/readme.rdoc 0000644 0001751 0001750 00000000543 13176057521 013613 0 ustar mmoll mmoll == Parser / Regexp Combinator for Ruby.
Easier and faster than treetop / rex+racc.
It's ruby1.9 only.
== License
As Ruby's
== Install
The pure Ruby gem is fast enough (about 10+x faster than treetop generated code):
gem in rsec
== Doc
http://rsec.herokuapp.com
== Code
http://github.com/luikore/rsec/tree/master
rsec-0.4.2/license.txt 0000644 0001751 0001750 00000000011 13176057521 013656 0 ustar mmoll mmoll As Ruby's rsec-0.4.2/lib/ 0000755 0001751 0001750 00000000000 13176057521 012251 5 ustar mmoll mmoll rsec-0.4.2/lib/rsec/ 0000755 0001751 0001750 00000000000 13176057521 013205 5 ustar mmoll mmoll rsec-0.4.2/lib/rsec/utils.rb 0000644 0001751 0001750 00000005376 13176057521 014705 0 ustar mmoll mmoll # coding: utf-8
module Rsec #:nodoc:
# error class for rescue
class SyntaxError < StandardError
attr_reader :msg, :line_text, :line, :col
# constructor
def initialize msg, line_text, line, col
@msg, @line_text, @line, @col = msg, line_text, line, col
end
# info with source position
def to_s
%Q<#@msg\n#@line_text\n#{' ' * @col}^>
end
end
# parse context inherits from StringScanner
#
# attributes:
#
# [R] string: string to parse # [RW] pos: current position # [R] source: source file name # [R] current_line_text: current line text # [R] cache: for memoization #class ParseContext < StringScanner attr_reader :source, :cache, :last_fail_pos attr_accessor :attr_names def initialize str, source super(str) @source = source @cache = {} @last_fail_pos = 0 @last_fail_mask = 0 end # clear packrat parser cache def clear_cache @cache.clear end # add fail message def on_fail mask if pos > @last_fail_pos @last_fail_pos = pos @last_fail_mask = mask elsif pos == @last_fail_pos @last_fail_mask |= mask end end # generate parse error def generate_error source if self.pos <= @last_fail_pos line = line @last_fail_pos col = col @last_fail_pos line_text = line_text @last_fail_pos expect_tokens = Fail.get_tokens @last_fail_mask expects = ", expect token [ #{expect_tokens.join ' | '} ]" else line = line pos col = col pos line_text = line_text pos expects = nil end msg = "\nin #{source}:#{line} at #{col}#{expects}" SyntaxError.new msg, line_text, line, col end # get line number def line pos string[0...pos].count("\n") + 1 end # get column number: position in line def col pos return 1 if pos == 0 newline_pos = string.rindex "\n", pos - 1 if newline_pos pos - newline_pos else pos + 1 end end # get line text containing pos # the text is 80 at most def line_text pos from = string.rindex "\n", pos (from = string.rindex "\n", pos - 1) if from == pos from = from ? from + 1 : 0 from = pos - 40 if (from < pos - 40) to = string.index("\n", pos) to = to ? to - 1 : string.size to = pos + 40 if (to > pos + 40) string[from..to] end end # the invalid token INVALID = Object.new class << INVALID def to_str 'INVALID_TOKEN' end alias :[] :== alias inspect to_str end end rsec-0.4.2/lib/rsec/parsers/ 0000755 0001751 0001750 00000000000 13176057521 014664 5 ustar mmoll mmoll rsec-0.4.2/lib/rsec/parsers/seq.rb 0000644 0001751 0001750 00000003734 13176057521 016010 0 ustar mmoll mmoll module Rsec # sequence combinator
#{s}
"
}
escape = '<'.r{'<'} | '&'.r{'&'} | /\\[\!\`\*\[\]]/.r{|s|s[1]}
text = /[^\!\`\*\[\]]+/
id = seq_(('['.r >> /[^\]]+/ << ']:'), text){|(id, text)|
"#{text}"
}
line = (img | link | strong | em | code | escape | id | text).star
line.eof.map &:join
end
# pseudo xml tag parser, except