2012-05-23 04:31:23 +04:00
|
|
|
import sys
|
|
|
|
import yaml
|
|
|
|
import hashlib
|
|
|
|
|
|
|
|
NS = 'Emitter'
|
|
|
|
EVENT_COUNT = 5
|
|
|
|
|
2012-05-23 06:59:12 +04:00
|
|
|
def encode_stream(line):
|
|
|
|
for c in line:
|
|
|
|
if c == '\n':
|
|
|
|
yield '\\n'
|
|
|
|
elif c == '"':
|
|
|
|
yield '\\"'
|
|
|
|
elif c == '\t':
|
|
|
|
yield '\\t'
|
|
|
|
elif ord(c) < 0x20:
|
|
|
|
yield '\\x' + hex(ord(c))
|
|
|
|
else:
|
|
|
|
yield c
|
|
|
|
|
|
|
|
def encode(line):
|
|
|
|
return ''.join(encode_stream(line))
|
|
|
|
|
|
|
|
def doc_start(implicit=False):
|
|
|
|
if implicit:
|
|
|
|
return {'emit': '', 'handle': 'DOC_START()'}
|
|
|
|
else:
|
2012-05-23 07:17:50 +04:00
|
|
|
return {'emit': 'YAML::BeginDoc', 'handle': 'DOC_START()'}
|
2012-05-23 06:59:12 +04:00
|
|
|
|
|
|
|
def doc_end(implicit=False):
|
|
|
|
if implicit:
|
|
|
|
return {'emit': '', 'handle': 'DOC_END()'}
|
|
|
|
else:
|
2012-05-23 07:17:50 +04:00
|
|
|
return {'emit': 'YAML::EndDoc', 'handle': 'DOC_END()'}
|
2012-05-23 06:59:12 +04:00
|
|
|
|
|
|
|
def scalar(value, tag='', anchor='', anchor_id=0):
|
|
|
|
emit = []
|
|
|
|
if tag:
|
|
|
|
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
|
|
|
|
if anchor:
|
|
|
|
emit += ['YAML::Anchor("%s")' % encode(anchor)]
|
2012-05-23 07:17:50 +04:00
|
|
|
if tag:
|
|
|
|
out_tag = encode(tag)
|
|
|
|
else:
|
2012-05-23 20:00:33 +04:00
|
|
|
if value == encode(value):
|
|
|
|
out_tag = '?'
|
|
|
|
else:
|
|
|
|
out_tag = '!'
|
2012-05-23 06:59:12 +04:00
|
|
|
emit += ['"%s"' % encode(value)]
|
2012-05-23 07:17:50 +04:00
|
|
|
return {'emit': emit, 'handle': 'SCALAR("%s", %s, "%s")' % (out_tag, anchor_id, encode(value))}
|
2012-05-23 06:59:12 +04:00
|
|
|
|
2012-05-23 19:56:16 +04:00
|
|
|
def comment(value):
|
|
|
|
return {'emit': 'YAML::Comment("%s")' % value, 'handle': ''}
|
|
|
|
|
2012-05-23 20:11:50 +04:00
|
|
|
def seq_start(tag='', anchor='', anchor_id=0):
|
|
|
|
emit = []
|
|
|
|
if tag:
|
|
|
|
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
|
|
|
|
if anchor:
|
|
|
|
emit += ['YAML::Anchor("%s")' % encode(anchor)]
|
|
|
|
if tag:
|
|
|
|
out_tag = encode(tag)
|
|
|
|
else:
|
|
|
|
out_tag = '?'
|
|
|
|
emit += ['YAML::BeginSeq']
|
|
|
|
return {'emit': emit, 'handle': 'SEQ_START("%s", %s)' % (out_tag, anchor_id)}
|
|
|
|
|
|
|
|
def seq_end():
|
|
|
|
return {'emit': 'YAML::EndSeq', 'handle': 'SEQ_END()'}
|
|
|
|
|
2012-05-23 20:16:32 +04:00
|
|
|
def map_start(tag='', anchor='', anchor_id=0):
|
|
|
|
emit = []
|
|
|
|
if tag:
|
|
|
|
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
|
|
|
|
if anchor:
|
|
|
|
emit += ['YAML::Anchor("%s")' % encode(anchor)]
|
|
|
|
if tag:
|
|
|
|
out_tag = encode(tag)
|
|
|
|
else:
|
|
|
|
out_tag = '?'
|
|
|
|
emit += ['YAML::BeginMap']
|
|
|
|
return {'emit': emit, 'handle': 'MAP_START("%s", %s)' % (out_tag, anchor_id)}
|
|
|
|
|
|
|
|
def map_end():
|
|
|
|
return {'emit': 'YAML::EndMap', 'handle': 'MAP_END()'}
|
|
|
|
|
2012-05-23 19:56:16 +04:00
|
|
|
def gen_templates():
|
2012-05-23 20:11:50 +04:00
|
|
|
yield [[doc_start(), doc_start(True)],
|
|
|
|
[scalar('foo'), scalar('foo\n'), scalar('foo', 'tag'), scalar('foo', '', 'anchor', 1)],
|
|
|
|
[doc_end(), doc_end(True)]]
|
|
|
|
yield [[doc_start(), doc_start(True)],
|
|
|
|
[seq_start()],
|
|
|
|
[[], [scalar('foo')], [scalar('foo', 'tag')], [scalar('foo', '', 'anchor', 1)], [scalar('foo', 'tag', 'anchor', 1)], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]],
|
|
|
|
[seq_end()],
|
|
|
|
[doc_end(), doc_end(True)]]
|
2012-05-23 20:16:32 +04:00
|
|
|
yield [[doc_start(), doc_start(True)],
|
|
|
|
[map_start()],
|
|
|
|
[[], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]],
|
|
|
|
[map_end()],
|
|
|
|
[doc_end(), doc_end(True)]]
|
|
|
|
yield [[doc_start(True)],
|
|
|
|
[map_start()],
|
|
|
|
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
|
|
|
|
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
|
|
|
|
[map_end()],
|
|
|
|
[doc_end(True)]]
|
2012-05-23 19:56:16 +04:00
|
|
|
|
|
|
|
def expand(template):
|
|
|
|
if len(template) == 0:
|
|
|
|
pass
|
|
|
|
elif len(template) == 1:
|
|
|
|
for item in template[0]:
|
|
|
|
if isinstance(item, list):
|
|
|
|
yield item
|
|
|
|
else:
|
|
|
|
yield [item]
|
|
|
|
else:
|
|
|
|
for car in expand(template[:1]):
|
|
|
|
for cdr in expand(template[1:]):
|
|
|
|
yield car + cdr
|
|
|
|
|
2012-05-23 04:31:23 +04:00
|
|
|
|
|
|
|
def gen_events():
|
2012-05-23 19:56:16 +04:00
|
|
|
for template in gen_templates():
|
|
|
|
for events in expand(template):
|
2012-05-23 20:00:33 +04:00
|
|
|
base = list(events)
|
|
|
|
for i in range(0, len(base)+1):
|
|
|
|
cpy = list(base)
|
|
|
|
cpy.insert(i, comment('comment'))
|
|
|
|
yield cpy
|
2012-05-23 04:31:23 +04:00
|
|
|
|
|
|
|
def gen_tests():
|
|
|
|
for events in gen_events():
|
|
|
|
name = 'test' + hashlib.sha1(''.join(yaml.dump(event) for event in events)).hexdigest()[:20]
|
|
|
|
yield {'name': name, 'events': events}
|
|
|
|
|
|
|
|
|
|
|
|
def create_emitter_tests(out):
|
|
|
|
out.write('namespace %s {\n' % NS)
|
|
|
|
|
2012-05-23 07:10:47 +04:00
|
|
|
tests = list(gen_tests())
|
|
|
|
|
|
|
|
for test in tests:
|
|
|
|
out.write('TEST %s(YAML::Emitter& out)\n' % test['name'])
|
2012-05-23 04:31:23 +04:00
|
|
|
out.write('{\n')
|
|
|
|
for event in test['events']:
|
|
|
|
emit = event['emit']
|
2012-05-23 06:59:12 +04:00
|
|
|
if isinstance(emit, list):
|
|
|
|
for e in emit:
|
|
|
|
out.write(' out << %s;\n' % e)
|
|
|
|
elif emit:
|
2012-05-23 04:31:23 +04:00
|
|
|
out.write(' out << %s;\n' % emit)
|
|
|
|
out.write('\n')
|
|
|
|
out.write(' HANDLE(out.c_str());\n')
|
|
|
|
for event in test['events']:
|
|
|
|
handle = event['handle']
|
|
|
|
if handle:
|
|
|
|
out.write(' EXPECT_%s;\n' % handle)
|
|
|
|
out.write(' DONE();\n')
|
|
|
|
out.write('}\n')
|
|
|
|
|
|
|
|
out.write('}\n')
|
|
|
|
|
2012-05-23 07:10:47 +04:00
|
|
|
out.write('void RunGenEmitterTests(int& passed, int& total)\n')
|
|
|
|
out.write('{\n')
|
|
|
|
for test in tests:
|
2012-05-23 07:17:50 +04:00
|
|
|
out.write(' RunGenEmitterTest(&Emitter::%s, "%s", passed, total);\n' % (test['name'], encode(test['name'])))
|
2012-05-23 07:10:47 +04:00
|
|
|
out.write('}\n')
|
|
|
|
|
2012-05-23 04:31:23 +04:00
|
|
|
if __name__ == '__main__':
|
|
|
|
create_emitter_tests(sys.stdout)
|