Full Code of brixen/poetics for AI

master b382a804e3d3 cached
26 files
34.8 KB
10.7k tokens
120 symbols
1 requests
Download .txt
Repository: brixen/poetics
Branch: master
Commit: b382a804e3d3
Files: 26
Total size: 34.8 KB

Directory structure:
gitextract_l4a1w08_/

├── .gitignore
├── Gemfile
├── LICENSE
├── README
├── Rakefile
├── bin/
│   └── poetics
├── lib/
│   ├── poetics/
│   │   ├── library/
│   │   │   └── code_loader.rb
│   │   ├── library.rb
│   │   ├── parser/
│   │   │   ├── parser.rb
│   │   │   └── poetics.kpeg
│   │   ├── parser.rb
│   │   ├── syntax/
│   │   │   ├── ast.rb
│   │   │   ├── literal.rb
│   │   │   └── node.rb
│   │   ├── syntax.rb
│   │   └── version.rb
│   └── poetics.rb
├── poetics.gemspec
└── spec/
    ├── custom/
    │   ├── matchers/
    │   │   └── parse_as.rb
    │   ├── runner/
    │   │   └── relates.rb
    │   └── utils/
    │       ├── options.rb
    │       └── script.rb
    ├── custom.rb
    ├── default.mspec
    ├── spec_helper.rb
    └── syntax/
        └── literal_spec.rb

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.rbc
*.gem
.bundle
Gemfile.lock
pkg/*


================================================
FILE: Gemfile
================================================
source "http://rubygems.org"

gemspec

gem "rake",   ">= 0.8.7"
gem "kpeg",   "~> 0.8.2"
gem "mspec",  "~> 1.5.17"


================================================
FILE: LICENSE
================================================
Copyright (c) 2011 Brian Ford. All rights reserved.

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.


================================================
FILE: README
================================================
1. What is Poetics?

A native implementation of CoffeeScript [1] that runs on the Rubinius VM [2].

  Q. Whence comes the name Poetics?

  A. Poetics is a partial anagram of the word CoffeeScript. It is also a nod
     to Jeremy Ashkenas, the author of CoffeeScript, and his interest in code
     as literature.

  Q. Why a native implementation?

  A. CoffeeScript is an interesting language in its own right. Rather than
     merely being a syntax layer on top of Javascript, and bound to expressing
     its semantics in those of Javascript, it deserves its own implementation.
     Many of the reasons to use CoffeeScript in Node.js would also apply to
     using this native implementation.


2. License

Poetics is MIT licensed. See the LICENSE file.


3. Installation

First, install Rubinius:

  1. Using RVM (http://rvm.beginrescueend.com).

    rvm install rbx

  2. Or directly (http://rubini.us/doc/en/what-is-rubinius/).

Second, install Poetics:

    rbx -S gem install poetics


4. Running Poetics

Poetics provides a REPL for exploratory programming or runs CoffeeScript
scripts.

    rbx -S poetics -h

The REPL presently just parses code and returns an S-Expression
representation:

    $ rbx -S poetics
    > 42
    [:number, 42.0, 1, 1]
    > "hello, y'all"
    [:string, "hello, y'all", 1, 1]
    >

To exit the REPL hit CTRL + d.


5. Getting Help

Poetics is a work in progress. If you encounter trouble, please file an issue
at https://github.com/brixen/poetics/issues


6. Contributing

If you find Poetics interesting and would like to help out, fork the project
on Github and submit a pull request.


7. People

Poetics was created by Brian Ford (brixen) to force him to really learn
Javascript and CoffeeScript.

<add your name here>


8. Credits

Jeremy has created an very interesting language in CoffeeScript. This
implementation steals bits and pieces from other projects:

* Rubinius (https://github.com/rubinius/rubinius/)
* KPeg (https://github.com/evanphx/kpeg/)
* Atomy (https://github.com/vito/atomy/)
* Poison (https://github.com/brixen/poison/)
* Talon (https://github.com/evanphx/talon/)


[1] CoffeeScript (http://jashkenas.github.com/coffee-script/)
[2] Rubinius (http://rubini.us)


================================================
FILE: Rakefile
================================================
require 'bundler'
Bundler::GemHelper.install_tasks

task :default => :spec

base = File.expand_path '../lib/poetics/parser', __FILE__

grammar = "#{base}/poetics.kpeg"
parser  = "#{base}/parser.rb"

file parser => grammar do
  sh "rbx -S kpeg -f -s #{base}/poetics.kpeg -o #{base}/parser.rb"
end

desc "Convert the grammar description to a parser"
task :parser => parser

desc "Run the specs (default)"
task :spec => :parser do
  sh "mspec spec"
end


================================================
FILE: bin/poetics
================================================
#!/usr/bin/env rbx
#
# vim: filetype=ruby

$:.unshift File.expand_path('../../lib', __FILE__)

require 'readline'
require 'poetics'

class Poetics::Script
  HISTORY = File.expand_path "~/.poetics_history"

  attr_accessor :prompt

  def initialize
    @evals = []
    @script = nil
    @history = []
  end

  def options(argv=ARGV)
    options = Rubinius::Options.new "Usage: poetics [options] [script]", 20

    options.on "-", "Read and evaluate code from STDIN" do
      @evals << STDIN.read
    end

    options.on "-c", "FILE", "Check the syntax of FILE" do |f|
      begin
        begin
          Poetics::Parser.parse_file f
        rescue => e
          e.render
          exit 1
        end

        puts "Syntax OK"
        exit 0
      end
    end

    options.on "-e", "CODE", "Execute CODE" do |e|
      @evals << e
    end

    options.on "-v", "--version", "Display the version" do
      puts Poetics::COMMAND_VERSION
    end

    options.on "-h", "--help", "Display this help" do
      puts options
      exit 0
    end

    options.doc ""

    rest = options.parse(argv)
    @script ||= rest.first
  end

  def evals
    return if @evals.empty?

    Poetics::CodeLoader.evaluate @evals.join("\n")
  end

  def script
    return unless @script

    if File.exists? @script
      Poetics::CodeLoader.execute_file @script
    else
      STDERR.puts "Unable to find '#{@script}' to run"
      exit 1
    end
  end

  def load_history
    return unless File.exists? HISTORY

    File.open HISTORY, "r" do |f|
      f.each { |l| Readline::HISTORY << l }
    end
  end

  def save_history
    File.open HISTORY, "w" do |f|
      @history.last(100).map { |s| f.puts s }
    end
  end

  def record_history(str)
    @history << str
  end

  def start_prompt
    @prompt = "> "
  end

  def continue_prompt
    @prompt = ". "
  end

  def repl
    return if @script
    load_history
    start_prompt

    begin
      snippet = ""
      while str = Readline.readline(prompt)
        break if str.nil? and snippet.empty?
        next if str.empty?

        snippet << str
        begin
          value = Poetics::CodeLoader.evaluate snippet
          p value

          record_history snippet
          snippet = ""
          start_prompt
        rescue => e
          STDERR.puts e
        end
      end
    ensure
      save_history
    end
  end

  def main
    options
    evals
    script
    repl
  end
end

Poetics::Script.new.main


================================================
FILE: lib/poetics/library/code_loader.rb
================================================
module Poetics
  class CodeLoader
    def self.evaluate(string)
      # We're just parsing for now
      Poetics::Parser.parse_to_sexp string
    end

    def self.execute_file(name)
      value = Poetics::Parser.parse_to_sexp IO.read(name)
      p value
    end
  end
end


================================================
FILE: lib/poetics/library.rb
================================================
require 'poetics/library/code_loader'


================================================
FILE: lib/poetics/parser/parser.rb
================================================
class Poetics::Parser
# STANDALONE START
    def setup_parser(str, debug=false)
      @string = str
      @pos = 0
      @memoizations = Hash.new { |h,k| h[k] = {} }
      @result = nil
      @failed_rule = nil
      @failing_rule_offset = -1

      setup_foreign_grammar
    end

    # This is distinct from setup_parser so that a standalone parser
    # can redefine #initialize and still have access to the proper
    # parser setup code.
    #
    def initialize(str, debug=false)
      setup_parser(str, debug)
    end

    attr_reader :string
    attr_reader :failing_rule_offset
    attr_accessor :result, :pos

    # STANDALONE START
    def current_column(target=pos)
      if c = string.rindex("\n", target-1)
        return target - c - 1
      end

      target + 1
    end

    def current_line(target=pos)
      cur_offset = 0
      cur_line = 0

      string.each_line do |line|
        cur_line += 1
        cur_offset += line.size
        return cur_line if cur_offset >= target
      end

      -1
    end

    def lines
      lines = []
      string.each_line { |l| lines << l }
      lines
    end

    #

    def get_text(start)
      @string[start..@pos-1]
    end

    def show_pos
      width = 10
      if @pos < width
        "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
      else
        "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
      end
    end

    def failure_info
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset

      if @failed_rule.kind_of? Symbol
        info = self.class::Rules[@failed_rule]
        "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
      else
        "line #{l}, column #{c}: failed rule '#{@failed_rule}'"
      end
    end

    def failure_caret
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset

      line = lines[l-1]
      "#{line}\n#{' ' * (c - 1)}^"
    end

    def failure_character
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset
      lines[l-1][c-1, 1]
    end

    def failure_oneline
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset

      char = lines[l-1][c-1, 1]

      if @failed_rule.kind_of? Symbol
        info = self.class::Rules[@failed_rule]
        "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
      else
        "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
      end
    end

    class ParseError < RuntimeError
    end

    def raise_error
      raise ParseError, failure_oneline
    end

    def show_error(io=STDOUT)
      error_pos = @failing_rule_offset
      line_no = current_line(error_pos)
      col_no = current_column(error_pos)

      io.puts "On line #{line_no}, column #{col_no}:"

      if @failed_rule.kind_of? Symbol
        info = self.class::Rules[@failed_rule]
        io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
      else
        io.puts "Failed to match rule '#{@failed_rule}'"
      end

      io.puts "Got: #{string[error_pos,1].inspect}"
      line = lines[line_no-1]
      io.puts "=> #{line}"
      io.print(" " * (col_no + 3))
      io.puts "^"
    end

    def set_failed_rule(name)
      if @pos > @failing_rule_offset
        @failed_rule = name
        @failing_rule_offset = @pos
      end
    end

    attr_reader :failed_rule

    def match_string(str)
      len = str.size
      if @string[pos,len] == str
        @pos += len
        return str
      end

      return nil
    end

    def scan(reg)
      if m = reg.match(@string[@pos..-1])
        width = m.end(0)
        @pos += width
        return true
      end

      return nil
    end

    if "".respond_to? :getbyte
      def get_byte
        if @pos >= @string.size
          return nil
        end

        s = @string.getbyte @pos
        @pos += 1
        s
      end
    else
      def get_byte
        if @pos >= @string.size
          return nil
        end

        s = @string[@pos]
        @pos += 1
        s
      end
    end

    def parse(rule=nil)
      if !rule
        _root ? true : false
      else
        # This is not shared with code_generator.rb so this can be standalone
        method = rule.gsub("-","_hyphen_")
        __send__("_#{method}") ? true : false
      end
    end

    class LeftRecursive
      def initialize(detected=false)
        @detected = detected
      end

      attr_accessor :detected
    end

    class MemoEntry
      def initialize(ans, pos)
        @ans = ans
        @pos = pos
        @uses = 1
        @result = nil
      end

      attr_reader :ans, :pos, :uses, :result

      def inc!
        @uses += 1
      end

      def move!(ans, pos, result)
        @ans = ans
        @pos = pos
        @result = result
      end
    end

    def external_invoke(other, rule, *args)
      old_pos = @pos
      old_string = @string

      @pos = other.pos
      @string = other.string

      begin
        if val = __send__(rule, *args)
          other.pos = @pos
          other.result = @result
        else
          other.set_failed_rule "#{self.class}##{rule}"
        end
        val
      ensure
        @pos = old_pos
        @string = old_string
      end
    end

    def apply_with_args(rule, *args)
      memo_key = [rule, args]
      if m = @memoizations[memo_key][@pos]
        m.inc!

        prev = @pos
        @pos = m.pos
        if m.ans.kind_of? LeftRecursive
          m.ans.detected = true
          return nil
        end

        @result = m.result

        return m.ans
      else
        lr = LeftRecursive.new(false)
        m = MemoEntry.new(lr, @pos)
        @memoizations[memo_key][@pos] = m
        start_pos = @pos

        ans = __send__ rule, *args

        m.move! ans, @pos, @result

        # Don't bother trying to grow the left recursion
        # if it's failing straight away (thus there is no seed)
        if ans and lr.detected
          return grow_lr(rule, args, start_pos, m)
        else
          return ans
        end

        return ans
      end
    end

    def apply(rule)
      if m = @memoizations[rule][@pos]
        m.inc!

        prev = @pos
        @pos = m.pos
        if m.ans.kind_of? LeftRecursive
          m.ans.detected = true
          return nil
        end

        @result = m.result

        return m.ans
      else
        lr = LeftRecursive.new(false)
        m = MemoEntry.new(lr, @pos)
        @memoizations[rule][@pos] = m
        start_pos = @pos

        ans = __send__ rule

        m.move! ans, @pos, @result

        # Don't bother trying to grow the left recursion
        # if it's failing straight away (thus there is no seed)
        if ans and lr.detected
          return grow_lr(rule, nil, start_pos, m)
        else
          return ans
        end

        return ans
      end
    end

    def grow_lr(rule, args, start_pos, m)
      while true
        @pos = start_pos
        @result = m.result

        if args
          ans = __send__ rule, *args
        else
          ans = __send__ rule
        end
        return nil unless ans

        break if @pos <= m.pos

        m.move! ans, @pos, @result
      end

      @result = m.result
      @pos = m.pos
      return m.ans
    end

    class RuleInfo
      def initialize(name, rendered)
        @name = name
        @rendered = rendered
      end

      attr_reader :name, :rendered
    end

    def self.rule_info(name, rendered)
      RuleInfo.new(name, rendered)
    end

    #
  def setup_foreign_grammar; end

  # root = - value? - end
  def _root

    _save = self.pos
    while true # sequence
      _tmp = apply(:__hyphen_)
      unless _tmp
        self.pos = _save
        break
      end
      _save1 = self.pos
      _tmp = apply(:_value)
      unless _tmp
        _tmp = true
        self.pos = _save1
      end
      unless _tmp
        self.pos = _save
        break
      end
      _tmp = apply(:__hyphen_)
      unless _tmp
        self.pos = _save
        break
      end
      _tmp = apply(:_end)
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_root unless _tmp
    return _tmp
  end

  # end = !.
  def _end
    _save = self.pos
    _tmp = get_byte
    _tmp = _tmp ? nil : true
    self.pos = _save
    set_failed_rule :_end unless _tmp
    return _tmp
  end

  # - = (" " | "\t" | "\n")*
  def __hyphen_
    while true

      _save1 = self.pos
      while true # choice
        _tmp = match_string(" ")
        break if _tmp
        self.pos = _save1
        _tmp = match_string("\t")
        break if _tmp
        self.pos = _save1
        _tmp = match_string("\n")
        break if _tmp
        self.pos = _save1
        break
      end # end choice

      break unless _tmp
    end
    _tmp = true
    set_failed_rule :__hyphen_ unless _tmp
    return _tmp
  end

  # value = (string | number | boolean)
  def _value

    _save = self.pos
    while true # choice
      _tmp = apply(:_string)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_number)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_boolean)
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_value unless _tmp
    return _tmp
  end

  # boolean = position (true | false | null | undefined)
  def _boolean

    _save = self.pos
    while true # sequence
      _tmp = apply(:_position)
      unless _tmp
        self.pos = _save
        break
      end

      _save1 = self.pos
      while true # choice
        _tmp = apply(:_true)
        break if _tmp
        self.pos = _save1
        _tmp = apply(:_false)
        break if _tmp
        self.pos = _save1
        _tmp = apply(:_null)
        break if _tmp
        self.pos = _save1
        _tmp = apply(:_undefined)
        break if _tmp
        self.pos = _save1
        break
      end # end choice

      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_boolean unless _tmp
    return _tmp
  end

  # true = "true" {true_value}
  def _true

    _save = self.pos
    while true # sequence
      _tmp = match_string("true")
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; true_value; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_true unless _tmp
    return _tmp
  end

  # false = "false" {false_value}
  def _false

    _save = self.pos
    while true # sequence
      _tmp = match_string("false")
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; false_value; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_false unless _tmp
    return _tmp
  end

  # null = "null" {null_value}
  def _null

    _save = self.pos
    while true # sequence
      _tmp = match_string("null")
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; null_value; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_null unless _tmp
    return _tmp
  end

  # undefined = "undefined" {undefined_value}
  def _undefined

    _save = self.pos
    while true # sequence
      _tmp = match_string("undefined")
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; undefined_value; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_undefined unless _tmp
    return _tmp
  end

  # number = position (real | hex | int)
  def _number

    _save = self.pos
    while true # sequence
      _tmp = apply(:_position)
      unless _tmp
        self.pos = _save
        break
      end

      _save1 = self.pos
      while true # choice
        _tmp = apply(:_real)
        break if _tmp
        self.pos = _save1
        _tmp = apply(:_hex)
        break if _tmp
        self.pos = _save1
        _tmp = apply(:_int)
        break if _tmp
        self.pos = _save1
        break
      end # end choice

      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_number unless _tmp
    return _tmp
  end

  # hexdigits = /[0-9A-Fa-f]/
  def _hexdigits
    _tmp = scan(/\A(?-mix:[0-9A-Fa-f])/)
    set_failed_rule :_hexdigits unless _tmp
    return _tmp
  end

  # hex = "0x" < hexdigits+ > {hexadecimal(text)}
  def _hex

    _save = self.pos
    while true # sequence
      _tmp = match_string("0x")
      unless _tmp
        self.pos = _save
        break
      end
      _text_start = self.pos
      _save1 = self.pos
      _tmp = apply(:_hexdigits)
      if _tmp
        while true
          _tmp = apply(:_hexdigits)
          break unless _tmp
        end
        _tmp = true
      else
        self.pos = _save1
      end
      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; hexadecimal(text); end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_hex unless _tmp
    return _tmp
  end

  # digits = ("0" | /[1-9]/ /[0-9]/*)
  def _digits

    _save = self.pos
    while true # choice
      _tmp = match_string("0")
      break if _tmp
      self.pos = _save

      _save1 = self.pos
      while true # sequence
        _tmp = scan(/\A(?-mix:[1-9])/)
        unless _tmp
          self.pos = _save1
          break
        end
        while true
          _tmp = scan(/\A(?-mix:[0-9])/)
          break unless _tmp
        end
        _tmp = true
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_digits unless _tmp
    return _tmp
  end

  # int = < digits > {number(text)}
  def _int

    _save = self.pos
    while true # sequence
      _text_start = self.pos
      _tmp = apply(:_digits)
      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; number(text); end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_int unless _tmp
    return _tmp
  end

  # real = < digits "." digits ("e" /[-+]/? /[0-9]/+)? > {number(text)}
  def _real

    _save = self.pos
    while true # sequence
      _text_start = self.pos

      _save1 = self.pos
      while true # sequence
        _tmp = apply(:_digits)
        unless _tmp
          self.pos = _save1
          break
        end
        _tmp = match_string(".")
        unless _tmp
          self.pos = _save1
          break
        end
        _tmp = apply(:_digits)
        unless _tmp
          self.pos = _save1
          break
        end
        _save2 = self.pos

        _save3 = self.pos
        while true # sequence
          _tmp = match_string("e")
          unless _tmp
            self.pos = _save3
            break
          end
          _save4 = self.pos
          _tmp = scan(/\A(?-mix:[-+])/)
          unless _tmp
            _tmp = true
            self.pos = _save4
          end
          unless _tmp
            self.pos = _save3
            break
          end
          _save5 = self.pos
          _tmp = scan(/\A(?-mix:[0-9])/)
          if _tmp
            while true
              _tmp = scan(/\A(?-mix:[0-9])/)
              break unless _tmp
            end
            _tmp = true
          else
            self.pos = _save5
          end
          unless _tmp
            self.pos = _save3
          end
          break
        end # end sequence

        unless _tmp
          _tmp = true
          self.pos = _save2
        end
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; number(text); end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_real unless _tmp
    return _tmp
  end

  # string = position "\"" < /[^\\"]*/ > "\"" {string_value(text)}
  def _string

    _save = self.pos
    while true # sequence
      _tmp = apply(:_position)
      unless _tmp
        self.pos = _save
        break
      end
      _tmp = match_string("\"")
      unless _tmp
        self.pos = _save
        break
      end
      _text_start = self.pos
      _tmp = scan(/\A(?-mix:[^\\"]*)/)
      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      _tmp = match_string("\"")
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin; string_value(text); end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_string unless _tmp
    return _tmp
  end

  # line = { current_line }
  def _line
    @result = begin;  current_line ; end
    _tmp = true
    set_failed_rule :_line unless _tmp
    return _tmp
  end

  # column = { current_column }
  def _column
    @result = begin;  current_column ; end
    _tmp = true
    set_failed_rule :_column unless _tmp
    return _tmp
  end

  # position = line:l column:c { position(l, c) }
  def _position

    _save = self.pos
    while true # sequence
      _tmp = apply(:_line)
      l = @result
      unless _tmp
        self.pos = _save
        break
      end
      _tmp = apply(:_column)
      c = @result
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;  position(l, c) ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_position unless _tmp
    return _tmp
  end

  Rules = {}
  Rules[:_root] = rule_info("root", "- value? - end")
  Rules[:_end] = rule_info("end", "!.")
  Rules[:__hyphen_] = rule_info("-", "(\" \" | \"\\t\" | \"\\n\")*")
  Rules[:_value] = rule_info("value", "(string | number | boolean)")
  Rules[:_boolean] = rule_info("boolean", "position (true | false | null | undefined)")
  Rules[:_true] = rule_info("true", "\"true\" {true_value}")
  Rules[:_false] = rule_info("false", "\"false\" {false_value}")
  Rules[:_null] = rule_info("null", "\"null\" {null_value}")
  Rules[:_undefined] = rule_info("undefined", "\"undefined\" {undefined_value}")
  Rules[:_number] = rule_info("number", "position (real | hex | int)")
  Rules[:_hexdigits] = rule_info("hexdigits", "/[0-9A-Fa-f]/")
  Rules[:_hex] = rule_info("hex", "\"0x\" < hexdigits+ > {hexadecimal(text)}")
  Rules[:_digits] = rule_info("digits", "(\"0\" | /[1-9]/ /[0-9]/*)")
  Rules[:_int] = rule_info("int", "< digits > {number(text)}")
  Rules[:_real] = rule_info("real", "< digits \".\" digits (\"e\" /[-+]/? /[0-9]/+)? > {number(text)}")
  Rules[:_string] = rule_info("string", "position \"\\\"\" < /[^\\\\\"]*/ > \"\\\"\" {string_value(text)}")
  Rules[:_line] = rule_info("line", "{ current_line }")
  Rules[:_column] = rule_info("column", "{ current_column }")
  Rules[:_position] = rule_info("position", "line:l column:c { position(l, c) }")
end


================================================
FILE: lib/poetics/parser/poetics.kpeg
================================================
%% name = Poetics::Parser

root      = - value? - end

end       = !.
-         = (" " | "\t" | "\n")*

value     = string
          | number
          | boolean


boolean   = position (
            true
          | false
          | null
          | undefined)

true      = "true" ~true_value
false     = "false" ~false_value
null      = "null" ~null_value
undefined = "undefined" ~undefined_value


number    = position (
            real
          | hex
          | int )

hexdigits = /[0-9A-Fa-f]/
hex       = '0x' < hexdigits+ > ~hexadecimal(text)
digits    = '0' | /[1-9]/ /[0-9]/*
int       = < digits > ~number(text)
real      = < digits '.' digits ('e' /[-+]/? /[0-9]/+)? > ~number(text)


string    = position '"' < /[^\\"]*/ > '"' ~string_value(text)

# keep track of column and line
line      = { current_line }
column    = { current_column }
position  = line:l column:c { position(l, c) }


================================================
FILE: lib/poetics/parser.rb
================================================
require 'poetics/parser/parser'

class Poetics::Parser
  include Poetics::Syntax

  def self.parse_to_sexp(string)
    parser = new string
    unless parser.parse
      parser.raise_error
    end

    parser.result.to_sexp
  end

  attr_reader :line, :column

  def position(line, column)
    @line = line
    @column = column
  end
end


================================================
FILE: lib/poetics/syntax/ast.rb
================================================
module Poetics
  module Syntax
    def number(value)
      Number.new line, column, value
    end

    def hexadecimal(value)
      Number.new line, column, value.to_i(16)
    end

    def true_value
      True.new line, column
    end

    def false_value
      False.new line, column
    end

    def null_value
      Null.new line, column
    end

    def undefined_value
      Undefined.new line, column
    end

    def string_value(value)
      String.new line, column, value
    end
  end
end


================================================
FILE: lib/poetics/syntax/literal.rb
================================================
module Poetics
  module Syntax
    class Value < Node
      def to_sexp
        [sexp_name, value, line, column]
      end
    end

    class Number < Value
      attr_accessor :value

      def initialize(line, column, value)
        super
        @value = value.to_f
      end

      def sexp_name
        :number
      end
    end

    class Boolean < Node
      def to_sexp
        [sexp_name, line, column]
      end
    end

    class True < Boolean
      def sexp_name
        :true
      end
    end

    class False < Boolean
      def sexp_name
        :false
      end
    end

    class Null < Boolean
      def sexp_name
        :null
      end
    end

    class Undefined < Boolean
      def sexp_name
        :undefined
      end
    end

    class String < Value
      attr_accessor :value

      def initialize(line, column, text)
        super
        @value = text
      end

      def sexp_name
        :string
      end
    end
  end
end


================================================
FILE: lib/poetics/syntax/node.rb
================================================
module Poetics
  module Syntax
    class Node
      attr_accessor :line, :column

      def initialize(line, column, *)
        @line = line
        @column = column
      end

      def to_sexp
      end
    end
  end
end


================================================
FILE: lib/poetics/syntax.rb
================================================
require 'poetics/syntax/node'
require 'poetics/syntax/literal'
require 'poetics/syntax/ast'


================================================
FILE: lib/poetics/version.rb
================================================
module Poetics
  VERSION = "0.0.1"
  RELEASE_DATE = "yyyy-mm-dd"
  COMMAND_VERSION = "poetics #{VERSION} (1.1.0 #{RELEASE_DATE})"
end


================================================
FILE: lib/poetics.rb
================================================
require 'poetics/version'
require 'poetics/syntax'
require 'poetics/parser'
require 'poetics/library'


================================================
FILE: poetics.gemspec
================================================
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "poetics/version"

Gem::Specification.new do |s|
  s.name        = "poetics"
  s.version     = Poetics::VERSION
  s.platform    = Gem::Platform::RUBY
  s.authors     = ["Brian Ford"]
  s.email       = ["brixen@gmail.com"]
  s.homepage    = "https://github.com/brixen/poetics"
  s.summary     = %q{A native implementation of CoffeeScript on the Rubinius VM}
  s.description =<<-EOD
Poetics implements CoffeeScript (http://jashkenas.github.com/coffee-script/)
directly on the Rubinius VM (http://rubini.us). It includes a REPL for
exploratory programming, as well as executing CoffeeScript scripts directly.
  EOD

  s.files         = `git ls-files`.split("\n")
  s.test_files    = Dir["spec/**/*.rb"]
  s.executables   = ["poetics"]
  s.require_paths = ["lib"]
end


================================================
FILE: spec/custom/matchers/parse_as.rb
================================================
class ParseAsMatcher
  def initialize(expected)
    @expected = expected
  end

  def matches?(actual)
    @actual = Poetics::Parser.parse_to_sexp actual
    @actual == @expected
  end

  def failure_message
    ["Expected:\n#{@actual.inspect}\n",
     "to equal:\n#{@expected.inspect}"]
  end
end

class Object
  def parse_as(sexp)
    ParseAsMatcher.new sexp
  end
end


================================================
FILE: spec/custom/runner/relates.rb
================================================
# NOTE: Copied from Rubinius
#
# SpecDataRelation enables concise specs that involve several different forms
# of the same data. This is specifically useful for the parser and compiler
# specs where the output of each stage is essentially related to the input
# Ruby source. Together with the #relates spec method, it enables specs like:
#
#   describe "An If node" do
#     relates "a if b" do
#       parse do
#         # return the expected sexp
#       end
#
#       compile do |g|
#         # return the expected bytecode
#       end
#
#       jit do |as|
#         # return the expected asm/machine code
#       end
#     end
#
#     relates "if a; b; end" do
#       # ...
#     end
#   end

class SpecDataRelation
  # Provides a simple configurability so that any one or more of the possible
  # processes can be run. See the custom options in custom/utils/options.rb.
  def self.enable(process)
    @processors ||= []
    @processors << process
  end

  # Returns true if no process is specifically set or if +process+ is in the
  # list of enabled processes. In other words, all processes are enabled by
  # default, or any combination of them may be enabled.
  def self.enabled?(process)
    @processors.nil? or @processors.include?(process)
  end

  def initialize(ruby)
    @ruby = ruby
  end

  # Formats the Ruby source code for reabable output in the -fs formatter
  # option. If the source contains no newline characters, wraps the source in
  # single quotes to set if off from the rest of the description string. If
  # the source does contain newline characters, sets the indent level to four
  # characters.
  def format(ruby)
    if /\n/ =~ ruby
      lines = ruby.rstrip.to_a
      if /( *)/ =~ lines.first
        if $1.size > 4
          dedent = $1.size - 4
          ruby = lines.map { |l| l[dedent..-1] }.join
        else
          indent = " " * (4 - $1.size)
          ruby = lines.map { |l| "#{indent}#{l}" }.join
        end
      end
      "\n#{ruby}"
    else
      "'#{ruby}'"
    end
  end

  # Creates spec example blocks if the compile process is enabled.
  def compile(*plugins, &block)
    return unless self.class.enabled? :compiler

    ruby = @ruby
    it "is compiled from #{format ruby}" do
      generator = Rubinius::TestGenerator.new
      generator.instance_eval(&block)

      ruby.should compile_as(generator, *plugins)
    end
  end

  def parse(&block)
    return unless self.class.enabled? :parser

    ruby = @ruby
    it "is parsed from #{format ruby}" do
      ruby.should parse_as(block.call)
    end
  end
end

class Object
  def relates(str, &block)
    SpecDataRelation.new(str).instance_eval(&block)
  end
end


================================================
FILE: spec/custom/utils/options.rb
================================================
# Custom MSpec options
#
class MSpecOptions
  def compiler
    # The require is inside the method because this file has to be able to be
    # loaded in MRI and there are parts of the custom ensemble that are
    # Rubinius specific (primarily iseq, which could potentially be fixed by
    # better structuring the compiler).
    require 'spec/custom/runner/relates'

    on("--compiler", "Run only the compile part of the compiler specs") do
      SpecDataRelation.enable :compiler
    end
  end

  def parser
    on("--parser", "Run only the parse part of the compiler specs") do
      SpecDataRelation.enable :parser
    end
  end
end


================================================
FILE: spec/custom/utils/script.rb
================================================
# Custom options for mspec-run
#
class MSpecRun
  def custom_options(options)
    options.compiler
    options.parser
  end
end

# Custom options for mspec-ci
#
class MSpecCI
  def custom_options(options)
    options.compiler
    options.parser
  end
end

# Custom options for mspec-tag
#
class MSpecTag
  def custom_options(options)
    options.compiler
    options.parser
  end
end


================================================
FILE: spec/custom.rb
================================================
require 'spec/custom/runner/relates'
require 'spec/custom/matchers/parse_as'
require 'spec/custom/utils/options'
require 'spec/custom/utils/script'


================================================
FILE: spec/default.mspec
================================================
# vim: filetype=ruby
require 'spec/custom'

class MSpecScript
  set :target, 'rbx'
end


================================================
FILE: spec/spec_helper.rb
================================================
$: << File.expand_path('../../lib', __FILE__)

require 'poetics'


================================================
FILE: spec/syntax/literal_spec.rb
================================================
require 'spec/spec_helper'

describe "The Number node" do
  relates "42" do
    parse { [:number, 42.0, 1, 1] }
  end

  relates " 42" do
    parse { [:number, 42.0, 1, 2] }
  end

  relates "42 " do
    parse { [:number, 42.0, 1, 1] }
  end

  relates "1.23" do
    parse { [:number, 1.23, 1, 1] }
  end

  relates "0x2a" do
    parse { [:number, 42.0, 1, 1] }
  end
end

describe "The True node" do
  relates "true" do
    parse { [:true, 1, 1] }
  end
end

describe "The False node" do
  relates "false" do
    parse { [:false, 1, 1] }
  end
end

describe "The Null node" do
  relates "null" do
    parse { [:null, 1, 1] }
  end
end

describe "The Undefined node" do
  relates "undefined" do
    parse { [:undefined, 1, 1] }
  end
end

describe "The String node" do
  relates '"hello, world"' do
    parse { [:string, "hello, world", 1, 1] }
  end

  relates <<-ruby do
      "hello"
    ruby

    parse { [:string, "hello", 1, 7] }
  end
end
Download .txt
gitextract_l4a1w08_/

├── .gitignore
├── Gemfile
├── LICENSE
├── README
├── Rakefile
├── bin/
│   └── poetics
├── lib/
│   ├── poetics/
│   │   ├── library/
│   │   │   └── code_loader.rb
│   │   ├── library.rb
│   │   ├── parser/
│   │   │   ├── parser.rb
│   │   │   └── poetics.kpeg
│   │   ├── parser.rb
│   │   ├── syntax/
│   │   │   ├── ast.rb
│   │   │   ├── literal.rb
│   │   │   └── node.rb
│   │   ├── syntax.rb
│   │   └── version.rb
│   └── poetics.rb
├── poetics.gemspec
└── spec/
    ├── custom/
    │   ├── matchers/
    │   │   └── parse_as.rb
    │   ├── runner/
    │   │   └── relates.rb
    │   └── utils/
    │       ├── options.rb
    │       └── script.rb
    ├── custom.rb
    ├── default.mspec
    ├── spec_helper.rb
    └── syntax/
        └── literal_spec.rb
Download .txt
SYMBOL INDEX (120 symbols across 11 files)

FILE: lib/poetics/library/code_loader.rb
  type Poetics (line 1) | module Poetics
    class CodeLoader (line 2) | class CodeLoader
      method evaluate (line 3) | def self.evaluate(string)
      method execute_file (line 8) | def self.execute_file(name)

FILE: lib/poetics/parser.rb
  class Poetics::Parser (line 3) | class Poetics::Parser
    method parse_to_sexp (line 6) | def self.parse_to_sexp(string)
    method position (line 17) | def position(line, column)

FILE: lib/poetics/parser/parser.rb
  class Poetics::Parser (line 1) | class Poetics::Parser
    method setup_parser (line 3) | def setup_parser(str, debug=false)
    method initialize (line 18) | def initialize(str, debug=false)
    method current_column (line 27) | def current_column(target=pos)
    method current_line (line 35) | def current_line(target=pos)
    method lines (line 48) | def lines
    method get_text (line 56) | def get_text(start)
    method show_pos (line 60) | def show_pos
    method failure_info (line 69) | def failure_info
    method failure_caret (line 81) | def failure_caret
    method failure_character (line 89) | def failure_character
    method failure_oneline (line 95) | def failure_oneline
    class ParseError (line 109) | class ParseError < RuntimeError
    method raise_error (line 112) | def raise_error
    method show_error (line 116) | def show_error(io=STDOUT)
    method set_failed_rule (line 137) | def set_failed_rule(name)
    method match_string (line 146) | def match_string(str)
    method scan (line 156) | def scan(reg)
    method get_byte (line 167) | def get_byte
    method get_byte (line 177) | def get_byte
    method parse (line 188) | def parse(rule=nil)
    class LeftRecursive (line 198) | class LeftRecursive
      method initialize (line 199) | def initialize(detected=false)
    class MemoEntry (line 206) | class MemoEntry
      method initialize (line 207) | def initialize(ans, pos)
      method inc! (line 216) | def inc!
      method move! (line 220) | def move!(ans, pos, result)
    method external_invoke (line 227) | def external_invoke(other, rule, *args)
    method apply_with_args (line 248) | def apply_with_args(rule, *args)
    method apply (line 285) | def apply(rule)
    method grow_lr (line 321) | def grow_lr(rule, args, start_pos, m)
    class RuleInfo (line 343) | class RuleInfo
      method initialize (line 344) | def initialize(name, rendered)
    method rule_info (line 352) | def self.rule_info(name, rendered)
    method setup_foreign_grammar (line 357) | def setup_foreign_grammar; end
    method _root (line 360) | def _root
    method _end (line 396) | def _end
    method __hyphen_ (line 406) | def __hyphen_
    method _value (line 431) | def _value
    method _boolean (line 452) | def _boolean
    method _true (line 490) | def _true
    method _false (line 512) | def _false
    method _null (line 534) | def _null
    method _undefined (line 556) | def _undefined
    method _number (line 578) | def _number
    method _hexdigits (line 613) | def _hexdigits
    method _hex (line 620) | def _hex
    method _digits (line 661) | def _digits
    method _int (line 697) | def _int
    method _real (line 723) | def _real
    method _string (line 812) | def _string
    method _line (line 853) | def _line
    method _column (line 861) | def _column
    method _position (line 869) | def _position

FILE: lib/poetics/syntax/ast.rb
  type Poetics (line 1) | module Poetics
    type Syntax (line 2) | module Syntax
      function number (line 3) | def number(value)
      function hexadecimal (line 7) | def hexadecimal(value)
      function true_value (line 11) | def true_value
      function false_value (line 15) | def false_value
      function null_value (line 19) | def null_value
      function undefined_value (line 23) | def undefined_value
      function string_value (line 27) | def string_value(value)

FILE: lib/poetics/syntax/literal.rb
  type Poetics (line 1) | module Poetics
    type Syntax (line 2) | module Syntax
      class Value (line 3) | class Value < Node
        method to_sexp (line 4) | def to_sexp
      class Number (line 9) | class Number < Value
        method initialize (line 12) | def initialize(line, column, value)
        method sexp_name (line 17) | def sexp_name
      class Boolean (line 22) | class Boolean < Node
        method to_sexp (line 23) | def to_sexp
      class True (line 28) | class True < Boolean
        method sexp_name (line 29) | def sexp_name
      class False (line 34) | class False < Boolean
        method sexp_name (line 35) | def sexp_name
      class Null (line 40) | class Null < Boolean
        method sexp_name (line 41) | def sexp_name
      class Undefined (line 46) | class Undefined < Boolean
        method sexp_name (line 47) | def sexp_name
      class String (line 52) | class String < Value
        method initialize (line 55) | def initialize(line, column, text)
        method sexp_name (line 60) | def sexp_name

FILE: lib/poetics/syntax/node.rb
  type Poetics (line 1) | module Poetics
    type Syntax (line 2) | module Syntax
      class Node (line 3) | class Node
        method initialize (line 6) | def initialize(line, column, *)
        method to_sexp (line 11) | def to_sexp

FILE: lib/poetics/version.rb
  type Poetics (line 1) | module Poetics

FILE: spec/custom/matchers/parse_as.rb
  class ParseAsMatcher (line 1) | class ParseAsMatcher
    method initialize (line 2) | def initialize(expected)
    method matches? (line 6) | def matches?(actual)
    method failure_message (line 11) | def failure_message
  class Object (line 17) | class Object
    method parse_as (line 18) | def parse_as(sexp)

FILE: spec/custom/runner/relates.rb
  class SpecDataRelation (line 28) | class SpecDataRelation
    method enable (line 31) | def self.enable(process)
    method enabled? (line 39) | def self.enabled?(process)
    method initialize (line 43) | def initialize(ruby)
    method format (line 52) | def format(ruby)
    method compile (line 71) | def compile(*plugins, &block)
    method parse (line 83) | def parse(&block)
  class Object (line 93) | class Object
    method relates (line 94) | def relates(str, &block)

FILE: spec/custom/utils/options.rb
  class MSpecOptions (line 3) | class MSpecOptions
    method compiler (line 4) | def compiler
    method parser (line 16) | def parser

FILE: spec/custom/utils/script.rb
  class MSpecRun (line 3) | class MSpecRun
    method custom_options (line 4) | def custom_options(options)
  class MSpecCI (line 12) | class MSpecCI
    method custom_options (line 13) | def custom_options(options)
  class MSpecTag (line 21) | class MSpecTag
    method custom_options (line 22) | def custom_options(options)
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (39K chars).
[
  {
    "path": ".gitignore",
    "chars": 39,
    "preview": "*.rbc\n*.gem\n.bundle\nGemfile.lock\npkg/*\n"
  },
  {
    "path": "Gemfile",
    "chars": 115,
    "preview": "source \"http://rubygems.org\"\n\ngemspec\n\ngem \"rake\",   \">= 0.8.7\"\ngem \"kpeg\",   \"~> 0.8.2\"\ngem \"mspec\",  \"~> 1.5.17\"\n"
  },
  {
    "path": "LICENSE",
    "chars": 1076,
    "preview": "Copyright (c) 2011 Brian Ford. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person\nobtaini"
  },
  {
    "path": "README",
    "chars": 2225,
    "preview": "1. What is Poetics?\n\nA native implementation of CoffeeScript [1] that runs on the Rubinius VM [2].\n\n  Q. Whence comes th"
  },
  {
    "path": "Rakefile",
    "chars": 450,
    "preview": "require 'bundler'\nBundler::GemHelper.install_tasks\n\ntask :default => :spec\n\nbase = File.expand_path '../lib/poetics/pars"
  },
  {
    "path": "bin/poetics",
    "chars": 2444,
    "preview": "#!/usr/bin/env rbx\n#\n# vim: filetype=ruby\n\n$:.unshift File.expand_path('../../lib', __FILE__)\n\nrequire 'readline'\nrequir"
  },
  {
    "path": "lib/poetics/library/code_loader.rb",
    "chars": 273,
    "preview": "module Poetics\n  class CodeLoader\n    def self.evaluate(string)\n      # We're just parsing for now\n      Poetics::Parser"
  },
  {
    "path": "lib/poetics/library.rb",
    "chars": 38,
    "preview": "require 'poetics/library/code_loader'\n"
  },
  {
    "path": "lib/poetics/parser/parser.rb",
    "chars": 19573,
    "preview": "class Poetics::Parser\n# STANDALONE START\n    def setup_parser(str, debug=false)\n      @string = str\n      @pos = 0\n     "
  },
  {
    "path": "lib/poetics/parser/poetics.kpeg",
    "chars": 902,
    "preview": "%% name = Poetics::Parser\n\nroot      = - value? - end\n\nend       = !.\n-         = (\" \" | \"\\t\" | \"\\n\")*\n\nvalue     = stri"
  },
  {
    "path": "lib/poetics/parser.rb",
    "chars": 337,
    "preview": "require 'poetics/parser/parser'\n\nclass Poetics::Parser\n  include Poetics::Syntax\n\n  def self.parse_to_sexp(string)\n    p"
  },
  {
    "path": "lib/poetics/syntax/ast.rb",
    "chars": 500,
    "preview": "module Poetics\n  module Syntax\n    def number(value)\n      Number.new line, column, value\n    end\n\n    def hexadecimal(v"
  },
  {
    "path": "lib/poetics/syntax/literal.rb",
    "chars": 960,
    "preview": "module Poetics\n  module Syntax\n    class Value < Node\n      def to_sexp\n        [sexp_name, value, line, column]\n      e"
  },
  {
    "path": "lib/poetics/syntax/node.rb",
    "chars": 223,
    "preview": "module Poetics\n  module Syntax\n    class Node\n      attr_accessor :line, :column\n\n      def initialize(line, column, *)\n"
  },
  {
    "path": "lib/poetics/syntax.rb",
    "chars": 92,
    "preview": "require 'poetics/syntax/node'\nrequire 'poetics/syntax/literal'\nrequire 'poetics/syntax/ast'\n"
  },
  {
    "path": "lib/poetics/version.rb",
    "chars": 134,
    "preview": "module Poetics\n  VERSION = \"0.0.1\"\n  RELEASE_DATE = \"yyyy-mm-dd\"\n  COMMAND_VERSION = \"poetics #{VERSION} (1.1.0 #{RELEAS"
  },
  {
    "path": "lib/poetics.rb",
    "chars": 102,
    "preview": "require 'poetics/version'\nrequire 'poetics/syntax'\nrequire 'poetics/parser'\nrequire 'poetics/library'\n"
  },
  {
    "path": "poetics.gemspec",
    "chars": 843,
    "preview": "# -*- encoding: utf-8 -*-\n$:.push File.expand_path(\"../lib\", __FILE__)\nrequire \"poetics/version\"\n\nGem::Specification.new"
  },
  {
    "path": "spec/custom/matchers/parse_as.rb",
    "chars": 371,
    "preview": "class ParseAsMatcher\n  def initialize(expected)\n    @expected = expected\n  end\n\n  def matches?(actual)\n    @actual = Poe"
  },
  {
    "path": "spec/custom/runner/relates.rb",
    "chars": 2673,
    "preview": "# NOTE: Copied from Rubinius\n#\n# SpecDataRelation enables concise specs that involve several different forms\n# of the sa"
  },
  {
    "path": "spec/custom/utils/options.rb",
    "chars": 638,
    "preview": "# Custom MSpec options\n#\nclass MSpecOptions\n  def compiler\n    # The require is inside the method because this file has "
  },
  {
    "path": "spec/custom/utils/script.rb",
    "chars": 384,
    "preview": "# Custom options for mspec-run\n#\nclass MSpecRun\n  def custom_options(options)\n    options.compiler\n    options.parser\n  "
  },
  {
    "path": "spec/custom.rb",
    "chars": 148,
    "preview": "require 'spec/custom/runner/relates'\nrequire 'spec/custom/matchers/parse_as'\nrequire 'spec/custom/utils/options'\nrequire"
  },
  {
    "path": "spec/default.mspec",
    "chars": 87,
    "preview": "# vim: filetype=ruby\nrequire 'spec/custom'\n\nclass MSpecScript\n  set :target, 'rbx'\nend\n"
  },
  {
    "path": "spec/spec_helper.rb",
    "chars": 65,
    "preview": "$: << File.expand_path('../../lib', __FILE__)\n\nrequire 'poetics'\n"
  },
  {
    "path": "spec/syntax/literal_spec.rb",
    "chars": 946,
    "preview": "require 'spec/spec_helper'\n\ndescribe \"The Number node\" do\n  relates \"42\" do\n    parse { [:number, 42.0, 1, 1] }\n  end\n\n "
  }
]

About this extraction

This page contains the full source code of the brixen/poetics GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (34.8 KB), approximately 10.7k tokens, and a symbol index with 120 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!