Skip to content

Commit 6220067

Browse files
committed
♻️ Add some methods from forthcoming parser update
Add helpers to simplify parser code, especially comparison with and translation to/from the RFC ABNF. Additionally, move `atom` to the top, because it and its accompanying methods will be referenced by `alias` later.
1 parent 4d58cec commit 6220067

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

lib/net/imap/response_parser.rb

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,45 @@ def parse(str)
9999

100100
Token = Struct.new(:symbol, :value)
101101

102+
# atom = 1*ATOM-CHAR
103+
#
104+
# TODO: match atom entirely by regexp (in the "lexer")
105+
def atom; -combine_adjacent(*ATOM_TOKENS) end
106+
107+
# the #accept version of #atom
108+
def atom?; -combine_adjacent(*ATOM_TOKENS) if lookahead?(*ATOM_TOKENS) end
109+
110+
# Returns <tt>atom.upcase</tt>
111+
def case_insensitive__atom; -combine_adjacent(*ATOM_TOKENS).upcase end
112+
113+
# Returns <tt>atom?&.upcase</tt>
114+
def case_insensitive__atom?
115+
-combine_adjacent(*ATOM_TOKENS).upcase if lookahead?(*ATOM_TOKENS)
116+
end
117+
118+
# In addition to explicitly uses of +tagged-ext-label+, use this to match
119+
# keywords when the grammar has not provided any extension syntax.
120+
#
121+
# Do *not* use this for labels where the grammar specifies extensions
122+
# can be +atom+, even if all currently defined labels would match. For
123+
# example response codes in +resp-text-code+.
124+
#
125+
# tagged-ext-label = tagged-label-fchar *tagged-label-char
126+
# ; Is a valid RFC 3501 "atom".
127+
# tagged-label-fchar = ALPHA / "-" / "_" / "."
128+
# tagged-label-char = tagged-label-fchar / DIGIT / ":"
129+
#
130+
# TODO: add to lexer and only match tagged-ext-label
131+
alias tagged_ext_label case_insensitive__atom
132+
alias tagged_ext_label? case_insensitive__atom?
133+
134+
# Use #label or #label_in to assert specific known labels
135+
# (+tagged-ext-label+ only, not +atom+).
136+
def label(word)
137+
(val = tagged_ext_label) == word and return val
138+
parse_error("unexpected atom %p, expected %p instead", val, word)
139+
end
140+
102141
def response
103142
token = lookahead
104143
case token.symbol
@@ -1333,10 +1372,6 @@ def case_insensitive_string
13331372
T_PLUS
13341373
]
13351374

1336-
def atom
1337-
-combine_adjacent(*ATOM_TOKENS)
1338-
end
1339-
13401375
# ASTRING-CHAR = ATOM-CHAR / resp-specials
13411376
# resp-specials = "]"
13421377
ASTRING_CHARS_TOKENS = [*ATOM_TOKENS, T_RBRA]
@@ -1408,12 +1443,18 @@ def nil_atom
14081443
# This advances @pos directly so it's safe before changing @lex_state.
14091444
def accept_space
14101445
if @token
1411-
shift_token if @token.symbol == T_SPACE
1446+
if @token.symbol == T_SPACE
1447+
shift_token
1448+
" "
1449+
end
14121450
elsif @str[@pos] == " "
14131451
@pos += 1
1452+
" "
14141453
end
14151454
end
14161455

1456+
alias SP? accept_space
1457+
14171458
# The RFC is very strict about this and usually we should be too.
14181459
# But skipping spaces is usually a safe workaround for buggy servers.
14191460
#

lib/net/imap/response_parser/parser_utils.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ def accept(*args)
4242
end
4343
end
4444

45+
# like accept, without consuming the token
46+
def lookahead?(*symbols)
47+
@token if symbols.include?((@token ||= next_token)&.symbol)
48+
end
49+
4550
def lookahead
4651
@token ||= next_token
4752
end

0 commit comments

Comments
 (0)