Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Side by Side Diff: ppapi/generators/idl_lexer.py

Issue 7272043: Update Lexer/Parser to support '#inline' and 'label' (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | ppapi/generators/idl_parser.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """ Lexer for PPAPI IDL """ 7 """ Lexer for PPAPI IDL """
8 8
9 # 9 #
10 # IDL Lexer 10 # IDL Lexer
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 # IDL Lexer 42 # IDL Lexer
43 # 43 #
44 class IDLLexer(object): 44 class IDLLexer(object):
45 # 'tokens' is a value required by lex which specifies the complete list 45 # 'tokens' is a value required by lex which specifies the complete list
46 # of valid token types. 46 # of valid token types.
47 tokens = [ 47 tokens = [
48 # Symbol and keywords types 48 # Symbol and keywords types
49 'COMMENT', 49 'COMMENT',
50 'DESCRIBE', 50 'DESCRIBE',
51 'ENUM', 51 'ENUM',
52 'LABEL',
52 'SYMBOL', 53 'SYMBOL',
54 'INLINE',
53 'INTERFACE', 55 'INTERFACE',
54 'STRUCT', 56 'STRUCT',
55 'TYPEDEF', 57 'TYPEDEF',
56 58
57 # Data types 59 # Data types
58 'FLOAT', 60 'FLOAT',
59 'OCT', 61 'OCT',
60 'INT', 62 'INT',
61 'HEX', 63 'HEX',
62 'STRING', 64 'STRING',
63 65
64 # Operators 66 # Operators
65 'LSHIFT' 67 'LSHIFT'
66 ] 68 ]
67 69
68 # 'keywords' is a map of string to token type. All SYMBOL tokens are 70 # 'keywords' is a map of string to token type. All SYMBOL tokens are
69 # matched against keywords, to determine if the token is actually a keyword. 71 # matched against keywords, to determine if the token is actually a keyword.
70 keywords = { 72 keywords = {
73 'attribute' : 'ATTRIBUTE',
71 'describe' : 'DESCRIBE', 74 'describe' : 'DESCRIBE',
72 'enum' : 'ENUM', 75 'enum' : 'ENUM',
76 'label' : 'LABEL',
73 'interface' : 'INTERFACE', 77 'interface' : 'INTERFACE',
74 'readonly' : 'READONLY', 78 'readonly' : 'READONLY',
75 'struct' : 'STRUCT', 79 'struct' : 'STRUCT',
76 'typedef' : 'TYPEDEF', 80 'typedef' : 'TYPEDEF',
77 } 81 }
78 82
79 # 'literals' is a value expected by lex which specifies a list of valid 83 # 'literals' is a value expected by lex which specifies a list of valid
80 # literal tokens, meaning the token type and token value are identical. 84 # literal tokens, meaning the token type and token value are identical.
81 literals = '"*.(){}[],;:=+-' 85 literals = '"*.(){}[],;:=+-'
82 86
(...skipping 24 matching lines...) Expand all
107 def t_STRING(self, t): 111 def t_STRING(self, t):
108 r'"[^"]*"' 112 r'"[^"]*"'
109 t.value = t.value[1:-1] 113 t.value = t.value[1:-1]
110 self.AddLines(t.value.count('\n')) 114 self.AddLines(t.value.count('\n'))
111 return t 115 return t
112 116
113 # A C or C++ style comment: /* xxx */ or // 117 # A C or C++ style comment: /* xxx */ or //
114 def t_COMMENT(self, t): 118 def t_COMMENT(self, t):
115 r'(/\*(.|\n)*?\*/)|(//.*)' 119 r'(/\*(.|\n)*?\*/)|(//.*)'
116 self.AddLines(t.value.count('\n')) 120 self.AddLines(t.value.count('\n'))
121 return t
117 122
118 # C++ comments should keep the newline 123 # Return a "preprocessor" inline block
119 if t.value[:2] == '//': t.value += '\n' 124 def t_INLINE(self, t):
125 r'\#inline (.|\n)*\#endinl.*'
126 self.AddLines(t.value.count('\n'))
120 return t 127 return t
121 128
122 # A symbol or keyword. 129 # A symbol or keyword.
123 def t_KEYWORD_SYMBOL(self, t): 130 def t_KEYWORD_SYMBOL(self, t):
124 r'[A-Za-z][A-Za-z_0-9]*' 131 r'[A-Za-z][A-Za-z_0-9]*'
125 132
126 #All non-keywords are assumed to be symbols 133 #All non-keywords are assumed to be symbols
127 t.type = self.keywords.get(t.value, 'SYMBOL') 134 t.type = self.keywords.get(t.value, 'SYMBOL')
128 return t 135 return t
129 136
130 def t_ANY_error(self, t): 137 def t_ANY_error(self, t):
138 msg = "Unrecognized input"
131 line = self.lexobj.lineno 139 line = self.lexobj.lineno
140
141 # If that line has not been accounted for, then we must have hit
142 # EoF, so compute the beginning of the line that caused the problem.
143 if line >= len(self.index):
144 # Find the offset in the line of the first word causing the issue
145 word = t.value.split()[0]
146 offs = self.lines[line - 1].find(word)
147 # Add the computed line's starting position
148 self.index.append(self.lexobj.lexpos - offs)
149 msg = "Unexpected EoF reached after"
150
132 pos = self.lexobj.lexpos - self.index[line] 151 pos = self.lexobj.lexpos - self.index[line]
133 file = self.lexobj.filename 152 file = self.lexobj.filename
134 out = self.ErrorMessage(file, line, pos, "Unrecognized input") 153 out = self.ErrorMessage(file, line, pos, msg)
135 sys.stderr.write(out + '\n') 154 sys.stderr.write(out + '\n')
136 155
137 def AddLines(self, count): 156 def AddLines(self, count):
138 # Set the lexer position for the beginning of the next line. In the case 157 # Set the lexer position for the beginning of the next line. In the case
139 # of multiple lines, tokens can not exist on any of the lines except the 158 # of multiple lines, tokens can not exist on any of the lines except the
140 # last one, so the recorded value for previous lines are unused. We still 159 # last one, so the recorded value for previous lines are unused. We still
141 # fill the array however, to make sure the line count is correct. 160 # fill the array however, to make sure the line count is correct.
142 self.lexobj.lineno += count 161 self.lexobj.lineno += count
143 for i in range(count): 162 for i in range(count):
144 self.index.append(self.lexobj.lexpos) 163 self.index.append(self.lexobj.lexpos)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 for filename in filenames: 201 for filename in filenames:
183 data = open(filename).read() 202 data = open(filename).read()
184 lexer.SetData(filename, data) 203 lexer.SetData(filename, data)
185 if verbose: sys.stdout.write(' Loaded %s...\n' % filename) 204 if verbose: sys.stdout.write(' Loaded %s...\n' % filename)
186 while 1: 205 while 1:
187 t = lexer.lexobj.token() 206 t = lexer.lexobj.token()
188 if t is None: break 207 if t is None: break
189 outlist.append(t) 208 outlist.append(t)
190 return outlist 209 return outlist
191 210
211
212 def TokensFromText(text):
213 lexer = IDLLexer()
214 lexer.SetData('unknown', text)
215 outlist = []
216 while 1:
217 t = lexer.lexobj.token()
218 if t is None: break
219 outlist.append(t.value)
220 return outlist
221
192 # 222 #
193 # TextToTokens 223 # TextToTokens
194 # 224 #
195 # From a block of text, generate a list of tokens 225 # From a block of text, generate a list of tokens
196 # 226 #
197 def TextToTokens(source): 227 def TextToTokens(source):
198 lexer = IDLLexer() 228 lexer = IDLLexer()
199 outlist = [] 229 outlist = []
200 lexer.SetData('AUTO', source) 230 lexer.SetData('AUTO', source)
201 while 1: 231 while 1:
202 t = lexer.lexobj.token() 232 t = lexer.lexobj.token()
203 if t is None: break 233 if t is None: break
204 outlist.append(t.value) 234 outlist.append(t.value)
205 return outlist 235 return outlist
206 236
207 237
208 # 238 #
209 # TestSame 239 # TestSame
210 # 240 #
211 # From a set of token values, generate a new source text by joining with a 241 # From a set of token values, generate a new source text by joining with a
212 # single space. The new source is then tokenized and compared against the 242 # single space. The new source is then tokenized and compared against the
213 # old set. 243 # old set.
214 # 244 #
215 def TestSame(values): 245 def TestSame(values1):
216 src1 = ' '.join(values) 246 # Recreate the source from the tokens. We use newline instead of whitespace
217 src2 = ' '.join(TextToTokens(src1)) 247 # since the '//' and #inline regex are line sensitive.
248 text = '\n'.join(values1)
249 values2 = TextToTokens(text)
250
251 count1 = len(values1)
252 count2 = len(values2)
253 if count1 != count2:
254 print "Size mismatch original %d vs %d\n" % (count1, count2)
255 if count1 > count2: count1 = count2
256
257 for i in range(count1):
258 if values1[i] != values2[i]:
259 print "%d >>%s<< >>%s<<" % (i, values1[i], values2[i])
218 260
219 if GetOption('output'): 261 if GetOption('output'):
220 sys.stdout.write('Generating original.txt and tokenized.txt\n') 262 sys.stdout.write('Generating original.txt and tokenized.txt\n')
221 open('original.txt', 'w').write(src1) 263 open('original.txt', 'w').write(src1)
222 open('tokenized.txt', 'w').write(src2) 264 open('tokenized.txt', 'w').write(src2)
223 265
224 if src1 == src2: 266 if values1 == values2:
225 sys.stdout.write('Same: Pass\n') 267 sys.stdout.write('Same: Pass\n')
226 return 0 268 return 0
227 269
270 print "****************\n%s\n%s***************\n" % (src1, src2)
228 sys.stdout.write('Same: Failed\n') 271 sys.stdout.write('Same: Failed\n')
229 return -1 272 return -1
230 273
231 274
232 # 275 #
233 # TestExpect 276 # TestExpect
234 # 277 #
235 # From a set of tokens pairs, verify the type field of the second matches 278 # From a set of tokens pairs, verify the type field of the second matches
236 # the value of the first, so that: 279 # the value of the first, so that:
237 # INT 123 FLOAT 1.1 280 # INT 123 FLOAT 1.1
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return -1 319 return -1
277 return 0 320 return 0
278 321
279 except lex.LexError as le: 322 except lex.LexError as le:
280 sys.stderr.write('%s\n' % str(le)) 323 sys.stderr.write('%s\n' % str(le))
281 return -1 324 return -1
282 325
283 if __name__ == '__main__': 326 if __name__ == '__main__':
284 sys.exit(Main(sys.argv[1:])) 327 sys.exit(Main(sys.argv[1:]))
285 328
OLDNEW
« no previous file with comments | « no previous file | ppapi/generators/idl_parser.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698