Class: Dentaku::TokenScanner
- Inherits:
-
Object
- Object
- Dentaku::TokenScanner
- Defined in:
- lib/dentaku/token_scanner.rb
Class Method Summary collapse
- .available_scanners ⇒ Object
- .boolean ⇒ Object
- .case_statement ⇒ Object
- .combinator ⇒ Object
- .comparator ⇒ Object
-
.datetime ⇒ Object
NOTE: Convert to DateTime as Array(Time) returns the parts of the time for some reason.
- .double_quoted_string ⇒ Object
- .function ⇒ Object
- .grouping ⇒ Object
- .identifier ⇒ Object
- .negate ⇒ Object
- .null ⇒ Object
- .numeric ⇒ Object
- .operator ⇒ Object
- .register_default_scanners ⇒ Object
- .register_scanner(id, scanner) ⇒ Object
- .register_scanners(scanner_ids) ⇒ Object
- .scanners ⇒ Object
- .scanners=(scanner_ids) ⇒ Object
- .single_quoted_string ⇒ Object
- .whitespace ⇒ Object
Instance Method Summary collapse
-
#initialize(category, regexp, converter = nil, condition = nil) ⇒ TokenScanner
constructor
A new instance of TokenScanner.
- #scan(string, last_token = nil) ⇒ Object
Constructor Details
#initialize(category, regexp, converter = nil, condition = nil) ⇒ TokenScanner
Returns a new instance of TokenScanner.
7 8 9 10 11 12 |
# File 'lib/dentaku/token_scanner.rb', line 7 def initialize(category, regexp, converter=nil, condition=nil) @category = category @regexp = %r{\A(#{ regexp })}i @converter = converter @condition = condition || ->(*) { true } end |
Class Method Details
.available_scanners ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/dentaku/token_scanner.rb', line 28 def available_scanners [ :null, :whitespace, :datetime, # before numeric so it can pick up timestamps :numeric, :double_quoted_string, :single_quoted_string, :negate, :operator, :grouping, :case_statement, :comparator, :combinator, :boolean, :function, :identifier ] end |
.boolean ⇒ Object
131 132 133 |
# File 'lib/dentaku/token_scanner.rb', line 131 def boolean new(:logical, '(true|false)\b', lambda { |raw| raw.strip.downcase == 'true' }) end |
.case_statement ⇒ Object
116 117 118 119 |
# File 'lib/dentaku/token_scanner.rb', line 116 def case_statement names = { open: 'case', close: 'end', then: 'then', when: 'when', else: 'else' }.invert new(:case, '(case|end|then|when|else)\b', lambda { |raw| names[raw.downcase] }) end |
.combinator ⇒ Object
127 128 129 |
# File 'lib/dentaku/token_scanner.rb', line 127 def combinator new(:combinator, '(and|or)\b', lambda { |raw| raw.strip.downcase.to_sym }) end |
.comparator ⇒ Object
121 122 123 124 125 |
# File 'lib/dentaku/token_scanner.rb', line 121 def comparator names = { le: '<=', ge: '>=', ne: '!=', lt: '<', gt: '>', eq: '=' }.invert alternate = { ne: '<>', eq: '==' }.invert new(:comparator, '<=|>=|!=|<>|<|>|==|=', lambda { |raw| names[raw] || alternate[raw] }) end |
.datetime ⇒ Object
NOTE: Convert to DateTime as Array(Time) returns the parts of the time for some reason
79 80 81 |
# File 'lib/dentaku/token_scanner.rb', line 79 def datetime new(:datetime, /\d{2}\d{2}?-\d{1,2}-\d{1,2}( \d{1,2}:\d{1,2}:\d{1,2})? ?(Z|((\+|\-)\d{2}\:?\d{2}))?/, lambda { |raw| Time.parse(raw).to_datetime }) end |
.double_quoted_string ⇒ Object
87 88 89 |
# File 'lib/dentaku/token_scanner.rb', line 87 def double_quoted_string new(:string, '"[^"]*"', lambda { |raw| raw.gsub(/^"|"$/, '') }) end |
.function ⇒ Object
135 136 137 138 139 140 |
# File 'lib/dentaku/token_scanner.rb', line 135 def function new(:function, '\w+!?\s*\(', lambda do |raw| function_name = raw.gsub('(', '') [Token.new(:function, function_name.strip.downcase.to_sym, function_name), Token.new(:grouping, :open, '(')] end) end |
.grouping ⇒ Object
111 112 113 114 |
# File 'lib/dentaku/token_scanner.rb', line 111 def grouping names = { open: '(', close: ')', comma: ',' }.invert new(:grouping, '\(|\)|,', lambda { |raw| names[raw] }) end |
.identifier ⇒ Object
142 143 144 |
# File 'lib/dentaku/token_scanner.rb', line 142 def identifier new(:identifier, '[\w\.]+\b', lambda { |raw| raw.strip.downcase }) end |
.negate ⇒ Object
95 96 97 98 99 100 101 102 103 104 |
# File 'lib/dentaku/token_scanner.rb', line 95 def negate new(:operator, '-', lambda { |raw| :negate }, lambda { |last_token| last_token.nil? || last_token.is?(:operator) || last_token.is?(:comparator) || last_token.is?(:combinator) || last_token.value == :open || last_token.value == :comma }) end |
.null ⇒ Object
74 75 76 |
# File 'lib/dentaku/token_scanner.rb', line 74 def null new(:null, 'null\b') end |
.numeric ⇒ Object
83 84 85 |
# File 'lib/dentaku/token_scanner.rb', line 83 def numeric new(:numeric, '(\d+(\.\d+)?|\.\d+)\b', lambda { |raw| raw =~ /\./ ? BigDecimal.new(raw) : raw.to_i }) end |
.operator ⇒ Object
106 107 108 109 |
# File 'lib/dentaku/token_scanner.rb', line 106 def operator names = { pow: '^', add: '+', subtract: '-', multiply: '*', divide: '/', mod: '%', bitor: '|', bitand: '&' }.invert new(:operator, '\^|\+|-|\*|\/|%|\||&', lambda { |raw| names[raw] }) end |
.register_default_scanners ⇒ Object
48 49 50 |
# File 'lib/dentaku/token_scanner.rb', line 48 def register_default_scanners register_scanners(available_scanners) end |
.register_scanner(id, scanner) ⇒ Object
58 59 60 |
# File 'lib/dentaku/token_scanner.rb', line 58 def register_scanner(id, scanner) @scanners[id] = scanner end |
.register_scanners(scanner_ids) ⇒ Object
52 53 54 55 56 |
# File 'lib/dentaku/token_scanner.rb', line 52 def register_scanners(scanner_ids) @scanners = scanner_ids.each_with_object({}) do |id, scanners| scanners[id] = self.send(id) end end |
.scanners ⇒ Object
66 67 68 |
# File 'lib/dentaku/token_scanner.rb', line 66 def scanners @scanners.values end |
.scanners=(scanner_ids) ⇒ Object
62 63 64 |
# File 'lib/dentaku/token_scanner.rb', line 62 def scanners=(scanner_ids) @scanners.select! { |k,v| scanner_ids.include?(k) } end |
.single_quoted_string ⇒ Object
91 92 93 |
# File 'lib/dentaku/token_scanner.rb', line 91 def single_quoted_string new(:string, "'[^']*'", lambda { |raw| raw.gsub(/^'|'$/, '') }) end |
.whitespace ⇒ Object
70 71 72 |
# File 'lib/dentaku/token_scanner.rb', line 70 def whitespace new(:whitespace, '\s+') end |
Instance Method Details
#scan(string, last_token = nil) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/dentaku/token_scanner.rb', line 14 def scan(string, last_token=nil) if (m = @regexp.match(string)) && @condition.call(last_token) value = raw = m.to_s value = @converter.call(raw) if @converter return Array(value).map do |v| Token === v ? v : Token.new(@category, v, raw) end end false end |