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''' 17Stage 6 parser. The following parser is designed to accept a stage 5 parser, 18whose output it consumes. This parser's purpose is to combine multiple assembly 19entities into a single top-level assembly. 20''' 21 22from __future__ import absolute_import, division, print_function, \ 23 unicode_literals 24from camkes.internal.seven import cmp, filter, map, zip 25 26from .base import Transformer 27from camkes.ast import Assembly, Composition, Configuration, Group, \ 28 TraversalAction 29from .exception import ParseError 30 31def precondition(ast_lifted): 32 ''' 33 Precondition of this parser. No groups should be present in the AST. 34 ''' 35 return all(not isinstance(x, Group) for x in ast_lifted) 36 37def postcondition(ast_lifted): 38 ''' 39 Postcondition of the stage 6 parser. Only a single assembly should remain. 40 ''' 41 class Post(TraversalAction): 42 def __init__(self): 43 self.count = 0 44 def __call__(self, item): 45 if isinstance(item, Assembly): 46 self.count += 1 47 return item 48 49 p = Post() 50 ast_lifted.postorder(p) 51 52 return p.count <= 1 53 54def compose_assemblies(ast): 55 assembly = ast.assembly 56 57 if assembly is None: 58 raise ParseError('no assembly found in input specification') 59 60 # collect pieces from all assemblies 61 for a in [x for x in ast.items if isinstance(x, Assembly) and 62 not x is assembly]: 63 64 assembly.composition.instances.extend(a.composition.instances) 65 assembly.composition.connections.extend(a.composition.connections) 66 67 if a.configuration is not None: 68 assembly.configuration.settings.extend(a.configuration.settings) 69 70 # Ensure AST consistency. 71 assembly.composition.claim_children() 72 assembly.configuration.claim_children() 73 74 # Remove all other assemblies from AST. 75 ast.filter(lambda x: not isinstance(x, Assembly) or x is assembly) 76 77class Parse6(Transformer): 78 def precondition(self, ast_lifted, _): 79 return precondition(ast_lifted) 80 81 def postcondition(self, ast_lifted, _): 82 return postcondition(ast_lifted) 83 84 def transform(self, ast_lifted, read): 85 compose_assemblies(ast_lifted) 86 return ast_lifted, read 87