class Predicator::Lexer

Constants

AGO
AND
BANG
BEGINSWITH
BETWEEN
BLANK
COMMA
DATE
DOT
DURATION
ENDSWITH
EQ
FALSE
FROMNOW
GT
IDENTIFIER
IN
INTEGER
LBRACKET
LPAREN
LT
NOT
OR
PRESENT
RBRACKET
RPAREN
SPACE
STARTSWITH
STRING
TRUE

Attributes

filename[RW]
lineno[RW]
match[RW]
old_pos[RW]
ss[RW]
state[RW]

Public Instance Methods

action() { || ... } click to toggle source
# File lib/predicator/lexer.rex.rb, line 58
def action
  yield
end
column() click to toggle source
# File lib/predicator/lexer.rex.rb, line 64
def column
  idx = ss.string.rindex("\n", old_pos) || -1
  old_pos - idx - 1
end
do_parse() click to toggle source
# File lib/predicator/lexer.rex.rb, line 186
def do_parse; end
location() click to toggle source
# File lib/predicator/lexer.rex.rb, line 88
def location
  [
    (filename || "<input>"),
    lineno,
    column,
  ].compact.join(":")
end
matches() click to toggle source
# File lib/predicator/lexer.rex.rb, line 52
def matches
  m = (1..9).map { |i| ss[i] }
  m.pop until m[-1] or m.empty?
  m
end
next_token() click to toggle source
# File lib/predicator/lexer.rex.rb, line 96
def next_token

  token = nil

  until ss.eos? or token do
    self.lineno += 1 if ss.peek(1) == "\n"
    self.old_pos = ss.pos
    token =
      case state
      when nil then
        case
        when ss.skip(/#{SPACE}/) then
          # do nothing
        when text = ss.scan(/#{LPAREN}/) then
          action { [:LPAREN, text] }
        when text = ss.scan(/#{RPAREN}/) then
          action { [:RPAREN, text] }
        when text = ss.scan(/#{LBRACKET}/) then
          action { [:LBRACKET, text] }
        when text = ss.scan(/#{RBRACKET}/) then
          action { [:RBRACKET, text] }
        when text = ss.scan(/#{TRUE}/) then
          action { [:TRUE, text] }
        when text = ss.scan(/#{FALSE}/) then
          action { [:FALSE, text] }
        when text = ss.scan(/#{BETWEEN}/) then
          action { [:BETWEEN, text] }
        when text = ss.scan(/#{IN}/) then
          action { [:IN, text] }
        when text = ss.scan(/#{BANG}/) then
          action { [:BANG, text] }
        when text = ss.scan(/#{NOT}/) then
          action { [:NOT, text] }
        when text = ss.scan(/#{DOT}/) then
          action { [:DOT, text] }
        when text = ss.scan(/#{COMMA}/) then
          action { [:COMMA, text] }
        when text = ss.scan(/#{AND}/) then
          action { [:AND, text] }
        when text = ss.scan(/#{OR}/) then
          action { [:OR, text] }
        when text = ss.scan(/#{EQ}/) then
          action { [:EQ, text] }
        when text = ss.scan(/#{GT}/) then
          action { [:GT, text] }
        when text = ss.scan(/#{LT}/) then
          action { [:LT, text] }
        when text = ss.scan(/#{AGO}/) then
          action { [:AGO, text] }
        when text = ss.scan(/#{FROMNOW}/) then
          action { [:FROMNOW, text] }
        when text = ss.scan(/#{ENDSWITH}/) then
          action { [:ENDSWITH, text] }
        when text = ss.scan(/#{STARTSWITH}/) then
          action { [:STARTSWITH, text] }
        when text = ss.scan(/#{BEGINSWITH}/) then
          action { [:STARTSWITH, text] }
        when text = ss.scan(/#{BLANK}/) then
          action { [:BLANK, text] }
        when text = ss.scan(/#{PRESENT}/) then
          action { [:PRESENT, text] }
        when text = ss.scan(/#{DATE}/) then
          action { [:DATE, text] }
        when text = ss.scan(/#{DURATION}/) then
          action { [:DURATION, text] }
        when text = ss.scan(/#{INTEGER}/) then
          action { [:INTEGER, text] }
        when text = ss.scan(/#{STRING}/) then
          action { [:STRING, text[1...-1]] }
        when text = ss.scan(/#{IDENTIFIER}/) then
          action { [:IDENTIFIER, text] }
        else
          text = ss.string[ss.pos .. -1]
          raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
        end
      else
        raise ScanError, "undefined state at #{location}: '#{state}'"
      end # token = case state

    next unless token # allow functions to trigger redo w/ nil
  end # while

  raise LexerError, "bad lexical result at #{location}: #{token.inspect}" unless
    token.nil? || (Array === token && token.size >= 2)

  # auto-switch state
  self.state = token.last if token && token.first == :state

  token
end
parse(str) click to toggle source
# File lib/predicator/lexer.rex.rb, line 73
def parse str
  self.ss     = scanner_class.new str
  self.lineno = 1
  self.state  ||= nil

  do_parse
end
parse_file(path) click to toggle source
# File lib/predicator/lexer.rex.rb, line 81
def parse_file path
  self.filename = path
  open path do |f|
    parse f.read
  end
end
scanner_class() click to toggle source
# File lib/predicator/lexer.rex.rb, line 69
def scanner_class
  StringScanner
end