Last active
December 28, 2015 17:29
-
-
Save drslump/7536419 to your computer and use it in GitHub Desktop.
Simple hand coded parser for alarms config
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CfgParser: | |
def __init__(self, src): | |
self.src = src | |
self.idx = 0 | |
def rowcol(self, ofs=None): | |
ofs = self.idx if ofs is None else ofs | |
lines = self.src.split('\n') | |
accum = 0 | |
for ln, line in enumerate(lines): | |
accum += len(line) + 1 | |
if accum > ofs: | |
return (ln, accum - ofs) | |
return (-1, -1) | |
def char(self): | |
ch = self.src[self.idx] | |
self.idx += 1 | |
return ch | |
def peek(self): | |
return self.src[self.idx] | |
def word(self): | |
word = '' | |
while True: | |
ch = self.peek() | |
if not ch.isalpha() and ch != '_': | |
break | |
word += self.char() | |
return word | |
def space(self): | |
space = '' | |
while True: | |
ch = self.peek() | |
if ch == '#': # Skip comments | |
self.line() | |
continue | |
elif ch not in (' ', '\t', '\r', '\n'): | |
break | |
space += self.char() | |
return space | |
def line(self): | |
line = '' | |
while True: | |
ch = self.char() | |
if ch == '\n': | |
break | |
line += ch | |
return line | |
def parse_define(self): | |
word = self.word() | |
assert word == 'define', "Expected `define` at " + repr(self.rowcol()) | |
self.space() | |
word = self.word() | |
sect = self.parse_section() | |
return (word, sect) | |
def parse_section(self): | |
sect = {} | |
self.space() | |
assert self.char() == '{', "Expected `{` at " + repr(self.rowcol()) | |
self.space() | |
while self.peek() != '}': | |
self.space() | |
prop = self.word() | |
self.space() | |
line = self.line() | |
sect[prop] = line | |
self.char() # Consume ending } | |
return sect | |
def parse(self): | |
results = {'host': [], 'hostgroup': [], 'service': []} | |
try: | |
while True: | |
self.space() | |
kind, sect = self.parse_define() | |
if kind not in results: | |
raise AssertionError('unsupported define "' + kind + '" near ' + repr(self.rowcol())) | |
results[kind].append(sect) | |
except AssertionError as ex: | |
print "ERROR: " + str(ex) | |
return None | |
except IndexError: | |
pass | |
except Exception as ex: | |
print 'Exception', ex.__class__, ex | |
return results | |
import sys | |
if len(sys.argv) > 1: | |
fp = open(sys.argv[1]) | |
code = fp.read() | |
else: | |
fp = sys.stdin | |
code = fp.read() | |
p = CfgParser(code) | |
results = p.parse() | |
from pprint import pprint | |
pprint(results) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment