2 ##########################################################################
4 # Copyright 2010 VMware, Inc.
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 ##########################################################################/
28 """Parser for OpenGL .txt extensions specification."""
34 from urllib2 import urlopen
38 sys.stderr.write(str(x) + '\n')
43 def __init__(self, stream):
48 """Base class for parsers that read line-based formats."""
50 def __init__(self, stream):
58 raise NotImplementedError
61 line = self._stream.readline()
65 self._line = line.rstrip('\r\n')
68 assert self._line is not None
72 assert self._line is not None
78 assert self._line is not None
81 def skip_whitespace(self):
82 while not self.eof() and self.match_whitespace() or self.match_comment():
85 def match_whitespace(self):
86 line = self.lookahead()
87 return not line.strip()
89 def match_comment(self):
93 class TxtParser(LineParser):
95 section_re = re.compile(r'^([A-Z]\w+)( \w+)*$')
97 property_re = re.compile(r'^\w+:')
98 prototype_re = re.compile(r'^(\w+)\((.*)\)$')
100 comment_start_re = re.compile(r'^/\*')
101 comment_end_re = re.compile(r'.*\*/$')
103 def __init__(self, stream, prefix=''):
104 LineParser.__init__(self, stream)
108 while not self.eof():
109 while not self.eof():
110 line = self.lookahead()
113 mo = self.section_re.match(line)
117 line = self.consume()
118 self.parse_section(line)
121 def parse_section(self, name):
122 if name == 'Name Strings':
124 if name == 'New Procedures and Functions':
127 def parse_strings(self):
128 while not self.eof():
129 line = self.lookahead()
133 if not line.startswith(' '):
137 if name.startswith('EGL_'):
141 def skip_c_comments(self):
142 while not self.eof():
143 line = self.lookahead().strip()
144 mo = self.comment_start_re.match(line)
147 while not self.eof():
149 mo = self.comment_end_re.match(line)
152 line = self.lookahead().strip()
154 def parse_procs(self):
156 while not self.eof():
157 self.skip_c_comments()
158 line = self.lookahead()
162 if not line[0].isspace():
165 lines.append(line.strip())
166 if line[-1] in (';', ')'):
167 prototype = ' '.join(lines)
168 self.parse_proc(prototype)
171 token_re = re.compile(r'(\w+|\s+|.)')
172 get_function_re = re.compile(r'^Get[A-Z]\w+')
174 def parse_proc(self, prototype):
176 tokens = self.token_re.split(prototype)
177 self.tokens = [token for token in tokens if token.strip()]
180 ret = self.parse_type()
182 name = self.tokens.pop(0)
184 if self.get_function_re.match(name):
185 extra += ', sideeffects=False'
186 name = self.prefix + name
188 assert self.tokens.pop(0) == '('
190 while self.tokens[0] != ')':
191 arg = self.parse_arg()
193 if self.tokens[0] == ',':
195 print ' GlFunction(%s, "%s", [%s]%s),' % (ret, name, ', '.join(args), extra)
198 type = self.parse_type()
199 if self.tokens[0] == ')':
200 assert type == 'Void'
202 name = self.tokens.pop(0)
203 if self.tokens[0] == '[':
205 n = int(self.tokens.pop(0))
206 assert self.tokens.pop(0) == ']'
207 type = 'Array(%s, %d)' % (type, n)
208 return '(%s, "%s")' % (type, name)
210 def parse_type(self):
211 token = self.tokens.pop(0)
213 return 'Const(%s)' % self.parse_type()
217 type = self.prefix.upper() + token
218 while self.tokens[0] == '*':
219 type = 'OpaquePointer(%s)' % type
225 optparser = optparse.OptionParser(
226 usage="\n\t%prog [options] [URL|TXT] ...")
227 optparser.add_option(
228 '-p', '--prefix', metavar='STRING',
229 type="string", dest="prefix", default='gl',
230 help="function prefix [default: %default]")
232 (options, args) = optparser.parse_args(sys.argv[1:])
235 if arg.startswith('http://'):
236 stream = urlopen(arg, 'rt')
238 stream = open(arg, 'rt')
239 parser = TxtParser(stream, prefix = options.prefix)
243 if __name__ == '__main__':