Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1)

Side by Side Diff: Lib/idlelib/HyperParser.py

Issue 21686: IDLE - Test hyperparser
Patch Set: Created 5 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 """ 1 """
2 HyperParser 2 HyperParser
3 =========== 3 ===========
4 This module defines the HyperParser class, which provides advanced parsing 4 This module defines the HyperParser class, which provides advanced parsing
5 abilities for the ParenMatch and other extensions. 5 abilities for the ParenMatch and other extensions.
6 The HyperParser uses PyParser. PyParser is intended mostly to give information 6 The HyperParser uses PyParser. PyParser is intended mostly to give information
7 on the proper indentation of code. HyperParser gives some information on the 7 on the proper indentation of code. HyperParser gives some information on the
8 structure of code, used by extensions to help the user. 8 structure of code, used by extensions to help the user.
9 """ 9 """
10 10
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 57
58 # We want what the parser has, except for the last newline and space. 58 # We want what the parser has, except for the last newline and space.
59 self.rawtext = parser.str[:-2] 59 self.rawtext = parser.str[:-2]
60 # As far as I can see, parser.str preserves the statement we are in, 60 # As far as I can see, parser.str preserves the statement we are in,
61 # so that stopatindex can be used to synchronize the string with the 61 # so that stopatindex can be used to synchronize the string with the
62 # text box indices. 62 # text box indices.
63 self.stopatindex = stopatindex 63 self.stopatindex = stopatindex
64 self.bracketing = parser.get_last_stmt_bracketing() 64 self.bracketing = parser.get_last_stmt_bracketing()
65 # find which pairs of bracketing are openers. These always correspond 65 # find which pairs of bracketing are openers. These always correspond
66 # to a character of rawtext. 66 # to a character of rawtext.
67 self.isopener = [i>0 and self.bracketing[i][1] > self.bracketing[i-1][1] 67 self.isopener = [self.bracketing[i][1] > self.bracketing[i-1][1]
68 for i in range(len(self.bracketing))] 68 and i > 0 for i in range(len(self.bracketing))]
69 69
70 self.set_index(index) 70 self.set_index(index)
71 71
72 def set_index(self, index): 72 def set_index(self, index):
73 """Set the index to which the functions relate. Note that it must be 73 """Set the index to which the functions relate. Note that it must be
74 in the same statement. 74 in the same statement.
75 """ 75 """
76 indexinrawtext = \ 76 indexinrawtext = \
77 len(self.rawtext) - len(self.text.get(index, self.stopatindex)) 77 len(self.rawtext) - len(self.text.get(index, self.stopatindex))
78 if indexinrawtext < 0: 78 if indexinrawtext < 0:
79 raise ValueError("The index given is before the analyzed statement") 79 raise ValueError("The index given is before the analyzed "
80 "statement")
80 self.indexinrawtext = indexinrawtext 81 self.indexinrawtext = indexinrawtext
81 # find the rightmost bracket to which index belongs 82 # find the rightmost bracket to which index belongs
82 self.indexbracket = 0 83 self.indexbracket = 0
83 while self.indexbracket < len(self.bracketing)-1 and \ 84 while self.indexbracket < len(self.bracketing)-1 and \
84 self.bracketing[self.indexbracket+1][0] < self.indexinrawtext: 85 self.bracketing[self.indexbracket+1][0] < self.indexinrawtext:
85 self.indexbracket += 1 86 self.indexbracket += 1
86 if self.indexbracket < len(self.bracketing)-1 and \ 87 if self.indexbracket < len(self.bracketing)-1 and \
87 self.bracketing[self.indexbracket+1][0] == self.indexinrawtext and \ 88 self.bracketing[self.indexbracket+1][0] == self.indexinrawtext and \
88 not self.isopener[self.indexbracket+1]: 89 not self.isopener[self.indexbracket+1]:
89 self.indexbracket += 1 90 self.indexbracket += 1
90 91
91 def is_in_string(self): 92 def is_in_string(self):
92 """Is the index given to the HyperParser is in a string?""" 93 """Is the index given to the HyperParser is in a string?"""
93 # The bracket to which we belong should be an opener. 94 # The bracket to which we belong should be an opener.
94 # If it's an opener, it has to have a character. 95 # If it's an opener, it has to have a character.
95 return self.isopener[self.indexbracket] and \ 96 return self.isopener[self.indexbracket] and \
96 self.rawtext[self.bracketing[self.indexbracket][0]] in ('"', "'") 97 self.rawtext[self.bracketing[self.indexbracket][0]] in ('"', "'")
sahutd 2014/06/14 16:38:34 Is there some way to make the length of this line
taleinat 2014/06/14 17:45:21 Certainly. Two possible ways: 1) use parenthesis a
97 98
98 def is_in_code(self): 99 def is_in_code(self):
99 """Is the index given to the HyperParser is in a normal code?""" 100 """Is the index given to the HyperParser is in a normal code?"""
100 return not self.isopener[self.indexbracket] or \ 101 return not self.isopener[self.indexbracket] or \
101 self.rawtext[self.bracketing[self.indexbracket][0]] not in \ 102 self.rawtext[self.bracketing[self.indexbracket][0]] not in \
102 ('#', '"', "'") 103 ('#', '"', "'")
103 104
104 def get_surrounding_brackets(self, openers='([{', mustclose=False): 105 def get_surrounding_brackets(self, openers='([{', mustclose=False):
105 """If the index given to the HyperParser is surrounded by a bracket 106 """If the index given to the HyperParser is surrounded by a bracket
106 defined in openers (or at least has one before it), return the 107 defined in openers (or at least has one before it), return the
(...skipping 29 matching lines...) Expand all
136 afterindex = self.text.index("%s-%dc" % 137 afterindex = self.text.index("%s-%dc" %
137 (self.stopatindex, 138 (self.stopatindex,
138 len(self.rawtext)-(self.bracketing[after][0]-1))) 139 len(self.rawtext)-(self.bracketing[after][0]-1)))
139 140
140 return beforeindex, afterindex 141 return beforeindex, afterindex
141 142
142 # This string includes all chars that may be in a white space 143 # This string includes all chars that may be in a white space
143 _whitespace_chars = " \t\n\\" 144 _whitespace_chars = " \t\n\\"
144 # This string includes all chars that may be in an identifier 145 # This string includes all chars that may be in an identifier
145 _id_chars = string.ascii_letters + string.digits + "_" 146 _id_chars = string.ascii_letters + string.digits + "_"
146 # This string includes all chars that may be the first char of an identifier 147 # This string includes all chars that may be
148 # the first char of an identifier
147 _id_first_chars = string.ascii_letters + "_" 149 _id_first_chars = string.ascii_letters + "_"
148 150
149 # Given a string and pos, return the number of chars in the identifier 151 # Given a string and pos, return the number of chars in the identifier
150 # which ends at pos, or 0 if there is no such one. Saved words are not 152 # which ends at pos, or 0 if there is no such one. Saved words are not
151 # identifiers. 153 # identifiers.
152 def _eat_identifier(self, str, limit, pos): 154 def _eat_identifier(self, str, limit, pos):
153 i = pos 155 i = pos
154 while i > limit and str[i-1] in self._id_chars: 156 while i > limit and str[i-1] in self._id_chars:
155 i -= 1 157 i -= 1
156 if i < pos and (str[i] not in self._id_first_chars or \ 158 if i < pos and (str[i] not in self._id_first_chars or \
157 keyword.iskeyword(str[i:pos])): 159 keyword.iskeyword(str[i:pos])):
158 i = pos 160 i = pos
159 return pos - i 161 return pos - i
160 162
161 def get_expression(self): 163 def get_expression(self):
162 """Return a string with the Python expression which ends at the given 164 """Return a string with the Python expression which ends at the given
163 index, which is empty if there is no real one. 165 index, which is empty if there is no real one.
164 """ 166 """
165 if not self.is_in_code(): 167 if not self.is_in_code():
166 raise ValueError("get_expression should only be called if index "\ 168 raise ValueError("get_expression should only be called if index "
167 "is inside a code.") 169 "is inside a code.")
168 170
169 rawtext = self.rawtext 171 rawtext = self.rawtext
170 bracketing = self.bracketing 172 bracketing = self.bracketing
171 173
172 brck_index = self.indexbracket 174 brck_index = self.indexbracket
173 brck_limit = bracketing[brck_index][0] 175 brck_limit = bracketing[brck_index][0]
174 pos = self.indexinrawtext 176 pos = self.indexinrawtext
175 177
176 last_identifier_pos = pos 178 last_identifier_pos = pos
177 postdot_phase = True 179 postdot_phase = True
178 180
179 while 1: 181 while 1:
180 # Eat whitespaces, comments, and if postdot_phase is False - one dot 182 # Eat whitespaces, comments, and if postdot_phase is False - a dot
181 while 1: 183 while 1:
182 if pos>brck_limit and rawtext[pos-1] in self._whitespace_chars: 184 if pos>brck_limit and rawtext[pos-1] in self._whitespace_chars:
183 # Eat a whitespace 185 # Eat a whitespace
184 pos -= 1 186 pos -= 1
185 elif not postdot_phase and \ 187 elif not postdot_phase and \
186 pos > brck_limit and rawtext[pos-1] == '.': 188 pos > brck_limit and rawtext[pos-1] == '.':
187 # Eat a dot 189 # Eat a dot
188 pos -= 1 190 pos -= 1
189 postdot_phase = True 191 postdot_phase = True
190 # The next line will fail if we are *inside* a comment, but we 192 # The next line will fail if we are *inside* a comment, but we
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 while pos > 0 and rawtext[pos - 1] in "rRbBuU": 239 while pos > 0 and rawtext[pos - 1] in "rRbBuU":
238 pos -= 1 240 pos -= 1
239 last_identifier_pos = pos 241 last_identifier_pos = pos
240 break 242 break
241 243
242 else: 244 else:
243 # We've found an operator or something. 245 # We've found an operator or something.
244 break 246 break
245 247
246 return rawtext[last_identifier_pos:self.indexinrawtext] 248 return rawtext[last_identifier_pos:self.indexinrawtext]
249
250 if __name__ == '__main__':
251 import unittest
252 unittest.main('idlelib.idle_test.test_hyperparser', verbosity=2)
OLDNEW
« no previous file with comments | « no previous file | Lib/idlelib/idle_test/test_hyperparser.py » ('j') | Lib/idlelib/idle_test/test_hyperparser.py » ('J')

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+