%%{

machine scanner;

action _number { @mark_num = p }
action number { @num_stack.push atos(data[@mark_num..p-1]) }

action constant { @tokens << Tokens::Constant.new(@num_stack.pop) }
action series {
  drop = @drop_current
  @drop_current = nil
  sides = @num_stack.pop
  count = @num_stack.pop
  @tokens << Tokens::Series.new(count, sides, drop)
}
action arithmetic { @tokens << Tokens::Arithmetic.new(data[p-1].chr) }

action drop { @drop_current = data[p-1].chr }

Number = digit+ >_number %number;

Constant = Number %constant;

Drop = ('^' | 'v') %drop;
Series = Number 'd' Number Drop? %series;

Arithmetic = ('+' | '-' | '*' | '/') %arithmetic;

UnaryExpression = Series | Constant;
BinaryExpression = UnaryExpression (space* Arithmetic space* UnaryExpression)+;
Expression = UnaryExpression | BinaryExpression;

main := Expression;

}%%

module Crapshoot

module Parser
  class Scan
    def initialize
      @tokens = []
      @num_stack = []
    end

    def parse(line)
      data = line.codepoints.to_a
      stack = []
      p = 0
      ts = 0
      te = 0
      act = 0
      eof = data.length
      %% write data;
      %% write init;
      %% write exec;
      return @tokens
    end

    def atos(a)
      a.map(&:chr).join
    end
  end
end

end