Class: Praat::Lexer

Inherits:
Object
  • Object
show all
Defined in:
lib/praat_lexer.rb,
lib/praat_lexer.rex.rb

Defined Under Namespace

Classes: ScanError

Constant Summary collapse

INTEGER =
/\d+/
FLOAT =
/\d+\.\d+(?:e-\d\d)?/
NUMBER =
/#{FLOAT}|#{INTEGER}/
LETTER =
/[\w'\u0250-\u02AF\u00E6\u00F0\u03B8\u014B]/
WORD =
/#{LETTER}+(?: #{LETTER}*)?/

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#filenameObject

Returns the value of attribute filename.



21
22
23
# File 'lib/praat_lexer.rex.rb', line 21

def filename
  @filename
end

#ssObject Also known as: match

Returns the value of attribute ss.



22
23
24
# File 'lib/praat_lexer.rex.rb', line 22

def ss
  @ss
end

#stateObject

Returns the value of attribute state.



23
24
25
# File 'lib/praat_lexer.rex.rb', line 23

def state
  @state
end

Instance Method Details

#actionObject



33
34
35
# File 'lib/praat_lexer.rex.rb', line 33

def action
  yield
end

#do_parseObject



6
7
8
9
10
11
12
13
# File 'lib/praat_lexer.rb', line 6

def do_parse 
  output = [] 
  while token = next_token do
    type, *vals = token
    output << send("lex_#{type}", *vals)
  end
  output
end

#lex_collection(collection) ⇒ Object



27
28
29
# File 'lib/praat_lexer.rb', line 27

def lex_collection collection
  [:collection, collection.chomp]
end

#lex_float_property(property, value) ⇒ Object



15
16
17
# File 'lib/praat_lexer.rb', line 15

def lex_float_property property, value
  [:property, property.chomp, value.to_f]
end

#lex_indent(spaces) ⇒ Object



35
36
37
38
# File 'lib/praat_lexer.rb', line 35

def lex_indent spaces
  indents = spaces.length / 4
  [:indent, indents]
end

#lex_integer_property(property, value) ⇒ Object



19
20
21
# File 'lib/praat_lexer.rb', line 19

def lex_integer_property property, value
  [:property, property.chomp, value.to_i]
end

#lex_object(object, index) ⇒ Object



31
32
33
# File 'lib/praat_lexer.rb', line 31

def lex_object object, index
  [:object, object.chomp, index.to_i]
end

#lex_string_property(property, value) ⇒ Object



23
24
25
# File 'lib/praat_lexer.rb', line 23

def lex_string_property property, value
  [:property, property.chomp, value.chomp]
end

#matchesObject



27
28
29
30
31
# File 'lib/praat_lexer.rex.rb', line 27

def matches
  m = (1..9).map { |i| ss[i] }
  m.pop until m[-1] or m.empty?
  m
end

#next_tokenObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/praat_lexer.rex.rb', line 56

def next_token

  token = nil

  until ss.eos? or token do
    token =
      case state
      when nil then
        case
        when text = ss.scan(/(#{WORD}) = (#{FLOAT})/) then
          action { [:float_property, *matches] }
        when text = ss.scan(/(#{WORD}) = (#{INTEGER})/) then
          action { [:integer_property, *matches] }
        when text = ss.scan(/(#{WORD}) = "(#{WORD}|)"/) then
          action { [:string_property, *matches] }
        when text = ss.scan(/(#{WORD}) \[\]:/) then
          action { [:collection, *matches] }
        when text = ss.scan(/(intervals): size = #{INTEGER}.*/) then
          action { [:collection, *matches] }
        when text = ss.scan(/(#{WORD}) \[(#{INTEGER})\]:/) then
          action { [:object, *matches] }
        when text = ss.scan(/( {4}+)/) then
          action { [:indent, *matches] }
        when text = ss.scan(/\s*\n/) then
          # do nothing
        when text = ss.scan(/tiers\?.*/) then
          # do nothing
        else
          text = ss.string[ss.pos .. -1]
          raise ScanError, "can not match (#{state.inspect}): '#{text}'"
        end
      else
        raise ScanError, "undefined state: '#{state}'"
      end # token = case state

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

  raise "bad lexical result: #{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) ⇒ Object



42
43
44
45
46
47
# File 'lib/praat_lexer.rex.rb', line 42

def parse str
  self.ss     = scanner_class.new str
  self.state  ||= nil

  do_parse
end

#parse_file(path) ⇒ Object



49
50
51
52
53
54
# File 'lib/praat_lexer.rex.rb', line 49

def parse_file path
  self.filename = path
  open path do |f|
    parse f.read
  end
end

#scanner_classObject



38
39
40
# File 'lib/praat_lexer.rex.rb', line 38

def scanner_class
  StringScanner
end