Class: DDQL::Parser
- Inherits:
-
Object
show all
- Defined in:
- lib/ddql/parser.rb
Defined Under Namespace
Classes: NoTokenException, ParseException, ResolvedToken
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(expression: nil, tokens: nil) ⇒ Parser
Returns a new instance of Parser.
50
51
52
53
54
55
56
57
58
59
|
# File 'lib/ddql/parser.rb', line 50
def initialize(expression: nil, tokens: nil)
@expression = expression
@depth = 0
if expression
@tokens = Lexer.lex(expression)
else
@tokens = tokens
end
raise "tokens cannot be determined" if @tokens.nil? || @tokens.empty?
end
|
Instance Attribute Details
#tokens ⇒ Object
Returns the value of attribute tokens.
3
4
5
|
# File 'lib/ddql/parser.rb', line 3
def tokens
@tokens
end
|
Class Method Details
.from_tokens(tokens) ⇒ Object
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
# File 'lib/ddql/parser.rb', line 26
def self.from_tokens(tokens)
opener = tokens.doubly_linked!.find { |node| node.value.type == TokenType::NESTED_OPENER }
if opener
closer = tokens.find_from_tail { |node| node.value.type == TokenType::NESTED_CLOSER }
new_tokens = DDQL::LinkedList.new
current = opener
while (current = current.next) && !(current === closer)
new_tokens << current.dup
end
new_tokens.tail.next = nil
new(tokens: tokens.replace!(
from: opener,
to: closer,
with: ResolvedToken.new(sub_query: from_tokens(new_tokens).parse)),
)
else
new(tokens: tokens)
end
end
|
.parse(expr) ⇒ Object
46
47
48
|
# File 'lib/ddql/parser.rb', line 46
def self.parse(expr)
from_tokens(Lexer.lex(expr)).record_expression(expr).parse
end
|
Instance Method Details
#consume(token_type) ⇒ Object
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'lib/ddql/parser.rb', line 61
def consume(token_type)
token = @tokens.poll
if token.nil? || token_type != token.type
message = "Expected token[#{token_type.name}], got #{token.nil? ? 'nil' : "[#{token.type.name}]"}\n"
if token
message += " #{@expression}\n"
message += " #{' ' * token.location}^"
end
raise ParseException, message
end
token
end
|
#parse(precedence: 0) ⇒ Object
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/ddql/parser.rb', line 74
def parse(precedence: 0)
@depth += 1
token = @tokens.poll
raise NoTokenException if token.nil?
expression = token.parse(self)
while precedence < next_precedence
token = @tokens.poll
expression = token.parse(self, expression: expression)
end
@depth -= 1
if @depth == 0 && !peek.nil?
raise ParseException, "Unable to fully parse expression; token[#{peek}], possible cause: invalid operator"
end
expression
end
|
#peek ⇒ Object
94
95
96
|
# File 'lib/ddql/parser.rb', line 94
def peek
@tokens.peek
end
|
#record_expression(expr) ⇒ Object
98
99
100
101
|
# File 'lib/ddql/parser.rb', line 98
def record_expression(expr)
@expression = expr
self
end
|
supports reading until the next token_type
, does not support nested reads of token_type
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/ddql/parser.rb', line 108
def until(token_type)
new_list = LinkedList.new.doubly_linked!
while token = @tokens.poll
if token.type?(token_type)
return new_list
else
new_list << token
end
end
raise "expected to consume tokens up to type[#{token_type.name}]"
end
|