1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# 5# Copyright 2017, Data61 6# Commonwealth Scientific and Industrial Research Organisation (CSIRO) 7# ABN 41 687 119 230. 8# 9# This software may be distributed and modified according to the terms of 10# the BSD 2-Clause license. Note that NO WARRANTY is provided. 11# See "LICENSE_BSD2.txt" for details. 12# 13# @TAG(DATA61_BSD) 14# 15 16'''Generate railroad diagrams of the CAmkES syntax. Note that this needs a very 17up to date version of parcon to generate diagrams correctly. At time of writing, 18you need to get this from https://github.com/javawizard/parcon. 19''' 20 21from __future__ import absolute_import, division, print_function, \ 22 unicode_literals 23 24import os, sys 25 26from parcon.railroad import Bullet, Loop, Nothing, Or, PRODUCTION, TEXT, Then, Token 27from parcon.railroad.raildraw import draw_to_png 28 29def Production(t): 30 return Token(PRODUCTION, t) 31def Text(t): 32 return Token(TEXT, t) 33 34def diag(*obj): 35 o = list(obj) + [Bullet()] 36 return Then(Bullet(), *o) 37 38DIAGRAMS = [ 39 {'assembly':diag( 40 Text('assembly'), 41 Text('{'), 42 Production('composition'), 43 Or(Production('configuration'), 44 Nothing()), 45 Text('}')) 46 }, 47 {'attribute':diag( 48 Production('type'), 49 Production('id')) 50 }, 51 {'composition':diag( 52 Text('composition'), 53 Text('{'), 54 Loop(Or(Production('instance'), 55 Production('connection'), 56 Nothing()), 57 Nothing()), 58 Text('}')) 59 }, 60 {'component':diag( 61 Text('component'), 62 Production('id'), 63 Text('{'), 64 Loop(Or( 65 Then(Text('control'), Text(';')), 66 Then(Text('uses'), Production('id'), Production('id')), 67 Then(Text('provides'), Production('id'), Production('id')), 68 Then(Text('consumes'), Production('id'), Production('id')), 69 Then(Text('emits'), Production('id'), Production('id')), 70 Then(Text('dataport'), Production('id'), Production('id')), 71 Then(Text('has'), Text('mutex'), Production('id')), 72 Then(Text('has'), Text('semaphore'), Production('id')), 73 Nothing()), 74 Nothing()), 75 Text('}')) 76 }, 77 {'connection':diag( 78 Text('connection'), 79 Production('id'), 80 Production('id'), 81 Text('('), 82 Text('from'), 83 Production('id'), 84 Text('.'), 85 Production('id'), 86 Text(','), 87 Text('to'), 88 Production('id'), 89 Text('.'), 90 Production('id'), 91 Text(')'), 92 Text(';')) 93 }, 94 {'dataport':diag( 95 Text('dataport'), 96 Production('id'), 97 Production('id')) 98 }, 99 {'direction':diag(Or( 100 Text('refin'), 101 Text('in'), 102 Text('inout'), 103 Text('out'))) 104 }, 105 {'event':diag( 106 Text('event'), 107 Production('id'), 108 Text('='), 109 Production('number')) 110 }, 111 {'instance':diag( 112 Text('component'), 113 Production('id'), 114 Production('id'), 115 Text(';')) 116 }, 117 {'method':diag( 118 Or( 119 Text('void'), 120 Production('type')), 121 Production('id'), 122 Text('('), 123 Or( 124 Text('void'), 125 Loop( 126 Production('parameter'), 127 Nothing()), 128 Nothing()), 129 Text(')'), 130 Text(';')) 131 }, 132 {'parameter':diag( 133 Production('direction'), 134 Production('type'), 135 Production('id')) 136 }, 137 {'procedure':diag( 138 Or( 139 Loop( 140 Production('method'), 141 Nothing()), 142 Nothing())) 143 }, 144 {'setting':diag( 145 Production('id'), 146 Text('.'), 147 Production('id'), 148 Text('='), 149 Or(Production('boolean'), 150 Production('number'), 151 Production('string'), 152 Production('id'))) 153 }, 154 {'type':diag(Or( 155 Text('int'), 156 Text('integer'), 157 Text('signed int'), 158 Text('unsigned int'), 159 Text('unsigned integer'), 160 Text('int8_t'), 161 Text('int16_t'), 162 Text('int32_t'), 163 Text('int64_t'), 164 Text('uint8_t'), 165 Text('uint16_t'), 166 Text('uint32_t'), 167 Text('uint64_t'), 168 Text('real'), 169 Text('double'), 170 Text('float'), 171 Text('uintptr_t'), 172 Text('char'), 173 Text('character'), 174 Text('boolean'), 175 Text('bool'), 176 Text('string'))) 177 }, 178] 179 180def main(): 181 if len(sys.argv) == 2: 182 out = sys.argv[1] 183 elif len(sys.argv) == 1: 184 out = os.curdir 185 else: 186 sys.stderr.write('Usage: %s [output directory]\n' % sys.argv[0]) 187 return -1 188 189 # Tweak options to hide the title we don't need. 190 options = { 191 'raildraw_title_hide':True, 192 'raildraw_title_after':0, 193 } 194 195 # Dump each diagram as a PNG. 196 for d in DIAGRAMS: 197 path = os.path.join(out, '%s.png' % list(d.keys())[0]) 198 draw_to_png(d, options, path, True) 199 200 return 0 201 202if __name__ == '__main__': 203 sys.exit(main()) 204