Skip to content

Instantly share code, notes, and snippets.

@juntalis
Created June 17, 2013 15:34
Show Gist options
  • Select an option

  • Save juntalis/5797844 to your computer and use it in GitHub Desktop.

Select an option

Save juntalis/5797844 to your computer and use it in GitHub Desktop.
import string
ws = string.whitespace
def cleanup(doc):
return ' '.join([ l.strip(ws) for l in doc.splitlines() ])
class Declaration(object):
def __init__(self, name, doc=None):
self.name = name
if doc is None:
doc = ''
self.doc = doc
def __str__(self):
return '{0} <variable> : {1}'.format(self.name, self.doc)
def __repr__(self): return self.__str__()
class Function(Declaration):
def __init__(self, name, params, doc=None):
super(Function, self).__init__(name, doc)
self.params = []
self.ret = None
for param in params:
param = param.strip(ws)
if len(param) == 0: continue
if ' ' in param:
parts = map(lambda a: a.strip(ws), param.split(' '))
if len(parts) > 2:
print 'Parts','=',parts
raise Exception('Dont know what to do with parts of param')
elif len(parts) == 2 and parts[1].upper().startswith('OPT'):
param = parts[0] + '?'
self.params.append(param)
def __str__(self):
return '{0}({1}) <function> : {2}'.format(self.name, self.params, self.doc)
from string import *
import re
from yappsrt import *
class LineClassifierScanner(Scanner):
patterns = [
("r'\\)'", re.compile('\\)')),
("r'\\('", re.compile('\\(')),
('END', re.compile('$')),
('EOL', re.compile('\\n')),
('IDENTIFIER', re.compile('[A-Za-z_][A-Za-z0-9_]+')),
('SEP', re.compile('\\ *[:=-]\\ *')),
('OWS', re.compile('\\ *')),
('WS', re.compile(' +')),
('FOLLOWUP', re.compile('\\n(?:\\ {2})+')),
('PARAMS', re.compile('[^\\)\\n]+')),
('SUMMARY', re.compile('[A-Za-z0-9_\\(=]\\w+ [^\\n]+')),
('OPTIONAL', re.compile('OPT(?:IONAL)?')),
('TYPE', re.compile('[A-Za-z][Aa]ddress|[Bb]ytecount|[Tt]able|[Vv]alue|[Ww]idechar|[Nn]number|[Ii]nt(?:eger)?|[Ff]ilename|[sS]trings?|[Nn]ame|[Pp](?:rocess)?id|[Ff]unction|[Oo]bject|[Ss]ize')),
('TABLE', re.compile('{}')),
]
def __init__(self, str):
Scanner.__init__(self,None,[],str)
class LineClassifier(Parser):
def goal(self):
v = []
while self._peek('OWS', 'END', 'IDENTIFIER', 'SUMMARY') != 'END':
_token_ = self._peek('OWS', 'IDENTIFIER', 'SUMMARY')
if _token_ != 'OWS':
classified = self.classified()
EOL = self._scan('EOL')
v.append(classified)
else:# == 'OWS'
OWS = self._scan('OWS')
EOL = self._scan('EOL')
END = self._scan('END')
return '\n'.join([str(i) for i in v])
def classified(self):
_token_ = self._peek('IDENTIFIER', 'SUMMARY')
if _token_ == 'IDENTIFIER':
declaration = self.declaration()
return declaration
else:# == 'SUMMARY'
summary = self.summary()
return summary
def declaration(self):
IDENTIFIER = self._scan('IDENTIFIER')
n = IDENTIFIER
_token_ = self._peek('SEP', "r'\\('")
if _token_ == 'SEP':
SEP = self._scan('SEP')
summary = self.summary()
r = Declaration(n, summary)
else:# == "r'\\('"
params = self.params()
r = Function(n, params)
_token_ = self._peek('SEP', 'FOLLOWUP', 'EOL')
if _token_ == 'SEP':
SEP = self._scan('SEP')
_token_ = self._peek('SUMMARY', 'TABLE', 'IDENTIFIER')
if _token_ == 'SUMMARY':
summary = self.summary()
r.doc = summary
else:# in ['TABLE', 'IDENTIFIER']
restype = self.restype()
r.ret = restype
_token_ = self._peek('SEP', 'EOL')
if _token_ == 'SEP':
SEP = self._scan('SEP')
summary = self.summary()
r.doc = summary
else:# == 'EOL'
pass
elif _token_ == 'FOLLOWUP':
FOLLOWUP = self._scan('FOLLOWUP')
SUMMARY = self._scan('SUMMARY')
r.doc = cleanup(SUMMARY)
else:# == 'EOL'
pass
return r
def restype(self):
_token_ = self._peek('TABLE', 'IDENTIFIER')
if _token_ == 'TABLE':
TABLE = self._scan('TABLE')
return 'table'
else:# == 'IDENTIFIER'
IDENTIFIER = self._scan('IDENTIFIER')
return IDENTIFIER
def summary(self):
SUMMARY = self._scan('SUMMARY')
b = SUMMARY
while self._peek('FOLLOWUP', 'EOL') == 'FOLLOWUP':
FOLLOWUP = self._scan('FOLLOWUP')
SUMMARY = self._scan('SUMMARY')
b += '\n' + SUMMARY
return cleanup(b)
def params(self):
self._scan("r'\\('")
l = []
_token_ = self._peek('PARAMS', "r'\\)'")
if _token_ == 'PARAMS':
PARAMS = self._scan('PARAMS')
map(l.append, PARAMS.split(','))
else:# == "r'\\)'"
pass
self._scan("r'\\)'")
return l
def parse(rule, text):
P = LineClassifier(LineClassifierScanner(text))
return wrap_error_reporter(P, rule)
if __name__ == '__main__':
from sys import argv, stdin
if len(argv) >= 2:
if len(argv) >= 3:
f = open(argv[2],'r')
else:
f = stdin
print parse(argv[1], f.read())
else: print 'Args: <rule> [<filename>]'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment