--- a/pvl/dhcp/config.py Wed Sep 11 15:17:53 2013 +0300
+++ b/pvl/dhcp/config.py Mon Dec 16 10:21:37 2013 +0200
@@ -11,16 +11,22 @@
Doesn't implement the full spec, but a useful approximation.
"""
+ @classmethod
+ def load (cls, file) :
+ return cls().parse_file(file)
+
def __init__ (self) :
+ self.stack = []
self.block = None
self.items = []
+ self.blocks = []
@classmethod
def split (cls, line) :
"""
Split given line-data.
- >>> split = DHCPLeasesParser.split
+ >>> split = DHCPConfigParser.split
>>> split('foo bar')
['foo', 'bar']
>>> split('"foo"')
@@ -48,7 +54,7 @@
"""
Yield tokens from the given lines.
- >>> lex = DHCPLeasesParser.lex
+ >>> lex = DHCPConfigParser.lex
>>> list(lex('foo;'))
[('item', ['foo'])]
>>> list(item for line in ['foo {', ' bar;', '}'] for item in lex(line))
@@ -109,20 +115,18 @@
"""
Open new block.
"""
-
- # XXX: stack
- assert not self.block
+
+ self.stack.append((self.block, self.items, self.blocks))
self.block = block
self.items = []
+ self.blocks = []
- def feed_block (self, item) :
+ def feed_item (self, item) :
"""
Add item to block
"""
- assert self.block
-
self.items.append(item)
def pop_block (self) :
@@ -133,30 +137,31 @@
assert self.block
- block, items = self.block, self.items
+ block = (self.block, self.items, self.blocks)
- self.block = None
- self.items = None
+ self.block, self.items, self.blocks = self.stack.pop(-1)
- return block, items
+ self.blocks.append(block)
- def parse (self, line) :
+ return block
+
+ def parse_line (self, line) :
"""
Parse given line, yielding any complete blocks that come out.
Yields (block, [ lines ]) tuples.
- >>> parser = DHCPLeasesParser()
+ >>> parser = DHCPConfigParser()
>>> list(parser.parse_lines(['foo {', ' bar;', ' quux asdf;', '}']))
- [(['foo'], [['bar'], ['quux', 'asdf']])]
+ [(['foo'], [['bar'], ['quux', 'asdf']], [])]
- >>> parser = DHCPLeasesParser()
- >>> list(parser.parse('foo {'))
+ >>> parser = DHCPConfigParser()
+ >>> list(parser.parse_line('foo {'))
[]
>>> list(parser.parse_lines([' bar;', ' quux asdf;']))
[]
- >>> list(parser.parse('}'))
- [(['foo'], [['bar'], ['quux', 'asdf']])]
+ >>> list(parser.parse_line('}'))
+ [(['foo'], [['bar'], ['quux', 'asdf']], [])]
"""
for token, args in self.lex(line) :
@@ -167,10 +172,10 @@
block = args
if self.block :
- log.warn("nested blocks: %s > %s", self.block, block)
- continue
-
- log.debug("open block: %s", block)
+ log.debug("nested block: %s > %s", self.block, block)
+ else :
+ log.debug("open block: %s", block)
+
self.push_block(block)
elif token == 'close' :
@@ -183,12 +188,8 @@
elif token == 'item' :
item = args
- if not self.block :
- log.warn("token outside block: %s: %s", token, args)
- continue
-
log.debug("block %s item: %s", self.block, item)
- self.feed_block(item)
+ self.feed_item(item)
else :
# ???
@@ -200,7 +201,21 @@
"""
for line in lines :
- for item in self.parse(line) :
+ for item in self.parse_line(line) :
yield item
+ def parse_file (self, file) :
+ """
+ Parse an entire file, returning (items, blocks) lists.
+ >>> DHCPConfigParser().parse_file(['foo;', 'barfoo {', 'bar;', '}'])
+ ([['foo']], [(['barfoo'], [['bar']], [])])
+ """
+
+ for line in file :
+ for item in self.parse_line(line) :
+ log.debug("%s", item)
+
+ assert not self.block
+
+ return self.items, self.blocks