pax_global_header 0000666 0000000 0000000 00000000064 13736726330 0014524 g ustar 00root root 0000000 0000000 52 comment=aaf1aa27e7bfb86a63339f4ebf3938ff2e0c0258
raabro-1.4.0/ 0000775 0000000 0000000 00000000000 13736726330 0012774 5 ustar 00root root 0000000 0000000 raabro-1.4.0/.gitignore 0000664 0000000 0000000 00000000246 13736726330 0014766 0 ustar 00root root 0000000 0000000
*.swp
.vimrc
.viminfo
pkg/
.ruby-version
#.rspec
.vimrc
.viminfo
.vimmarks
.vimspec
.vimgrep
*.swp
.errors
.rspec.out
.bxsinfo.yaml
.bxsenvs.yaml
Gemfile.lock
raabro-1.4.0/.rspec 0000664 0000000 0000000 00000000040 13736726330 0014103 0 ustar 00root root 0000000 0000000 --colour --format documentation
raabro-1.4.0/.travis.yml 0000664 0000000 0000000 00000000714 13736726330 0015107 0 ustar 00root root 0000000 0000000
language: ruby
rvm:
#- 1.8.7 # no, since it doesn't get fun(a, *b, c) or fun0\n.fun1
#- 1.9.3 # Travis broken September 2017
#- 2.1.1
- 2.2.2
- 2.3.1
- 2.4.1
- 2.5.1
#- jruby-18mode
- jruby-19mode
- jruby-20mode
#matrix:
# include:
# - rvm: jruby-9.1.13.0
# #- env: JRUBY_OPTS="--profile.api"
#before_install: gem install bundler
script: bundle exec rspec
branches:
only:
- master
#except:
# - master
cache: bundler
raabro-1.4.0/CHANGELOG.md 0000664 0000000 0000000 00000003730 13736726330 0014610 0 ustar 00root root 0000000 0000000
# raabro CHANGELOG.md
## raabro 1.4.0 released 2020-10-06
* Ensure that jseq, for n elts, parses n-1 separators
* Introduce Tree #symbol, #symbod, #strind and #strinpd
## raabro 1.3.3 released 2020-09-24
* Merge Henrik's rewrite_ optimization
## raabro 1.3.2 released 2020-09-24
* Make a tiny rewrite_ optimization
## raabro 1.3.1 released 2020-05-10
* Add '!' (not) seq quantifier
## raabro 1.3.0 released 2020-05-10
* Add `nott` parser element
* Add Tree#strinp and #strim
* Skip 1.2.0 to align on http://github.com/jmettraux/jaabro
## raabro 1.1.6 released 2018-06-22
* Remove unused `add` var, gh-2, thanks to https://github.com/utilum
## raabro 1.1.5 released 2017-08-19
* Default name to nil for Tree#subgather, #gather, #sublookup, and #lookup
## raabro 1.1.4 released 2017-08-17
* fail with ArgumentError if Raabro.pp input is not a Raabro::Tree
* parse(x, error: true) will produce an error message
`[ line, column, offset, err_message, err_visual ]`
## raabro 1.1.3 released 2016-07-11
* display `>nonstring(14)<` in Raabro.pp
* add "tears" to Raabro.pp
## raabro 1.1.2 released 2016-04-04
* add Raabro.pp(tree)
## raabro 1.1.1 released 2016-04-03
* Tree#clast
## raabro 1.1.0 released 2016-02-09
* many improvements
* unlock custom `rewrite(t)`
## raabro 1.0.5 released 2015-09-25
* allow for .parse(s, debug: 1 to 3)
* drop complications in _narrow(parser)
## raabro 1.0.4 released 2015-09-24
* provide a default .rewrite implementation
## raabro 1.0.3 released 2015-09-23
* drop the shrink! concept
## raabro 1.0.2 released 2015-09-23
* don't let parse() shrink tree when prune: false
* let parse() return tree anyway when prune: false
* add parse(s, rewrite: false) option
## raabro 1.0.1 released 2015-09-23
* take last parser as default :root
* provide default .parse for modules including Raabro
## raabro 1.0.0 released 2015-09-23
* first complete (hopefully) release
## raabro 0.9.0
* initial push to RubyGems
raabro-1.4.0/CREDITS.md 0000664 0000000 0000000 00000000574 13736726330 0014421 0 ustar 00root root 0000000 0000000
# raabro credits
* Henryk Nyh https://github.com/henrik optimized rewrite_, gh-6
* Utilum https://github.com/utilum removed unused var
* John Mettraux https://github.com/jmettraux author and maintainer
## aabro and jaabro credits
Thanks to all the people who contributed to aabro and jaabro as well.
* https://github.com/flon-io/aabro
* https://github.com/jmettraux/jaabro
raabro-1.4.0/Gemfile 0000664 0000000 0000000 00000000075 13736726330 0014271 0 ustar 00root root 0000000 0000000
source 'https://rubygems.org'
#gem 'tzinfo-data'
gemspec
raabro-1.4.0/LICENSE.txt 0000664 0000000 0000000 00000002117 13736726330 0014620 0 ustar 00root root 0000000 0000000
Copyright (c) 2015-2020, John Mettraux, jmettraux@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Made in Japan.
raabro-1.4.0/Makefile 0000664 0000000 0000000 00000001657 13736726330 0014445 0 ustar 00root root 0000000 0000000
## gem tasks ##
NAME = \
$(shell ruby -e "s = eval(File.read(Dir['*.gemspec'][0])); puts s.name")
VERSION = \
$(shell ruby -e "s = eval(File.read(Dir['*.gemspec'][0])); puts s.version")
count_lines:
find lib -name "*.rb" | xargs cat | ruby -e "p STDIN.readlines.count { |l| l = l.strip; l[0, 1] != '#' && l != '' }"
find spec -name "*_spec.rb" | xargs cat | ruby -e "p STDIN.readlines.count { |l| l = l.strip; l[0, 1] != '#' && l != '' }"
cl: count_lines
gemspec_validate:
@echo "---"
ruby -e "s = eval(File.read(Dir['*.gemspec'].first)); p s.validate"
@echo "---"
name: gemspec_validate
@echo "$(NAME) $(VERSION)"
cw:
find lib -name "*.rb" -exec ruby -cw {} \;
build: gemspec_validate
gem build $(NAME).gemspec
mkdir -p pkg
mv $(NAME)-$(VERSION).gem pkg/
push: build
gem push --otp "$(OTP)" pkg/$(NAME)-$(VERSION).gem
spec:
bundle exec rspec
test: spec
.PHONY: count_lines gemspec_validate name cw build push spec
raabro-1.4.0/README.md 0000664 0000000 0000000 00000020300 13736726330 0014246 0 ustar 00root root 0000000 0000000
# raabro
[](http://travis-ci.org/floraison/raabro)
[](http://badge.fury.io/rb/raabro)
A very dumb PEG parser library.
Son to [aabro](https://github.com/flon-io/aabro), grandson to [neg](https://github.com/jmettraux/neg), grand-grandson to [parslet](https://github.com/kschiess/parslet). There is also a javascript version [jaabro](https://github.com/jmettraux/jaabro).
## a sample parser/rewriter
You use raabro by providing the parsing rules, then some rewrite rules.
The parsing rules make use of the raabro basic parsers `seq`, `alt`, `str`, `rex`, `eseq`, ...
The rewrite rules match names passed as first argument to the basic parsers to rewrite the resulting parse trees.
```ruby
require 'raabro'
module Fun include Raabro
# parse
#
# Last function is the root, "i" stands for "input".
def pstart(i); rex(nil, i, /\(\s*/); end
def pend(i); rex(nil, i, /\)\s*/); end
# parenthese start and end, including trailing white space
def comma(i); rex(nil, i, /,\s*/); end
# a comma, including trailing white space
def num(i); rex(:num, i, /-?[0-9]+\s*/); end
# name is :num, a positive or negative integer
def args(i); eseq(nil, i, :pstart, :exp, :comma, :pend); end
# a set of :exp, beginning with a (, punctuated by commas and ending with )
def funame(i); rex(nil, i, /[a-z][a-z0-9]*/); end
def fun(i); seq(:fun, i, :funame, :args); end
# name is :fun, a function composed of a function name
# followed by arguments
def exp(i); alt(nil, i, :fun, :num); end
# an expression is either (alt) a function or a number
# rewrite
#
# Names above (:num, :fun, ...) get a rewrite_xxx function.
# "t" stands for "tree".
def rewrite_exp(t); rewrite(t.children[0]); end
def rewrite_num(t); t.string.to_i; end
def rewrite_fun(t)
funame, args = t.children
[ funame.string ] +
args.gather.collect { |e| rewrite(e) }
#
# #gather collect all the children in a tree that have
# a name, in this example, names can be :exp, :num, :fun
end
end
p Fun.parse('mul(1, 2)')
# => ["mul", 1, 2]
p Fun.parse('mul(1, add(-2, 3))')
# => ["mul", 1, ["add", -2, 3]]
p Fun.parse('mul (1, 2)')
# => nil (doesn't accept a space after the function name)
```
This sample is available at: [doc/readme0.rb](doc/readme0.rb).
## custom rewrite()
By default, a parser gets a `rewrite(t)` that looks at the parse tree node names and calls the corresponding `rewrite_{node_name}()`.
It's OK to provide a custom `rewrite(t)` function.
```ruby
module Hello include Raabro
def hello(i); str(:hello, i, 'hello'); end
def rewrite(t)
[ :ok, t.string ]
end
end
```
## basic parsers
One makes a parser by composing basic parsers, for example:
```ruby
def args(i); eseq(:args, i, :pa, :exp, :com, :pz); end
def funame(i); rex(:funame, i, /[a-z][a-z0-9]*/); end
def fun(i); seq(:fun, i, :funame, :args); end
```
where the `fun` parser is a sequence combining the `funame` parser then the `args` one. `:fun` (the first argument to the basic parser `seq`) will be the name of the resulting (local) parse tree.
Below is a list of the basic parsers provided by Raabro.
The first parameter to the basic parser is the name used by rewrite rules.
The second parameter is a `Raabro::Input` instance, mostly a wrapped string.
```ruby
def str(name, input, string)
# matching a string
def rex(name, input, regex_or_string)
# matching a regexp
# no need for ^ or \A, checks the match occurs at current offset
def seq(name, input, *parsers)
# a sequence of parsers
def alt(name, input, *parsers)
# tries the parsers returns as soon as one succeeds
def altg(name, input, *parsers)
# tries all the parsers, returns with the longest match
def rep(name, input, parser, min, max=0)
# repeats the the wrapped parser
def nott(name, input, parser)
# succeeds if the wrapped parser fails, fails if it succeeds
def ren(name, input, parser)
# renames the output of the wrapped parser
def jseq(name, input, eltpa, seppa)
#
# seq(name, input, eltpa, seppa, eltpa, seppa, eltpa, seppa, ...)
#
# a sequence of `eltpa` parsers separated (joined) by `seppa` parsers
def eseq(name, input, startpa, eltpa, seppa, endpa)
#
# seq(name, input, startpa, eltpa, seppa, eltpa, seppa, ..., endpa)
#
# a sequence of `eltpa` parsers separated (joined) by `seppa` parsers
# preceded by a `startpa` parser and followed by a `endpa` parser
```
## the `seq` parser and its quantifiers
`seq` is special, it understands "quantifiers": `'?'`, `'+'` or `'*'`. They make behave `seq` a bit like a classical regex.
The `'!'` (bang, not) quantifier is explained at the end of this section.
```ruby
module CartParser include Raabro
def fruit(i)
rex(:fruit, i, /(tomato|apple|orange)/)
end
def vegetable(i)
rex(:vegetable, i, /(potato|cabbage|carrot)/)
end
def cart(i)
seq(:cart, i, :fruit, '*', :vegetable, '*')
end
# zero or more fruits followed by zero or more vegetables
end
```
(Yes, this sample parser parses string like "appletomatocabbage", it's not very useful, but I hope you get the point about `.seq`)
The `'!'` (bang, not) quantifier is a kind of "negative lookahead".
```ruby
def menu(i)
seq(:menu, i, :mise_en_bouche, :main, :main, '!', :dessert)
end
```
Lousy example, but here a main cannot follow a main.
## trees
An instance of `Raabro::Tree` is passed to `rewrite()` and `rewrite_{name}()` functions.
The most useful methods of this class are:
```ruby
class Raabro::Tree
# Look for the first child or sub-child with the given name.
# If the given name is nil, looks for the first child with a name (not nil).
#
def sublookup(name=nil)
# Gathers all the children or sub-children with the given name.
# If the given name is nil, gathers all the children with a name (not nil).
# When a child matches, does not pursue gathering from the children of the
# matching child.
#
def subgather(name=nil)
end
```
I'm using "child or sub-child" instead of "descendant" because once a child or sub-child matches, those methods do not consider the children or sub-children of that matching entity.
Here is a closeup on the rewrite functions of the sample parser at [doc/readme1.rb](doc/readme1.rb) (extracted from an early version of [floraison/dense](https://github.com/floraison/dense)):
```ruby
require 'raabro'
module PathParser include Raabro
# (...)
def rewrite_name(t); t.string; end
def rewrite_off(t); t.string.to_i; end
def rewrite_index(t); rewrite(t.sublookup); end
def rewrite_path(t); t.subgather(:index).collect { |tt| rewrite(tt) }; end
end
```
Where `rewrite_index(t)` returns the result of the rewrite of the first of its children that has a name and `rewrite_path(t)` collects the result of the rewrite of all of its children that have the "index" name.
## errors
By default, a parser will return nil when it cannot successfully parse the input.
For example, given the above [`Fun` parser](#a-sample-parserrewriter), parsing some truncated input would yield `nil`:
```ruby
tree = Sample::Fun.parse('f(a, b')
# yields `nil`...
```
One can reparse with `error: true` and receive an error array with the parse error details:
```ruby
err = Sample::Fun.parse('f(a, b', error: true)
# yields:
# [ line, column, offest, error_message, error_visual ]
[ 1, 4, 3, 'parsing failed .../:exp/:fun/:arg', "f(a, b\n ^---" ]
```
The last string in the error array looks like when printed out:
```
f(a, b
^---
```
### error when not all is consumed
Consider the following toy parser:
```ruby
module ToPlus include Raabro
# parse
def to_plus(input); rep(:tos, input, :to, 1); end
# rewrite
def rewrite(t); [ :ok, t.string ]; end
end
```
```ruby
Sample::ToPlus.parse('totota')
# yields nil since all the input was not parsed, "ta" is remaining
Sample::ToPlus.parse('totota', all: false)
# yields
[ :ok, "toto" ]
# and doesn't care about the remaining input "ta"
Sample::ToPlus.parse('totota', error: true)
# yields
[ 1, 5, 4, "parsing failed, not all input was consumed", "totota\n ^---" ]
```
The last string in the error array looks like when printed out:
```
totota
^---
```
## LICENSE
MIT, see [LICENSE.txt](LICENSE.txt)
raabro-1.4.0/doc/ 0000775 0000000 0000000 00000000000 13736726330 0013541 5 ustar 00root root 0000000 0000000 raabro-1.4.0/doc/readme0.rb 0000664 0000000 0000000 00000002143 13736726330 0015403 0 ustar 00root root 0000000 0000000
#
# A sample raabro parser/rewriter
#
# Thu Sep 24 06:18:57 JST 2015
#
require 'raabro'
module Fun include Raabro
# parse
#
# Last function is the root, "i" stands for "input".
def pa(i); rex(nil, i, /\(\s*/); end
def pz(i); rex(nil, i, /\)\s*/); end
def com(i); rex(nil, i, /,\s*/); end
def num(i); rex(:num, i, /-?[0-9]+\s*/); end
def args(i); eseq(nil, i, :pa, :exp, :com, :pz); end
def funame(i); rex(nil, i, /[a-z][a-z0-9]*/); end
def fun(i); seq(:fun, i, :funame, :args); end
def exp(i); alt(nil, i, :fun, :num); end
# rewrite
#
# Names above (:num, :fun, ...) get a rewrite_xxx function.
# "t" stands for "tree".
#
# The trees with a nil name are handled by rewrite_(tree) a default
# rewrite function
def rewrite_num(t); t.string.to_i; end
def rewrite_fun(t)
[ t.children[0].string ] +
t.children[1].odd_children.collect { |a| rewrite(a) }
end
end
p Fun.parse('mul(1, 2)')
# => ["mul", 1, 2]
p Fun.parse('mul(1, add(-2, 3))')
# => ["mul", 1, ["add", -2, 3]]
p Fun.parse('mul (1, 2)')
# => nil (doesn't accept a space after the function name)
raabro-1.4.0/doc/readme1.rb 0000664 0000000 0000000 00000002743 13736726330 0015412 0 ustar 00root root 0000000 0000000
require 'raabro'
module PathParser include Raabro
# piece parsers bottom to top
def dot(i); str(nil, i, '.'); end
def bend(i); str(nil, i, ']'); end
def bstart(i); str(nil, i, '['); end
def dq(i); str(nil, i, '"'); end
def sq(i); str(nil, i, "'"); end
def name(i); rex(:name, i, /[a-z0-9_]+/i); end
def off(i); rex(:off, i, /\d+/); end
def dqname(i); seq(nil, i, :dq, :name, :dq); end
def sqname(i); seq(nil, i, :sq, :name, :sq); end
def bindex(i); alt(:index, i, :off, :dqname, :sqname); end
def dindex(i); alt(:index, i, :off, :name); end
def bracket_index(i); seq(nil, i, :bstart, :bindex, :bend); end
def dot_index(i); seq(nil, i, :dot, :dindex); end
def then_index(i); alt(nil, i, :dot_index, :bracket_index); end
def start_index(i); alt(nil, i, :dindex, :bracket_index); end
def path(i); seq(:path, i, :start_index, :then_index, '*'); end
# rewrite parsed tree
def rewrite_name(t); t.string; end
def rewrite_off(t); t.string.to_i; end
def rewrite_index(t); rewrite(t.sublookup); end
def rewrite_path(t); t.subgather(:index).collect { |tt| rewrite(tt) }; end
end
p PathParser.parse('0.name')
# => [ 0, 'name' ],
p PathParser.parse('name.0')
# => [ 'name', 0 ],
p PathParser.parse('11[0]')
# => [ 11, 0 ],
p PathParser.parse("name['first']")
# => [ 'name', 'first' ],
p PathParser.parse('name["last"]')
# => [ 'name', 'last' ],
p PathParser.parse('name[0]')
# => [ 'name', 0 ],
p PathParser.parse('[0].name')
# => [ 0, 'name' ],
raabro-1.4.0/doc/test.rb 0000664 0000000 0000000 00000003125 13736726330 0015046 0 ustar 00root root 0000000 0000000
#
# A sample raabro parser/rewriter
#
# Thu Sep 24 06:18:57 JST 2015
#
require 'raabro'
module Fun include Raabro
# parse
#
# Last function is the root, "i" stands for "input".
def pstart(i); rex(nil, i, /\(\s*/); end
def pend(i); rex(nil, i, /\)\s*/); end
# parenthese start and end, including trailing white space
def comma(i); rex(nil, i, /,\s*/); end
# a comma, including trailing white space
def num(i); rex(:num, i, /-?[0-9]+\s*/); end
# name is :num, a positive or negative integer
def args(i); eseq(nil, i, :pstart, :exp, :comma, :pend); end
# a set of :exp, beginning with a (, punctuated by commas and ending with )
def funame(i); rex(nil, i, /[a-z][a-z0-9]*/); end
def fun(i); seq(:fun, i, :funame, :args); end
# name is :fun, a function composed of a function name
# followed by arguments
def exp(i); alt(nil, i, :fun, :num); end
# an expression is either (alt) a function or a number
# rewrite
#
# Names above (:num, :fun, ...) get a rewrite_xxx function.
# "t" stands for "tree".
def rewrite_exp(t); rewrite(t.children[0]); end
def rewrite_num(t); t.string.to_i; end
def rewrite_fun(t)
funame, args = t.children
[ funame.string ] +
args.gather.collect { |e| rewrite(e) }
#
# #gather collect all the children in a tree that have
# a name, in this example, names can be :exp, :num, :fun
end
end
p Fun.parse('mul(1, 2)')
# => ["mul", 1, 2]
p Fun.parse('mul(1, add(-2, 3))')
# => ["mul", 1, ["add", -2, 3]]
p Fun.parse('mul (1, 2)')
# => nil (doesn't accept a space after the function name)
raabro-1.4.0/lib/ 0000775 0000000 0000000 00000000000 13736726330 0013542 5 ustar 00root root 0000000 0000000 raabro-1.4.0/lib/raabro.rb 0000664 0000000 0000000 00000033736 13736726330 0015351 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Raabro
VERSION = '1.4.0'
class Input
attr_accessor :string, :offset
attr_reader :options
def initialize(string, offset=0, options={})
@string = string
@offset = offset.is_a?(Hash) ? 0 : offset
@options = offset.is_a?(Hash) ? offset : options
end
def match(str_or_regex)
if str_or_regex.is_a?(Regexp)
m = @string[@offset..-1].match(str_or_regex)
m && (m.offset(0).first == 0) ? m[0].length : false
else # String or whatever responds to #to_s
s = str_or_regex.to_s
l = s.length
@string[@offset, l] == s ? l : false
end
end
def tring(l=-1)
l < 0 ? @string[@offset..l] : @string[@offset, l]
end
def at(i)
@string[i, 1]
end
end
class Tree
attr_accessor :name, :input
attr_accessor :result # ((-1 error,)) 0 nomatch, 1 success
attr_accessor :offset, :length
attr_accessor :parter, :children
def initialize(name, parter, input)
@result = 0
@name = name
@parter = parter
@input = input
@offset = input.offset
@length = 0
@children = []
end
def c0; @children[0]; end
def c1; @children[1]; end
def c2; @children[2]; end
def c3; @children[3]; end
def c4; @children[4]; end
def clast; @children.last; end
def empty?
@result == 1 && @length == 0
end
def successful_children
@children.select { |c| c.result == 1 }
end
def prune!
@children = successful_children
end
def string; @input.string[@offset, @length]; end
def strinp; string.strip; end
alias strim strinp
def nonstring(l=7); @input.string[@offset, l]; end
def stringd; string.downcase; end
alias strind stringd
def stringpd; strinp.downcase; end
alias strinpd stringpd
def symbol; strinp.to_sym; end
def symbold; symbol.downcase; end
alias symbod symbold
def lookup(name=nil)
name = name ? name.to_s : nil
return self if @name && name == nil
return self if @name.to_s == name
sublookup(name)
end
def sublookup(name=nil)
@children.each { |c| if n = c.lookup(name); return n; end }
nil
end
def gather(name=nil, acc=[])
name = name ? name.to_s : nil
if (@name && name == nil) || (@name.to_s == name)
acc << self
else
subgather(name, acc)
end
acc
end
def subgather(name=nil, acc=[])
@children.each { |c| c.gather(name, acc) }
acc
end
def to_a(opts={})
opts = Array(opts).inject({}) { |h, e| h[e] = true; h } \
unless opts.is_a?(Hash)
cn =
if opts[:leaves] && (@result == 1) && @children.empty?
string
elsif opts[:children] != false
@children.collect { |e| e.to_a(opts) }
else
@children.length
end
[ @name, @result, @offset, @length, @note, @parter, cn ]
end
def to_s(depth=0, io=StringIO.new)
io.print "\n" if depth > 0
io.print ' ' * depth
io.print "#{@result} #{@name.inspect} #{@offset},#{@length}"
io.print result == 1 && children.size == 0 ? ' ' + string.inspect : ''
@children.each { |c| c.to_s(depth + 1, io) }
depth == 0 ? io.string : nil
end
def odd_children
cs = []; @children.each_with_index { |c, i| cs << c if i.odd? }; cs
end
def even_children
cs = []; @children.each_with_index { |c, i| cs << c if i.even? }; cs
end
def extract_error
#Raabro.pp(self, colors: true)
err_tree, stack = lookup_error || lookup_all_error
line, column = line_and_column(err_tree.offset)
err_message =
if stack
path = stack
.compact.reverse.take(3).reverse
.collect(&:inspect).join('/')
"parsing failed .../#{path}"
else
'parsing failed, not all input was consumed'
end
visual =
visual(line, column)
[ line, column, err_tree.offset, err_message, visual ]
end
def lookup_error(stack=[])
#print 'le(): '; Raabro.pp(self, colors: true)
return nil if @result != 0
return [ self, stack ] if @children.empty?
@children.each { |c|
es = c.lookup_error(stack.dup.push(self.name))
return es if es }
nil
end
# Not "lookup all errors" but "lookup all error", in other
# words lookup the point up until which the parser stopped (not
# consuming all the input)
#
def lookup_all_error
#print "lae(): "; Raabro.pp(self, colors: true)
@children.each { |c| return [ c, nil ] if c.result == 0 }
@children.reverse.each { |c| es = c.lookup_all_error; return es if es }
nil
end
def line_and_column(offset)
line = 1
column = 0
(0..offset).each do |off|
column += 1
next unless @input.at(off) == "\n"
line += 1
column = 0
end
[ line, column ]
end
def visual(line, column)
@input.string.split("\n")[line - 1] + "\n" +
' ' * (column - 1) + '^---'
end
end
module ModuleMethods
def _match(name, input, parter, regex_or_string)
r = Raabro::Tree.new(name, parter, input)
if l = input.match(regex_or_string)
r.result = 1
r.length = l
input.offset += l
end
r
end
def str(name, input, string)
_match(name, input, :str, string)
end
def rex(name, input, regex_or_string)
_match(name, input, :rex, Regexp.new(regex_or_string))
end
def _quantify(parser)
return nil if parser.is_a?(Symbol) && respond_to?(parser)
# so that :plus and co can be overriden
case parser
when '?', :q, :qmark then [ 0, 1 ]
when '*', :s, :star then [ 0, 0 ]
when '+', :p, :plus then [ 1, 0 ]
when '!' then :bang
else nil
end
end
def _narrow(parser)
fail ArgumentError.new("lone quantifier #{parser}") if _quantify(parser)
method(parser.to_sym)
end
def _parse(parser, input)
#p [ caller.length, parser, input.tring ]
#r = _narrow(parser).call(input)
#p [ caller.length, parser, input.tring, r.to_a(children: false) ]
#r
_narrow(parser).call(input)
end
def seq(name, input, *parsers)
r = ::Raabro::Tree.new(name, :seq, input)
start = input.offset
c = nil
loop do
pa = parsers.shift
break unless pa
if parsers.first == '!'
parsers.shift
c = nott(nil, input, pa)
r.children << c
elsif q = _quantify(parsers.first)
parsers.shift
c = rep(nil, input, pa, *q)
r.children.concat(c.children)
else
c = _parse(pa, input)
r.children << c
end
break if c.result != 1
end
if c && c.result == 1
r.result = 1
r.length = input.offset - start
else
input.offset = start
end
r
end
def alt(name, input, *parsers)
greedy =
if parsers.last == true || parsers.last == false
parsers.pop
else
false
end
r = ::Raabro::Tree.new(name, greedy ? :altg : :alt, input)
start = input.offset
c = nil
parsers.each do |pa|
cc = _parse(pa, input)
r.children << cc
input.offset = start
if greedy
if cc.result == 1 && cc.length >= (c ? c.length : -1)
c.result = 0 if c
c = cc
else
cc.result = 0
end
else
c = cc
break if c.result == 1
end
end
if c && c.result == 1
r.result = 1
r.length = c.length
input.offset = start + r.length
end
r.prune! if input.options[:prune]
r
end
def altg(name, input, *parsers)
alt(name, input, *parsers, true)
end
def rep(name, input, parser, min, max=0)
min = 0 if min == nil || min < 0
max = nil if max.nil? || max < 1
r = ::Raabro::Tree.new(name, :rep, input)
start = input.offset
count = 0
loop do
c = _parse(parser, input)
r.children << c
break if c.result != 1
count += 1
break if c.length < 1
break if max && count == max
end
if count >= min && (max == nil || count <= max)
r.result = 1
r.length = input.offset - start
else
input.offset = start
end
r.prune! if input.options[:prune]
r
end
def ren(name, input, parser)
r = _parse(parser, input)
r.name = name
r
end
alias rename ren
def nott(name, input, parser)
start = input.offset
r = ::Raabro::Tree.new(name, :nott, input)
c = _parse(parser, input)
r.children << c
r.length = 0
r.result = c.result == 1 ? 0 : 1
input.offset = start
r
end
def all(name, input, parser)
start = input.offset
length = input.string.length - input.offset
r = ::Raabro::Tree.new(name, :all, input)
c = _parse(parser, input)
r.children << c
if c.length < length
input.offset = start
else
r.result = 1
r.length = c.length
end
r
end
def eseq(name, input, startpa, eltpa, seppa=nil, endpa=nil)
jseq = false
if seppa.nil? && endpa.nil?
jseq = true
seppa = eltpa; eltpa = startpa; startpa = nil
end
start = input.offset
r = ::Raabro::Tree.new(name, jseq ? :jseq : :eseq, input)
r.result = 1
c = nil
if startpa
c = _parse(startpa, input)
r.children << c
r.result = 0 if c.result != 1
end
if r.result == 1
on_elt = false
count = 0
empty_stack = 0
loop do
on_elt = ! on_elt
cr = _parse(on_elt ? eltpa : seppa, input)
empty_stack = cr.empty? ? empty_stack + 1 : 0
cr.result = 0 if empty_stack > 1
#
# prevent "no progress"
r.children.push(cr)
if cr.result != 1
if on_elt && count > 0
lsep = r.children[-2]
lsep.result = 0
input.offset = lsep.offset
end
break
end
count += 1
end
r.result = 0 if jseq && count < 1
end
if r.result == 1 && endpa
c = _parse(endpa, input)
r.children << c
r.result = 0 if c.result != 1
end
if r.result == 1
r.length = input.offset - start
else
input.offset = start
end
r.prune! if input.options[:prune]
r
end
alias jseq eseq
attr_accessor :last
def method_added(name)
m = method(name)
return unless m.arity == 1
return unless m.parameters[0][1] == :i || m.parameters[0][1] == :input
@last = name.to_sym
end
def parse(input, opts={})
d = opts[:debug].to_i
opts[:rewrite] = false if d > 0
opts[:all] = false if d > 1
opts[:prune] = false if d > 2
opts[:prune] = true unless opts.has_key?(:prune)
root = self.respond_to?(:root) ? :root : @last
t =
if opts[:all] == false
_parse(root, Raabro::Input.new(input, opts))
else
all(nil, Raabro::Input.new(input, opts), root)
end
return reparse_for_error(input, opts, t) if opts[:error] && t.result != 1
return nil if opts[:prune] != false && t.result != 1
t = t.children.first if t.parter == :all
return rewrite(t) if opts[:rewrite] != false
t
end
def reparse_for_error(input, opts, t)
t =
opts[:prune] == false ?
t :
parse(input, opts.merge(error: false, rewrite: false, prune: false))
#Raabro.pp(t, colours: true)
t.extract_error
end
def rewrite_(tree)
t = tree.lookup(nil)
t ? rewrite(t) : nil
end
def rewrite(tree)
return !! methods.find { |m| m.to_s.start_with?('rewrite_') } if tree == 0
# return true when "rewrite_xxx" methods seem to have been provided
send("rewrite_#{tree.name}", tree)
end
def make_includable
def self.included(target)
target.instance_eval do
extend ::Raabro::ModuleMethods
extend self
end
end
end
end
extend ModuleMethods
make_includable
# Black 0;30 Dark Gray 1;30
# Blue 0;34 Light Blue 1;34
# Green 0;32 Light Green 1;32
# Cyan 0;36 Light Cyan 1;36
# Red 0;31 Light Red 1;31
# Purple 0;35 Light Purple 1;35
# Brown 0;33 Yellow 1;33
# Light Gray 0;37 White 1;37
def self.pp(tree, depth=0, opts={})
fail ArgumentError.new(
'tree is not an instance of Raabro::Tree'
) unless tree.is_a?(Raabro::Tree)
depth, opts = 0, depth if depth.is_a?(Hash)
_rs, _dg, _gn, _yl, _bl, _lg =
(opts[:colors] || opts[:colours] || $stdout.tty?) ?
[ "[0;0m", "[1;30m", "[0;32m", "[1;33m", "[0;34m", "[0;37m" ] :
[ '', '', '', '', '', '' ]
lc = tree.result == 1 ? _gn : _dg
nc = tree.result == 1 ? _bl : _lg
nc = lc if tree.name == nil
sc = tree.result == 1 ? _yl : _dg
str =
if tree.children.size == 0
" #{sc}#{tree.string.length == 0 ?
"#{_dg} >#{tree.nonstring(14).inspect[1..-2]}<" :
tree.string.inspect}"
else
''
end
print "#{_dg}t---\n" if depth == 0
#print "#{' ' * depth}"
depth.times do |i|
pipe = i % 3 == 0 ? ': ' : '| '
print i.even? ? "#{_dg}#{pipe} " : ' '
end
print "#{lc}#{tree.result}"
print " #{nc}#{tree.name.inspect} #{lc}#{tree.offset},#{tree.length}"
print str
print "#{_rs}\n"
tree.children.each { |c| self.pp(c, depth + 1, opts) }
if depth == 0
print _dg
print "input ln: #{tree.input.string.length}, tree ln: #{tree.length} "
print "---t\n"
print _rs
end
end
end
raabro-1.4.0/raabro.gemspec 0000664 0000000 0000000 00000001532 13736726330 0015610 0 ustar 00root root 0000000 0000000
Gem::Specification.new do |s|
s.name = 'raabro'
s.version = File.read(
File.expand_path('../lib/raabro.rb', __FILE__)
).match(/ VERSION *= *['"]([^'"]+)/)[1]
s.platform = Gem::Platform::RUBY
s.authors = [ 'John Mettraux' ]
s.email = [ 'jmettraux+flor@gmail.com' ]
s.homepage = 'https://github.com/floraison/raabro'
s.license = 'MIT'
s.summary = 'a very dumb PEG parser library'
s.description = %{
A very dumb PEG parser library, with a horrible interface.
}.strip
#s.files = `git ls-files`.split("\n")
s.files = Dir[
'README.{md,txt}',
'CHANGELOG.{md,txt}', 'CREDITS.{md,txt}', 'LICENSE.{md,txt}',
'Makefile',
'lib/**/*.rb', #'spec/**/*.rb', 'test/**/*.rb',
"#{s.name}.gemspec",
]
#s.add_runtime_dependency 'tzinfo'
s.add_development_dependency 'rspec', '~> 3.7'
s.require_path = 'lib'
end
raabro-1.4.0/spec/ 0000775 0000000 0000000 00000000000 13736726330 0013726 5 ustar 00root root 0000000 0000000 raabro-1.4.0/spec/all_spec.rb 0000664 0000000 0000000 00000002216 13736726330 0016036 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Mon Sep 21 05:56:18 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.all' do
it 'fails when not all the input is consumed' do
i = Raabro::Input.new('tototota')
t = Raabro.all(nil, i, :to_plus)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 0, 0, 0, nil, :all, [
[ :tos, 1, 0, 6, nil, :rep, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 1, 2, 2, nil, :str, 'to' ],
[ nil, 1, 4, 2, nil, :str, 'to' ],
[ nil, 0, 6, 0, nil, :str, [] ]
] ]
] ]
)
expect(i.offset).to eq(0)
end
it 'succeeds when all the input is consumed' do
i = Raabro::Input.new('tototo')
t = Raabro.all(nil, i, :to_plus)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 6, nil, :all, [
[ :tos, 1, 0, 6, nil, :rep, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 1, 2, 2, nil, :str, 'to' ],
[ nil, 1, 4, 2, nil, :str, 'to' ],
[ nil, 0, 6, 0, nil, :str, [] ]
] ]
] ]
)
expect(i.offset).to eq(6)
end
end
end
raabro-1.4.0/spec/alt_spec.rb 0000664 0000000 0000000 00000007101 13736726330 0016044 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun Sep 20 07:31:53 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.alt' do
it "returns a tree with result == 0 in case of failure" do
i = Raabro::Input.new('tutu')
t = Raabro.alt(nil, i, :ta, :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 0, 0, 0, nil, :alt, [
[ nil, 0, 0, 0, nil, :str, [] ],
[ nil, 0, 0, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it "succeeds (1st alternative)" do
i = Raabro::Input.new('tato')
t = Raabro.alt(nil, i, :ta, :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :alt, [
[ nil, 1, 0, 2, nil, :str, 'ta' ]
] ]
)
expect(i.offset).to eq(2)
end
it "succeeds (2nd alternative)" do
i = Raabro::Input.new('tato')
t = Raabro.alt(nil, i, :to, :ta)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :alt, [
[ nil, 0, 0, 0, nil, :str, [] ],
[ nil, 1, 0, 2, nil, :str, 'ta' ]
] ]
)
expect(i.offset).to eq(2)
end
it 'prunes' do
i = Raabro::Input.new('tato', :prune => true)
t = Raabro.alt(nil, i, :to, :ta)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :alt, [
[ nil, 1, 0, 2, nil, :str, 'ta' ]
] ]
)
expect(i.offset).to eq(2)
end
context 'when not greedy (default)' do
it 'goes with the first successful result' do
i = Raabro::Input.new('xx')
t = Raabro.alt(nil, i, :onex, :twox)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 1, nil, :alt, [
[ :onex, 1, 0, 1, nil, :str, 'x' ]
] ]
)
expect(i.offset).to eq(1)
end
end
context 'when greedy (last argument set to true)' do
it 'takes the longest successful result' do
i = Raabro::Input.new('xx')
t = Raabro.alt(nil, i, :onex, :twox, true)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :altg, [
[ :onex, 0, 0, 1, nil, :str, [] ],
[ :twox, 1, 0, 2, nil, :str, 'xx' ]
] ]
)
expect(i.offset).to eq(2)
end
end
end
describe '.altg' do
it 'is greedy, always' do
i = Raabro::Input.new('xx')
t = Raabro.altg(nil, i, :onex, :twox)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :altg, [
[ :onex, 0, 0, 1, nil, :str, [] ],
[ :twox, 1, 0, 2, nil, :str, 'xx' ]
] ]
)
expect(i.offset).to eq(2)
end
it 'prunes' do
i = Raabro::Input.new('xx', :prune => true)
t = Raabro.altg(nil, i, :onex, :twox)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :altg, [
[ :twox, 1, 0, 2, nil, :str, 'xx' ]
] ]
)
expect(i.offset).to eq(2)
end
it 'declares a single winner' do
i = Raabro::Input.new('xx', :prune => true)
t = Raabro.altg(nil, i, :twox, :onex)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :altg, [
[ :twox, 1, 0, 2, nil, :str, 'xx' ]
] ]
)
expect(i.offset).to eq(2)
end
it 'takes the longest and latest winner' do
i = Raabro::Input.new('xx', :prune => true)
t = Raabro.altg(nil, i, :twox, :onex, :deux)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :altg, [
[ :deux, 1, 0, 2, nil, :str, 'xx' ]
] ]
)
expect(i.offset).to eq(2)
end
end
end
raabro-1.4.0/spec/eseq_spec.rb 0000664 0000000 0000000 00000010055 13736726330 0016223 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Mon Sep 21 10:15:35 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.eseq' do
it 'parses successfully' do
i = Raabro::Input.new('')
t = Raabro.eseq(:list, i, :lt, :cha, :com, :gt)
expect(t.to_a(:leaves => true)).to eq(
[ :list, 1, 0, 5, nil, :eseq, [
[ nil, 1, 0, 1, nil, :str, '<' ],
[ nil, 1, 1, 1, nil, :rex, 'a' ],
[ nil, 1, 2, 1, nil, :str, ',' ],
[ nil, 1, 3, 1, nil, :rex, 'b' ],
[ nil, 0, 4, 0, nil, :str, [] ],
[ nil, 1, 4, 1, nil, :str, '>' ]
] ]
)
expect(i.offset).to eq(5)
end
it 'prunes' do
i = Raabro::Input.new('', :prune => true)
t = Raabro.eseq(:list, i, :lt, :cha, :com, :gt)
expect(t.to_a(:leaves => true)).to eq(
[ :list, 1, 0, 5, nil, :eseq, [
[ nil, 1, 0, 1, nil, :str, '<' ],
[ nil, 1, 1, 1, nil, :rex, 'a' ],
[ nil, 1, 2, 1, nil, :str, ',' ],
[ nil, 1, 3, 1, nil, :rex, 'b' ],
[ nil, 1, 4, 1, nil, :str, '>' ]
] ]
)
expect(i.offset).to eq(5)
end
it 'parses <>' do
i = Raabro::Input.new('<>', :prune => true)
t = Raabro.eseq(:list, i, :lt, :cha, :com, :gt)
expect(t.to_a(:leaves => true)).to eq(
[ :list, 1, 0, 2, nil, :eseq, [
[ nil, 1, 0, 1, nil, :str, '<' ],
[ nil, 1, 1, 1, nil, :str, '>' ]
] ]
)
expect(i.offset).to eq(2)
end
context 'no start parser' do
it 'parses successfully' do
i = Raabro::Input.new('a,b>', prune: false)
t = Raabro.eseq(:list, i, nil, :cha, :com, :gt)
expect(t.to_a(:leaves => true)).to eq(
[ :list, 1, 0, 4, nil, :eseq, [
[ nil, 1, 0, 1, nil, :rex, 'a' ],
[ nil, 1, 1, 1, nil, :str, ',' ],
[ nil, 1, 2, 1, nil, :rex, 'b' ],
[ nil, 0, 3, 0, nil, :str, [] ],
[ nil, 1, 3, 1, nil, :str, '>' ]
] ]
)
expect(i.offset).to eq(4)
end
end
context 'no end parser' do
it 'parses successfully' do
i = Raabro::Input.new(' true)).to eq(
[ :list, 1, 0, 4, nil, :eseq, [
[ nil, 1, 0, 1, nil, :str, '<' ],
[ nil, 1, 1, 1, nil, :rex, 'a' ],
[ nil, 1, 2, 1, nil, :str, ',' ],
[ nil, 1, 3, 1, nil, :rex, 'b' ],
[ nil, 0, 4, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(4)
end
it 'prunes' do
i = Raabro::Input.new(' true)
t = Raabro.eseq(:list, i, :lt, :cha, :com, nil)
expect(t.to_a(:leaves => true)).to eq(
[ :list, 1, 0, 4, nil, :eseq, [
[ nil, 1, 0, 1, nil, :str, '<' ],
[ nil, 1, 1, 1, nil, :rex, 'a' ],
[ nil, 1, 2, 1, nil, :str, ',' ],
[ nil, 1, 3, 1, nil, :rex, 'b' ]
] ]
)
expect(i.offset).to eq(4)
end
end
context 'no progress' do
it 'parses <>' do
i = Raabro::Input.new('<>', :prune => true)
t = arr(i)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 2, nil, :eseq, [
[ nil, 1, 0, 1, nil, :str, '<' ],
[ nil, 1, 1, 0, nil, :rex, '' ],
[ nil, 1, 1, 1, nil, :str, '>' ]
] ]
)
expect(i.offset).to eq(2)
end
it 'parses ' do
i = Raabro::Input.new('', :prune => true)
t = arr(i)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 6, nil, :eseq, [
[ nil, 1, 0, 1, nil, :str, '<' ],
[ nil, 1, 1, 1, nil, :rex, 'a' ],
[ nil, 1, 2, 1, nil, :rex, ',' ],
[ nil, 1, 3, 0, nil, :rex, '' ],
[ nil, 1, 3, 1, nil, :rex, ',' ],
[ nil, 1, 4, 1, nil, :rex, 'a' ],
[ nil, 1, 5, 1, nil, :str, '>' ]
] ]
)
expect(i.offset).to eq(6)
end
end
end
end
raabro-1.4.0/spec/failure_spec.rb 0000664 0000000 0000000 00000004341 13736726330 0016716 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Thu Aug 10 07:52:29 JST 2017
#
require 'spec_helper'
module Sample::ToPlus include Raabro
# parse
def sp_star(i); rex(nil, i, /\s*/);end
def to_space(i); seq(nil, i, :to, :sp_star); end
def to_plus(i); rep(:tos, i, :to_space, 1); end
# rewrite
def rewrite(t)
[ :ok, t.string ]
end
end
module Sample::Fun include Raabro
# parse
#
# Last function is the root, "i" stands for "input".
def pa(i); rex(nil, i, /\(\s*/); end
def pz(i); rex(nil, i, /\)\s*/); end
def com(i); rex(nil, i, /,\s*/); end
def num(i); rex(:num, i, /-?[0-9]+\s*/); end
def args(i); eseq(:arg, i, :pa, :exp, :com, :pz); end
def funame(i); rex(:funame, i, /[a-z][a-z0-9]*/); end
def fun(i); seq(:fun, i, :funame, :args); end
def exp(i); alt(:exp, i, :fun, :num); end
# rewrite
#
# Names above (:num, :fun, ...) get a rewrite_xxx function.
# "t" stands for "tree".
#
# The trees with a nil name are handled by rewrite_(tree) a default
# rewrite function
def rewrite_num(t); t.string.to_i; end
def rewrite_fun(t)
[ t.children[0].string ] +
t.children[1].odd_children.collect { |a| rewrite(a) }
end
end
describe 'Raabro and parse failure' do
describe 'when there is a syntax error' do
it 'points at the error' do
t = Sample::Fun.parse('f(a, b')
expect(t).to eq(nil)
expect(
Sample::Fun.parse('f(a, b', error: true)
).to eq(
[ 1, 4, 3, 'parsing failed .../:exp/:fun/:arg', "f(a, b\n ^---" ]
)
end
end
describe 'when not all is consumed' do
it 'points at the start of the remaining input' do
t = Sample::ToPlus.parse('totota')
expect(t).to eq(nil)
expect(
Sample::ToPlus.parse('totota', error: true)
).to eq(
[ 1, 5, 4,
'parsing failed, not all input was consumed',
"totota\n ^---" ]
)
end
it 'points at the start of the remaining input (multiline)' do
s = "toto\r\n ta"
t = Sample::ToPlus.parse(s)
expect(t).to eq(nil)
expect(
Sample::ToPlus.parse(s, error: true)
).to eq(
[ 2, 3, 8,
'parsing failed, not all input was consumed',
" ta\n ^---" ]
)
end
end
end
raabro-1.4.0/spec/jseq_spec.rb 0000664 0000000 0000000 00000003546 13736726330 0016237 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Mon Sep 21 06:55:35 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.jseq' do
it 'parses elts joined by a separator' do
i = Raabro::Input.new('a,b,c')
t = Raabro.jseq(:j, i, :cha, :com)
expect(t.to_a(:leaves => true)).to eq(
[ :j, 1, 0, 5, nil, :jseq, [
[ nil, 1, 0, 1, nil, :rex, 'a' ],
[ nil, 1, 1, 1, nil, :str, ',' ],
[ nil, 1, 2, 1, nil, :rex, 'b' ],
[ nil, 1, 3, 1, nil, :str, ',' ],
[ nil, 1, 4, 1, nil, :rex, 'c' ],
[ nil, 0, 5, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(5)
end
it 'prunes' do
i = Raabro::Input.new('a,b,c', :prune => true)
t = Raabro.jseq(:j, i, :cha, :com)
expect(t.to_a(:leaves => true)).to eq(
[ :j, 1, 0, 5, nil, :jseq, [
[ nil, 1, 0, 1, nil, :rex, 'a' ],
[ nil, 1, 1, 1, nil, :str, ',' ],
[ nil, 1, 2, 1, nil, :rex, 'b' ],
[ nil, 1, 3, 1, nil, :str, ',' ],
[ nil, 1, 4, 1, nil, :rex, 'c' ]
] ]
)
expect(i.offset).to eq(5)
end
it 'fails when 0 elements' do
i = Raabro::Input.new('')
t = Raabro.jseq(:j, i, :cha, :com)
expect(t.to_a(:leaves => true)).to eq(
[ :j, 0, 0, 0, nil, :jseq, [
[ nil, 0, 0, 0, nil, :rex, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it 'does not include trailing separators' do
i = Raabro::Input.new('a,b,', :prune => false)
t = Raabro.jseq(:j, i, :cha, :com)
expect(t.to_a(:leaves => true)).to eq(
[:j, 1, 0, 3, nil, :jseq, [
[nil, 1, 0, 1, nil, :rex, 'a'],
[nil, 1, 1, 1, nil, :str, ','],
[nil, 1, 2, 1, nil, :rex, 'b'],
[nil, 0, 3, 1, nil, :str, []],
[nil, 0, 4, 0, nil, :rex, []]]]
)
end
end
end
raabro-1.4.0/spec/nott_spec.rb 0000664 0000000 0000000 00000001236 13736726330 0016253 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun May 10 13:45:35 JST 2020
#
require 'spec_helper'
describe Raabro do
describe '.nott' do
it 'hits' do
i = Raabro::Input.new('to')
t = Raabro.nott(:no0, i, :ta)
expect(t.to_a(leaves: true)).to eq(
[ :no0, 1, 0, 0, nil, :nott, [
[ nil, 0, 0, 0, nil, :str, [] ] ] ]
)
expect(i.offset).to eq(0)
end
it 'misses' do
i = Raabro::Input.new('ta')
t = Raabro.nott(:no0, i, :ta)
expect(t.to_a(leaves: true)).to eq(
[ :no0, 0, 0, 0, nil, :nott, [
[ nil, 1, 0, 2, nil, :str, 'ta' ] ] ]
)
expect(i.offset).to eq(0)
end
end
end
raabro-1.4.0/spec/ren_spec.rb 0000664 0000000 0000000 00000001271 13736726330 0016052 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Mon Sep 21 05:46:00 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.ren' do
it 'returns the tree coming from the wrapped parser' do
i = Raabro::Input.new('ta')
t = Raabro.ren('renamed', i, :nta)
expect(t.to_a(:leaves => true)).to eq(
[ 'renamed', 1, 0, 2, nil, :str, 'ta' ]
)
expect(i.offset).to eq(2)
end
end
describe '.rename' do
it 'is an alias to .ren' do
i = Raabro::Input.new('ta')
t = Raabro.rename('autre', i, :nta)
expect(t.to_a(:leaves => true)).to eq(
[ 'autre', 1, 0, 2, nil, :str, 'ta' ]
)
expect(i.offset).to eq(2)
end
end
end
raabro-1.4.0/spec/rep_spec.rb 0000664 0000000 0000000 00000003725 13736726330 0016062 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun Sep 20 09:36:16 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.rep' do
it 'returns a tree with result == 0 in case of failure' do
i = Raabro::Input.new('toto')
t = Raabro.rep(:x, i, :to, 3, 4)
expect(t.to_a(:leaves => true)).to eq(
[ :x, 0, 0, 0, nil, :rep, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 1, 2, 2, nil, :str, 'to' ],
[ nil, 0, 4, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it 'prunes' do
i = Raabro::Input.new('toto', :prune => true)
t = Raabro.rep(:x, i, :to, 3, 4)
expect(t.to_a(:leaves => true)).to eq(
[ :x, 0, 0, 0, nil, :rep, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 1, 2, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(0)
end
it "fails (min not reached)" do
i = Raabro::Input.new('toto')
t = Raabro.rep(:x, i, :to, 3)
expect(t.to_a(:leaves => true)).to eq(
[ :x, 0, 0, 0, nil, :rep, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 1, 2, 2, nil, :str, 'to' ],
[ nil, 0, 4, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it "succeeds (max set)" do
i = Raabro::Input.new('tototo')
t = Raabro.rep(:x, i, :to, 1, 2)
expect(t.to_a(:leaves => true)).to eq(
[ :x, 1, 0, 4, nil, :rep, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 1, 2, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(4)
end
it "succeeds (max not set)" do
i = Raabro::Input.new('toto')
t = Raabro.rep(:x, i, :to, 1)
expect(t.to_a(:leaves => true)).to eq(
[ :x, 1, 0, 4, nil, :rep, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 1, 2, 2, nil, :str, 'to' ],
[ nil, 0, 4, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(4)
end
end
end
raabro-1.4.0/spec/rex_spec.rb 0000664 0000000 0000000 00000001536 13736726330 0016070 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun Sep 20 07:12:35 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.rex' do
it 'hits' do
i = Raabro::Input.new('toto')
t = Raabro.rex(nil, i, /t[ua]/)
expect(t.to_a).to eq(
[ nil, 0, 0, 0, nil, :rex, [] ]
)
expect(i.offset).to eq(0)
end
it 'misses' do
i = Raabro::Input.new('toto')
t = Raabro.rex(nil, i, /(to)+/)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 4, nil, :rex, 'toto' ]
)
expect(i.offset).to eq(4)
end
it 'misses if the match is not at the current input offset' do
i = Raabro::Input.new('tato')
t = Raabro.rex(:biga, i, /(to)+/)
expect(t.to_a(:leaves => true)).to eq(
[ :biga, 0, 0, 0, nil, :rex, [] ]
)
expect(i.offset).to eq(0)
end
end
end
raabro-1.4.0/spec/sample_spec.rb 0000664 0000000 0000000 00000001050 13736726330 0016542 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun Oct 11 04:24:32 SGT 2015
#
require 'spec_helper'
module Sample::OwnRewrite include Raabro
# parse
def hello(i); str(:hello, i, 'hello'); end
#alias root exp
# not necessary since Raabro takes the last defined parser as the root
# rewrite
def rewrite(t)
[ :ok, t.string ]
end
end
describe Raabro do
describe Sample::OwnRewrite do
it 'uses its own rewrite' do
expect(
Sample::OwnRewrite.parse('hello')
).to eq(
[ :ok, 'hello' ]
)
end
end
end
raabro-1.4.0/spec/sample_xel_spec.rb 0000664 0000000 0000000 00000004744 13736726330 0017427 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Mon Sep 21 16:58:01 JST 2015
#
require 'spec_helper'
module Sample::Xel include Raabro
# parse
def pa(i); str(nil, i, '('); end
def pz(i); str(nil, i, ')'); end
def com(i); str(nil, i, ','); end
def num(i); rex(:num, i, /-?[0-9]+/); end
def args(i); eseq(:args, i, :pa, :exp, :com, :pz); end
def funame(i); rex(:funame, i, /[A-Z][A-Z0-9]*/); end
def fun(i); seq(:fun, i, :funame, :args); end
def exp(i); alt(:exp, i, :fun, :num); end
#alias root exp
# not necessary since Raabro takes the last defined parser as the root
# rewrite
def rewrite_exp(t); rewrite(t.children[0]); end
def rewrite_num(t); t.string.to_i; end
def rewrite_fun(t)
#[ t.children[0].string ] +
#t.children[1].children.inject([]) { |a, e| a << rewrite(e) if e.name; a }
[ t.children[0].string ] + t.children[1].odd_children.map { |c| rewrite(c) }
end
end
describe Raabro do
describe Sample::Xel do
describe '.funame' do
it 'hits' do
i = Raabro::Input.new('NADA')
t = Sample::Xel.funame(i)
expect(t.to_a(:leaves => true)).to eq(
[ :funame, 1, 0, 4, nil, :rex, 'NADA' ]
)
end
end
describe '.fun' do
it 'parses a function call' do
i = Raabro::Input.new('SUM(1,MUL(4,5))', :prune => true)
t = Sample::Xel.fun(i)
expect(t.result).to eq(1)
expect(
Sample::Xel.rewrite(t)
).to eq(
[ 'SUM', 1, [ 'MUL', 4, 5 ] ]
)
end
end
describe '.parse' do
it 'parses (success)' do
expect(
Sample::Xel.parse('MUL(7,-3)')
).to eq(
[ 'MUL', 7, -3 ]
)
end
it 'parses (rewrite: false, success)' do
expect(
Sample::Xel.parse('MUL(7,-3)', rewrite: false).to_s
).to eq(%{
1 :exp 0,9
1 :fun 0,9
1 :funame 0,3 "MUL"
1 :args 3,6
1 nil 3,1 "("
1 :exp 4,1
1 :num 4,1 "7"
1 nil 5,1 ","
1 :exp 6,2
1 :num 6,2 "-3"
1 nil 8,1 ")"
}.strip)
end
it 'parses (miss)' do
expect(Sample::Xel.parse('MUL(7,3) ')).to eq(nil)
expect(Sample::Xel.parse('MUL(7,3')).to eq(nil)
end
it 'parses (miss with error: true)' do
expect(
Sample::Xel.parse('MUL(7,3', error: true)
).to eq(
[ 1, 8, 7, 'parsing failed .../:exp/:fun/:args',
"MUL(7,3\n" +
" ^---" ]
)
end
end
end
end
raabro-1.4.0/spec/sample_xell_spec.rb 0000664 0000000 0000000 00000003274 13736726330 0017600 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun Dec 13 06:10:00 JST 2015
#
require 'spec_helper'
module Sample::Xell include Raabro
# parse
def pa(i); str(nil, i, '('); end
def pz(i); str(nil, i, ')'); end
def com(i); str(nil, i, ','); end
def num(i); rex(:num, i, /-?[0-9]+/); end
def args(i); eseq(nil, i, :pa, :exp, :com, :pz); end
def funame(i); rex(nil, i, /[A-Z][A-Z0-9]*/); end
def fun(i); seq(:fun, i, :funame, :args); end
def exp(i); alt(nil, i, :fun, :num); end
# rewrite
#def rewrite_(t)
#
# c = t.children.find { |c| c.length > 0 || c.name }
# c ? rewrite(c) : nil
#end
#
# part of aabro now
def rewrite_num(t); t.string.to_i; end
def rewrite_fun(t)
#as = []
#t.children[1].children.each_with_index { |e, i| as << e if i.odd? }
#[ t.children[0].string ] + as.collect { |a| rewrite(a) }
[ t.children[0].string ] +
t.children[1].odd_children.collect { |a| rewrite(a) }
end
end
describe Raabro do
describe Sample::Xell do
describe '.parse' do
it 'parses (success)' do
expect(
Sample::Xell.parse('MUL(7,-3)')
).to eq(
[ 'MUL', 7, -3 ]
)
end
it 'parses (rewrite: false, success)' do
expect(
Sample::Xell.parse('MUL(7,-3)', rewrite: false).to_s
).to eq(%{
1 nil 0,9
1 :fun 0,9
1 nil 0,3 "MUL"
1 nil 3,6
1 nil 3,1 "("
1 nil 4,1
1 :num 4,1 "7"
1 nil 5,1 ","
1 nil 6,2
1 :num 6,2 "-3"
1 nil 8,1 ")"
}.strip)
end
it 'parses (miss)' do
expect(Sample::Xell.parse('MUL(7,3) ')).to eq(nil)
expect(Sample::Xell.parse('MUL(7,3')).to eq(nil)
end
end
end
end
raabro-1.4.0/spec/seq_spec.rb 0000664 0000000 0000000 00000021311 13736726330 0016053 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun Sep 20 06:11:54 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.seq' do
it "returns a tree with result == 0 in case of failure" do
i = Raabro::Input.new('tato')
t = Raabro.seq(nil, i, :to, :ta)
expect(t.to_a).to eq(
[ nil, 0, 0, 0, nil, :seq, [
[ nil, 0, 0, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it "returns a tree with result == 0 in case of failure (at 2nd step)" do
i = Raabro::Input.new('tato')
t = Raabro.seq(nil, i, :ta, :ta)
expect(
t.to_a(:leaves => true)
).to eq(
[ nil, 0, 0, 0, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 0, 2, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it "returns a tree with result == 1 in case of success" do
i = Raabro::Input.new('tato')
t = Raabro.seq(nil, i, :ta, :to)
expect(
t.to_a(:leaves => true)
).to eq(
[ nil, 1, 0, 4, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(4)
end
it "names the result if there is a name" do
i = Raabro::Input.new('tato')
t = Raabro.seq(:x, i, :ta, :to)
expect(
t.to_a(:leaves => true)
).to eq(
[ :x, 1, 0, 4, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(4)
end
it "names in case of failure as well" do
i = Raabro::Input.new('tato')
t = Raabro.seq(:y, i, :ta, :ta)
expect(
t.to_a(:leaves => true)
).to eq(
[ :y, 0, 0, 0, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 0, 2, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it "fails when the input string ends" do
i = Raabro::Input.new('to')
t = Raabro.seq(:z, i, :to, :ta)
expect(
t.to_a(:leaves => true)
).to eq(
[ :z, 0, 0, 0, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'to' ],
[ nil, 0, 2, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it "accepts an empty input" do
i = Raabro::Input.new('tato', 4)
t = Raabro.seq(nil, i, :to, :ta)
expect(t.to_a).to eq(
[ nil, 0, 4, 0, nil, :seq, [
[ nil, 0, 4, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(4)
end
end
describe 'seq and quantifiers' do
describe 'a lonely quantifier' do
it 'raises an ArgumentError' do
i = Raabro::Input.new('tato')
expect {
t = Raabro.seq(nil, i, '?')
}.to raise_error(ArgumentError, 'lone quantifier ?')
end
end
describe 'the question mark quantifier' do
it 'lets optional elements appear in sequences (miss)' do
i = Raabro::Input.new('tato')
t = Raabro.seq(nil, i, :ta, :tu, '?', :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 4, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 0, 2, 0, nil, :str, [] ],
[ nil, 1, 2, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(4)
end
it 'lets optional elements appear in sequences (hit)' do
i = Raabro::Input.new('tatuto')
t = Raabro.seq(nil, i, :ta, :tu, '?', :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 6, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 2, nil, :str, 'tu' ],
[ nil, 1, 4, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(6)
end
it 'lets optional elements appear in sequences (fail)' do
i = Raabro::Input.new('tatututo')
t = Raabro.seq(nil, i, :ta, :tu, '?', :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 0, 0, 0, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 2, nil, :str, 'tu' ],
[ nil, 0, 4, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
end
describe 'the star quantifier' do
it 'lets optional elements recur in sequences (hit zero)' do
i = Raabro::Input.new('tato')
t = Raabro.seq(nil, i, :ta, :tu, '*', :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 4, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 0, 2, 0, nil, :str, [] ],
[ nil, 1, 2, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(4)
end
it 'lets optional elements recur in sequences (hit)' do
i = Raabro::Input.new('tatututo')
t = Raabro.seq(nil, i, :ta, :tu, '*', :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 8, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 2, nil, :str, 'tu' ],
[ nil, 1, 4, 2, nil, :str, 'tu' ],
[ nil, 0, 6, 0, nil, :str, [] ],
[ nil, 1, 6, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(8)
end
it 'stops when there is no progress' do
i = Raabro::Input.new('abc')
t = Raabro.seq(nil, i, :to_star, '*');
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 0, nil, :seq, [
[ nil, 1, 0, 0, nil, :rep, [
[ nil, 0, 0, 0, nil, :str, [] ]
] ]
] ]
)
end
end
describe 'the plus quantifier' do
it 'lets elements recur in sequences (hit)' do
i = Raabro::Input.new('tatututo')
t = Raabro.seq(nil, i, :ta, :tu, '+', :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 8, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 2, nil, :str, 'tu' ],
[ nil, 1, 4, 2, nil, :str, 'tu' ],
[ nil, 0, 6, 0, nil, :str, [] ],
[ nil, 1, 6, 2, nil, :str, 'to' ]
] ]
)
expect(i.offset).to eq(8)
end
it 'lets elements recur in sequences (fail)' do
i = Raabro::Input.new('tato')
t = Raabro.seq(nil, i, :ta, :tu, '+', :to)
expect(t.to_a(:leaves => true)).to eq(
[ nil, 0, 0, 0, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 0, 2, 0, nil, :str, [] ]
] ]
)
expect(i.offset).to eq(0)
end
it 'stops when there is no progress' do
i = Raabro::Input.new('abc')
t = Raabro.seq(nil, i, :to_star, '+');
expect(t.to_a(:leaves => true)).to eq(
[ nil, 1, 0, 0, nil, :seq, [
[ nil, 1, 0, 0, nil, :rep, [
[ nil, 0, 0, 0, nil, :str, [] ]
] ]
] ]
)
end
end
describe 'the exclamation mark' do
it 'throws an error when lonely' do
i = Raabro::Input.new('tato')
expect {
t = Raabro.seq(nil, i, '!')
}.to raise_error(ArgumentError, 'lone quantifier !')
end
it 'hits post' do
i = Raabro::Input.new('tatu')
t = Raabro.seq(nil, i, :ta, :ta, '!')
expect(t.to_a(leaves: true)).to eq(
[ nil, 1, 0, 2, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 0, nil, :nott, [
[ nil, 0, 2, 0, nil, :str, [] ] ] ] ] ]
)
expect(i.offset).to eq(2)
end
it 'misses post' do
i = Raabro::Input.new('tata')
t = Raabro.seq(nil, i, :ta, :ta, '!')
expect(t.to_a(leaves: true)).to eq(
[ nil, 0, 0, 0, nil, :seq, [
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 0, 2, 0, nil, :nott, [
[ nil, 1, 2, 2, nil, :str, 'ta' ] ] ] ] ]
)
expect(i.offset).to eq(0)
end
it 'hits pre' do
i = Raabro::Input.new('tatu')
t = Raabro.seq(nil, i, :tu, '!', :ta, :tu)
expect(t.to_a(leaves: true)).to eq(
[ nil, 1, 0, 4, nil, :seq, [
[ nil, 1, 0, 0, nil, :nott, [
[ nil, 0, 0, 0, nil, :str, [] ] ] ],
[ nil, 1, 0, 2, nil, :str, 'ta' ],
[ nil, 1, 2, 2, nil, :str, 'tu' ] ] ]
)
expect(i.offset).to eq(4)
end
it 'misses pre' do
i = Raabro::Input.new('tutu')
t = Raabro.seq(nil, i, :tu, '!', :ta, :tu)
expect(t.to_a(leaves: true)).to eq(
[ nil, 0, 0, 0, nil, :seq, [
[ nil, 0, 0, 0, nil, :nott, [
[ nil, 1, 0, 2, nil, :str, 'tu' ] ] ] ] ]
)
expect(i.offset).to eq(0)
end
end
end
end
raabro-1.4.0/spec/spec_helper.rb 0000664 0000000 0000000 00000003213 13736726330 0016543 0 ustar 00root root 0000000 0000000
#
# Specifying raabro
#
# Sat Sep 19 21:12:35 JST 2015
#
require 'pp'
require 'raabro'
#
# parsers
def ta(i); Raabro.str(nil, i, 'ta'); end
def to(i); Raabro.str(nil, i, 'to'); end
def tu(i); Raabro.str(nil, i, 'tu'); end
def to_plus(input); Raabro.rep(:tos, input, :to, 1); end
def to_star(input); Raabro.rep(nil, input, :to, 0); end
def to_qmark(input); Raabro.rep(nil, input, :to, 0, 1); end
def nta(i); Raabro.str('the-ta', i, 'ta'); end
def cha(i); Raabro.rex(nil, i, /\A[a-z]/); end
def com(i); Raabro.str(nil, i, ','); end
def chas(i); Raabro.rex(nil, i, /[a-z ]+/i); end
def lt(i); Raabro.str(nil, i, '<'); end
def gt(i); Raabro.str(nil, i, '>'); end
def onex(i); Raabro.str(:onex, i, 'x'); end
def twox(i); Raabro.str(:twox, i, 'xx'); end
def deux(i); Raabro.str(:deux, i, 'xx'); end
# testing eseq...
def acom(i); Raabro.rex(nil, i, /,?/); end
def aval(i); Raabro.rex(nil, i, /[a-z]?/); end
def arr(i); Raabro.eseq(nil, i, :lt, :aval, :acom, :gt); end
#
# test modules
module Sample; end
module Sample::Cal include Raabro
def sp(i); rex(nil, i, /\s+/); end
def num(i); rex(:num, i, /-?[0-9]+/); end
def op(i); rex(:op, i, /[+\-*\/]/); end
def item(i); alt(:item, i, :num, :op); end
def suite(i); jseq(nil, i, :item, :sp); end
end
module Sample::Arith include Raabro
def number(i); rex(:number, i, /-?[0-9]+\s*/); end
def plus(i); rex(:plus, i, /\+\s*/); end
def minus(i); rex(:minus, i, /-\s*/); end
def addition(i); seq(:addition, i, :number, :plus, :op_or_num); end
def substraction(i); seq(:substraction, i, :number, :minus, :op_or_num); end
def op_or_num(i); alt(nil, i, :addition, :substraction, :number); end
end
raabro-1.4.0/spec/str_spec.rb 0000664 0000000 0000000 00000002531 13736726330 0016076 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Sun Sep 20 06:11:54 JST 2015
#
require 'spec_helper'
describe Raabro do
describe '.str' do
it 'returns a tree with result == 0 in case of failure' do
i = Raabro::Input.new('toto')
t = Raabro.str(nil, i, 'nada')
expect(t.to_a).to eq(
[ nil, 0, 0, 0, nil, :str, [] ]
)
expect(i.offset).to eq(0)
end
it "returns a tree with result == 1 in case of success" do
i = Raabro::Input.new('toto')
t = Raabro.str(nil, i, 'toto')
expect(t.to_a).to eq(
[ nil, 1, 0, 4, nil, :str, [] ]
)
expect(i.offset).to eq(4)
end
it "names the result if there is a name" do
i = Raabro::Input.new('toto')
t = Raabro.str(:x, i, 'toto')
expect(t.to_a).to eq(
[ :x, 1, 0, 4, nil, :str, [] ]
)
expect(i.offset).to eq(4)
end
it "names in case of failure as well" do
i = Raabro::Input.new('toto')
t = Raabro.str(:y, i, 'nada')
expect(t.to_a).to eq(
[ :y, 0, 0, 0, nil, :str, [] ]
)
expect(i.offset).to eq(0)
end
it "accepts an empty input" do
i = Raabro::Input.new('toto')
i.offset = 4
t = Raabro.str(nil, i, 'nada')
expect(t.to_a).to eq(
[ nil, 0, 4, 0, nil, :str, [] ]
)
expect(i.offset).to eq(4)
end
end
end
raabro-1.4.0/spec/tree_spec.rb 0000664 0000000 0000000 00000010662 13736726330 0016231 0 ustar 00root root 0000000 0000000
#
# specifying raabro
#
# Tue Sep 22 07:55:52 JST 2015
#
require 'spec_helper'
describe Raabro::Tree do
describe '.lookup' do
it 'returns the first node with the given name' do
t = Sample::Cal.parse('4 5 6 + 1 2 3 * +', rewrite: false)
expect(
t.lookup('item').to_a(:leaves)
).to eq(
[ :item, 1, 0, 1, nil, :alt, [
[ :num, 1, 0, 1, nil, :rex, '4' ] ] ]
)
end
it 'returns the first named node if the given name is nil' do
t = Sample::Cal.parse('4 5 6 + 1 2 3 * +', rewrite: false)
expect(
t.lookup.to_a(:leaves)
).to eq(
[ :item, 1, 0, 1, nil, :alt, [
[ :num, 1, 0, 1, nil, :rex, '4' ] ] ]
)
end
end
describe '.sublookup' do
it 'skips the callee node' do
t = Sample::Cal.parse('4 5 6 + 1 2 3 * +', rewrite: false)
t = t.children[0]
expect(
t.sublookup.to_a(:leaves)
).to eq(
[ :num, 1, 0, 1, nil, :rex, '4' ]
)
end
end
describe '.gather' do
it 'returns all the nodes with a given name' do
t = Sample::Cal.parse('4 5 6 + 1 2 3 * +', rewrite: false)
expect(
t.gather('op').collect { |n| n.to_a(:leaves) }
).to eq(
[ [ :op, 1, 6, 1, nil, :rex, '+' ],
[ :op, 1, 14, 1, nil, :rex, '*' ],
[ :op, 1, 16, 1, nil, :rex, '+' ] ]
)
end
it 'returns all the nodes with a name if the given name is nil' do
t = Sample::Cal.parse('4 5 6 + 1 2 3 * +', rewrite: false)
expect(
t.gather.collect { |n| n.to_a(:leaves) }
).to eq([
[ :item, 1, 0, 1, nil, :alt, [
[ :num, 1, 0, 1, nil, :rex, '4' ] ] ],
[ :item, 1, 2, 1, nil, :alt, [
[ :num, 1, 2, 1, nil, :rex, '5' ] ] ],
[ :item, 1, 4, 1, nil, :alt, [
[ :num, 1, 4, 1, nil, :rex, '6' ] ] ],
[ :item, 1, 6, 1, nil, :alt, [
[ :op, 1, 6, 1, nil, :rex, '+' ] ] ],
[ :item, 1, 8, 1, nil, :alt, [
[ :num, 1, 8, 1, nil, :rex, '1' ] ] ],
[ :item, 1, 10, 1, nil, :alt, [
[ :num, 1, 10, 1, nil, :rex, '2' ] ] ],
[ :item, 1, 12, 1, nil, :alt, [
[ :num, 1, 12, 1, nil, :rex, '3' ] ] ],
[ :item, 1, 14, 1, nil, :alt, [
[ :op, 1, 14, 1, nil, :rex, '*' ] ] ],
[ :item, 1, 16, 1, nil, :alt, [
[ :op, 1, 16, 1, nil, :rex, '+' ] ] ]
])
end
end
describe '.subgather' do
it 'skips the callee node' do
t = Sample::Cal.parse('4 5 6 + 1 2 3 * +', rewrite: false)
expect(
t.children[0].subgather.collect { |n| n.to_a(:leaves) }
).to eq([
[ :num, 1, 0, 1, nil, :rex, '4' ]
])
end
end
describe '.string' do
it 'returns the string covered by the tree' do
t = Sample::Arith.parse('11 + 12', rewrite: false)
#Raabro.pp(t, colours: true)
expect(t.string).to eq('11 + 12')
expect(t.sublookup(:number).string).to eq('11 ')
expect(t.sublookup(:plus).string).to eq('+ ')
end
end
describe '.strinp' do
it 'returns the string covered by the tree by stripped' do
t = Sample::Arith.parse('11 + 13', rewrite: false)
#Raabro.pp(t, colours: true)
expect(t.strinp).to eq('11 + 13')
expect(t.sublookup(:number).strinp).to eq('11')
expect(t.sublookup(:plus).strinp).to eq('+')
end
end
describe '.strim' do
it 'returns the string covered by the tree by stripped' do
t = Sample::Arith.parse('11 + 13', rewrite: false)
#Raabro.pp(t, colours: true)
expect(t.strim).to eq('11 + 13')
expect(t.sublookup(:number).strim).to eq('11')
expect(t.sublookup(:plus).strim).to eq('+')
end
end
describe '.strind' do
it 'returns the string covered by the tree downcased' do
i = Raabro::Input.new('Hello')
t = chas(i)
expect(t.strind).to eq('hello')
end
end
describe '.strinpd' do
it 'returns the string covered by the tree stripped and downcased' do
i = Raabro::Input.new('AloaH ')
t = chas(i)
expect(t.strinpd).to eq('aloah')
end
end
describe '.symbol' do
it 'returns the string covered by the tree as a symbol' do
i = Raabro::Input.new('Hello ')
t = chas(i)
expect(t.symbol).to eq(:Hello)
end
end
describe '.symbod' do
it 'returns the string covered by the tree as a downcased symbol' do
i = Raabro::Input.new('Hello ')
t = chas(i)
expect(t.symbod).to eq(:hello)
end
end
end