home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / gtk-2.0 / codegen / scmexpr.py < prev   
Encoding:
Python Source  |  2007-11-01  |  4.8 KB  |  144 lines

  1. #!/usr/bin/env python
  2. # -*- Mode: Python; py-indent-offset: 4 -*-
  3. from __future__ import generators
  4.  
  5. import string
  6. from cStringIO import StringIO
  7.  
  8. class error(Exception):
  9.     def __init__(self, filename, lineno, msg):
  10.         Exception.__init__(self, msg)
  11.         self.filename = filename
  12.         self.lineno = lineno
  13.         self.msg = msg
  14.     def __str__(self):
  15.         return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
  16.  
  17. trans = [' '] * 256
  18. for i in range(256):
  19.     if chr(i) in string.letters + string.digits + '_':
  20.         trans[i] = chr(i)
  21.     else:
  22.         trans[i] = '_'
  23. trans = string.join(trans, '')
  24.  
  25. def parse(filename):
  26.     if isinstance(filename, str):
  27.         fp = open(filename, 'r')
  28.     else: # if not string, assume it is some kind of iterator
  29.         fp = filename
  30.         filename = getattr(fp, 'name', '<unknown>')
  31.     whitespace = ' \t\n\r\x0b\x0c'
  32.     nonsymbol = whitespace + '();\'"'
  33.     stack = []
  34.     openlines = []
  35.     lineno = 0
  36.     for line in fp:
  37.         pos = 0
  38.         lineno += 1
  39.         while pos < len(line):
  40.             if line[pos] in whitespace: # ignore whitespace
  41.                 pass
  42.             elif line[pos] == ';': # comment
  43.                 break
  44.             elif line[pos:pos+2] == "'(":
  45.                 pass # the open parenthesis will be handled next iteration
  46.             elif line[pos] == '(':
  47.                 stack.append(())
  48.                 openlines.append(lineno)
  49.             elif line[pos] == ')':
  50.                 if len(stack) == 0:
  51.                     raise error(filename, lineno, 'close parenthesis found when none open')
  52.                 closed = stack[-1]
  53.                 del stack[-1]
  54.                 del openlines[-1]
  55.                 if stack:
  56.                     stack[-1] += (closed,)
  57.                 else:
  58.                     yield closed
  59.             elif line[pos] == '"': # quoted string
  60.                 if not stack:
  61.                     raise error(filename, lineno,
  62.                                 'string found outside of s-expression')
  63.                 endpos = pos + 1
  64.                 chars = []
  65.                 while endpos < len(line):
  66.                     if endpos+1 < len(line) and line[endpos] == '\\':
  67.                         endpos += 1
  68.                         if line[endpos] == 'n':
  69.                             chars.append('\n')
  70.                         elif line[endpos] == 'r':
  71.                             chars.append('\r')
  72.                         elif line[endpos] == 't':
  73.                             chars.append('\t')
  74.                         else:
  75.                             chars.append('\\')
  76.                             chars.append(line[endpos])
  77.                     elif line[endpos] == '"':
  78.                         break
  79.                     else:
  80.                         chars.append(line[endpos])
  81.                     endpos += 1
  82.                 if endpos >= len(line):
  83.                     raise error(filename, lineno, "unclosed quoted string")
  84.                 pos = endpos
  85.                 stack[-1] += (''.join(chars),)
  86.             else: # symbol/number
  87.                 if not stack:
  88.                     raise error(filename, lineno,
  89.                                 'identifier found outside of s-expression')
  90.                 endpos = pos
  91.                 while endpos < len(line) and line[endpos] not in nonsymbol:
  92.                     endpos += 1
  93.                 symbol = line[pos:endpos]
  94.                 pos = max(pos, endpos-1)
  95.                 try: symbol = int(symbol)
  96.                 except ValueError:
  97.                     try: symbol = float(symbol)
  98.                     except ValueError: pass
  99.                 stack[-1] += (symbol,)
  100.             pos += 1
  101.     if len(stack) != 0:
  102.         msg = '%d unclosed parentheses found at end of ' \
  103.               'file (opened on line(s) %s)' % (len(stack),
  104.                                                ', '.join(map(str, openlines)))
  105.         raise error(filename, lineno, msg)
  106.  
  107. class Parser:
  108.     def __init__(self, filename):
  109.         """Argument is either a string, a parse tree, or file object"""
  110.         self.filename = filename
  111.     def startParsing(self, filename=None):
  112.         statements = parse(filename or self.filename)
  113.         for statement in statements:
  114.             self.handle(statement)
  115.     def handle(self, tup):
  116.         cmd = string.translate(tup[0], trans)
  117.         if hasattr(self, cmd):
  118.             getattr(self, cmd)(*tup[1:])
  119.         else:
  120.             self.unknown(tup)
  121.     def unknown(self, tup):
  122.         pass
  123.  
  124. _testString = """; a scheme file
  125. (define-func gdk_font_load    ; a comment at end of line
  126.   GdkFont
  127.   ((string name)))
  128.  
  129. (define-boxed GdkEvent
  130.   gdk_event_copy
  131.   gdk_event_free
  132.   "sizeof(GdkEvent)")
  133. """
  134.  
  135. if __name__ == '__main__':
  136.     import sys
  137.     if sys.argv[1:]:
  138.         fp = open(sys.argv[1])
  139.     else:
  140.         fp = StringIO(_testString)
  141.     statements = parse(fp)
  142.     for s in statements:
  143.         print `s`
  144.