summaryrefslogtreecommitdiff
path: root/yarnlib/block_parser.py
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2013-06-09 11:56:29 +0100
committerLars Wirzenius <liw@liw.fi>2013-06-09 11:56:29 +0100
commita91ac948b037f58217d89553fa031a18960b9623 (patch)
tree854a96f1d2d3fb3a58411ac6ae661a089a6ae607 /yarnlib/block_parser.py
parent7fdb775486405a334b2f0db4e47eac9c7ed53023 (diff)
downloadcmdtest-a91ac948b037f58217d89553fa031a18960b9623.tar.gz
Implement BlockParser
Diffstat (limited to 'yarnlib/block_parser.py')
-rw-r--r--yarnlib/block_parser.py112
1 files changed, 111 insertions, 1 deletions
diff --git a/yarnlib/block_parser.py b/yarnlib/block_parser.py
index 8fd87d2..09a7a22 100644
--- a/yarnlib/block_parser.py
+++ b/yarnlib/block_parser.py
@@ -16,6 +16,116 @@
# =*= License: GPL-3+ =*=
+import yarnlib
+
+
+# Parse a sequence of textual blocks into Story and Implementation
+# objects, and their constituent objects.
+
class BlockParser(object):
- pass
+ def __init__(self):
+ self.stories = []
+ self.implementations = []
+ self.line_parsers = {
+ 'STORY': self.parse_story,
+ 'GIVEN': self.parse_given,
+ 'WHEN': self.parse_when,
+ 'THEN': self.parse_then,
+ 'FINALLY': self.parse_finally,
+ 'AND': self.parse_and,
+ 'IMPLEMENTS': self.parse_implementing,
+ }
+
+ def parse_blocks(self, blocks):
+ while blocks:
+ blocks = self.parse_one(blocks)
+
+ def parse_one(self, blocks):
+ assert blocks
+ block = blocks[0]
+ assert block
+ t = block.split('\n', 1)
+ assert len(t) in [1,2]
+ if len(t) == 1:
+ line1 = block
+ block = ''
+ else:
+ line1, block = t
+ if block:
+ blocks[0] = block
+ else:
+ del blocks[0]
+
+ words = line1.split()
+ if not words:
+ return blocks
+ rest = ' '.join(words[1:])
+
+ for keyword in self.line_parsers:
+ if words[0] == keyword:
+ return self.line_parsers[keyword](rest, blocks)
+
+ raise StoryTestSyntaxError("Syntax error: unknown step: %s" % line1)
+
+ def parse_story(self, line, blocks):
+ self.stories.append(yarnlib.Story(line))
+ return blocks
+
+ def parse_simple(self, what, line, blocks):
+ if not self.stories:
+ raise StoryTestSyntaxError('Syntax errror: %s before STORY' % what)
+ step = yarnlib.StoryStep(what, line)
+ self.stories[-1].steps.append(step)
+ return blocks
+
+ def parse_given(self, line, blocks):
+ return self.parse_simple('GIVEN', line, blocks)
+
+ def parse_when(self, line, blocks):
+ return self.parse_simple('WHEN', line, blocks)
+
+ def parse_then(self, line, blocks):
+ return self.parse_simple('THEN', line, blocks)
+
+ def parse_finally(self, line, blocks):
+ return self.parse_simple('FINALLY', line, blocks)
+
+ def parse_and(self, line, blocks):
+ if not self.stories:
+ raise StoryTestSyntaxError('Syntax errror: AND before STORY')
+ story = self.stories[-1]
+ if not story.steps:
+ raise StoryTestSyntaxError(
+ 'Syntax errror: AND before what it would continue')
+ step = story.steps[-1]
+ assert step.what in self.line_parsers
+ return self.line_parsers[step.what](line, blocks)
+
+ def parse_implementing(self, line, blocks):
+ words = line.split()
+ if len(words) < 2:
+ raise StoryTestSyntaxError(
+ 'Syntax error: IMPLEMENTING must have what and regexp')
+ what = words[0]
+ regexp = ' '.join(words[1:])
+ if blocks:
+ block = blocks[0]
+ shell = []
+ rest = []
+ for block_line in block.splitlines():
+ if rest or block_line.startswith('IMPLEMENTS'):
+ rest.append(block_line)
+ else:
+ shell.append(block_line)
+ shell = '\n'.join(shell)
+ if rest:
+ blocks[0] = '\n'.join(rest)
+ else:
+ del blocks[0]
+ else:
+ shell = ''
+ implementation = yarnlib.Implementation(what, regexp, shell)
+ self.implementations.append(implementation)
+ return blocks
+