def is_valid_division(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if not tree.data == 'division': return False if not tree.children[0].data == 'number': raise exceptions.ValidationError('Tree prefix incorrect: ' + str(tree.data) + ' given, number expected.') if not tree.children[1].data == 'number': raise exceptions.ValidationError('Tree prefix incorrect: ' + str(tree.data) + ' given, number expected.') if not len(tree.children) == 2: raise exceptions.SemanticError('2 children expected, ' + len(tree.children[0].children) + ' given.') if not int(tree.children[0].children[0].value) > 0: raise exceptions.SemanticError('Positive/nonzero value needed for division numerator.') denom = int(tree.children[1].children[0].value) validDenoms = [1, 2, 4, 8, 16, 32, 64, 128] if denom not in validDenoms: raise exceptions.DivisionError('Division denominator must be power of 2.') return True
def is_valid_identifier(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if not tree.data == 'id': return False theID = tree.children[0] length = len(theID) if length < 2: raise exceptions.SemanticError('At least 2 children expected, ' + len(tree.children[0].children) + ' given.') if theID[0] != '$': raise exceptions.SemanticError('Identifier must begin with \'$\'') if not theID[1].isalpha(): raise exceptions.SemanticError('Identifier first non-$ must be alpha-non-numeric.') for i in range(2, length): idChar = theID[i] if not(idChar.isalnum() or idChar == '_' or idChar == '-'): raise exceptions.SemanticError('Identifier may only contain alphanumeric, _, and -.') return True
def _cmp(t): t1 = _typeof(t.children[0]) t2 = _typeof(t.children[1]) if t1.isInteger(): if t2 == t1: return BoolType() else: raise exceptions.SemanticError( Position.fromAny(t), f"Incompatible types: {str(t1)} and {str(t2)}") else: raise exceptions.SemanticError(Position.fromAny(t), f"Wrong arithmetic type: {str(t1)}")
def neg(self, tree): t = _typeof(tree.children[0]) if t.isInteger(): return t else: raise exceptions.SemanticError( Position.fromAny(tree), f"Wrong type for negation: {str(t)}")
def lnot(self, tree): t = _typeof(tree.children[0]) if t.isBool(): return BoolType() else: raise exceptions.SemanticError( Position.fromAny(tree), f"Wrong type for logical not: {str(t)}")
def addsub(tree, op, pattern): a, b = tree.children if isinstance(a, Tree) or isinstance(b, Tree): return tree if a.getIndirLevel() > 0 or b.getIndirLevel() > 0: return tree if a.getType().isPointer(): if not b.getType().isInteger(): raise exceptions.SemanticError( Position.fromAny(tree), f"Cannot add {str(b.getType())} to a pointer") else: if a.getType() != b.getType(): raise exceptions.SemanticError( Position.fromAny(tree), "Incompatible types in an expression") if not a.isConstNumber() or not b.isConstNumber(): if not a.getType().isPointer(): if a.getType().getSign(): print(str(a)) print(str(b)) raise exceptions.SemanticError(Position.fromAny(tree), "Signed label? WTF is that? 1") return Value(Position.fromAny(tree), a.getType(), 0, pattern.format(a.getSource(), b.getSource()), True) else: if b.isConstNumber() or not b.getType().getSign(): sb = signExpand(b.getType(), b.getSource()) memberSize = a.getType().deref().getReserveSize() return Value(Position.fromAny(tree), a.getType(), 0, pattern.format(a.getSource(), sb * memberSize), True) else: raise exceptions.SemanticError(Position.fromAny(tree), "Signed label? WTF is that? 2") elif not a.getType().isPointer(): newType = a.getType() sa = signExpand(a.getType(), a.getSource()) sb = signExpand(b.getType(), b.getSource()) return _const(Position.fromAny(tree), newType, op(sa, sb)) else: newType = a.getType() memberSize = a.getType().deref().getReserveSize() sa = signExpand(a.getType(), a.getSource()) sb = signExpand(b.getType(), b.getSource()) return _const(Position.fromAny(tree), newType, op(sa, sb * memberSize))
def land(self, tree): t0 = _typeof(tree.children[0]) t1 = _typeof(tree.children[1]) if t0.isBool() and t1.isBool(): return BoolType() else: raise exceptions.SemanticError( Position.fromAny(tree), f"Wrong types for logical and: {str(t0)}, {str(t1)}")
def ne(self, tree): t0 = _typeof(tree.children[0]) t1 = _typeof(tree.children[1]) if t0 == t1: return BoolType() else: raise exceptions.SemanticError( Position.fromAny(tree), f"Incompatible types: {str(t0)}, {str(t1)}")
def _shift(t): t1 = _typeof(t.children[0]) t2 = _typeof(t.children[1]) if t1.isInteger() and t2.isInteger(): return t1 else: raise exceptions.SemanticError( Position.fromAny(t), f"Wrong types for bit shift: {str(t1)} and {str(t2)}")
def note_to_signal(self, tree): if not self.is_valid_note(tree): raise exceptions.SemanticError(tree.data + ' given where note is expected.') signals = [] # this function loops through the note's children and fills # out the necessary fields when it finds them.` notesig = {'type': 'note', 'note_name':'', 'length_num':0, 'length_denom':0} chordsig = {'type': 'chord', 'notes':[], 'length_num':0, 'length_denom':0} restsig = {'type': 'rest', 'length_num':0, 'length_denom':0} num = 0 den = 0 for i in tree.children: # children of a note: division, notename, --, chord, tuple if i == "--": restsig['length_num'] = int(num) restsig['length_denom'] = int(den) signals.append(restsig) elif i.data == 'division': num = i.children[0].children[0] den = i.children[1].children[0] elif i.data == 'notename': notesig['note_name'] = self.collect_notename(i) notesig['length_num'] = int(num) notesig['length_denom'] = int(den) signals.append(notesig) elif i.data == "chord": chordsig['notes'] = self.chord_to_signal(i) chordsig['length_num'] = int(num) chordsig['length_denom'] = int(den) signals.append(chordsig) elif i.data == "tuple": tupleItems = self.tuple_to_signal(i) itemCount = len(tupleItems) newDen = int(den) * itemCount for item in tupleItems: if item['type'] == 'note': tnotesig = {'type': 'note', 'note_name':'', 'length_num':0, 'length_denom':0} tnotesig['note_name'] = item['value'] tnotesig['length_num'] = int(num) tnotesig['length_denom'] = newDen signals.append(tnotesig) elif item['type'] == 'chord': tchordsig = {'type': 'chord', 'notes':[], 'length_num':0, 'length_denom':0} tchordsig['notes'] = item['value'] tchordsig['length_num'] = int(num) tchordsig['length_denom'] = newDen signals.append(tchordsig) else: raise exceptions.SignalConversionError('Invalid note given.') return signals
def is_valid_noteitem(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if not tree.data == 'noteitem': return False if not len(tree.children) == 1: raise exceptions.SemanticError('1 child expected, ' + len(tree.children[0].children) + ' given.') item = tree.children[0].data if item == 'note': return Semantic.is_valid_note(self, tree.children[0]) elif item == 'id': return Semantic.is_valid_identifier(self, tree.children[0]) elif item == 'inlinedynamic': d = tree.children[0].children[0].lower() if d not in self.valid_levels: raise exceptions.DynamicError('Incorrect inline dynamic.') else: raise exceptions.SemanticError('Note, inline dynamic, or identifier expected, not given.') return True
def is_valid_note(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if tree.data != 'note': return False if len(tree.children[0].children) != 2: raise exceptions.SemanticError('2 children expected, ' + len(tree.children[0].children) + ' given.') if tree.children[0].data != 'division': raise exceptions.ValidationError('Tree prefix incorrect: ' + str(tree.data) + ' given, division expected.') if not self.is_valid_division(tree.children[0]): raise exceptions.SemanticError("Invalid Division") if type(tree.children[1]) == self.tokentype and tree.children[1].type == 'REST': return True if not self.is_valid_notename(tree.children[1]) and not self.is_valid_chord(tree.children[1]) and not self.is_valid_tuple(tree.children[1]): raise exceptions.SemanticError("Invalid notename or chord") return True
def is_valid_instrumentation(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if tree.data != 'instrumentation': return False if len(tree.children) < 1: raise exceptions.SemanticError('At least 1 child expected, ' + len(tree.children[0].children) + ' given.') child = tree.children if type(child[0]) == self.treetype: if not self.is_valid_identifier(child[0]): return False child[0] = self.variables[child[0].children[0]] if type(child[0]) != self.tokentype: raise exceptions.ValidationError('Type mismatch: ' + str(type(child[0])) + ' is not ' + str(self.tokentype) + '.') if child[0].type != 'INSTRUMENT': raise exceptions.ValidationError('Type mismatch: ' + child[0].type + ' is not INSTRUMENT.') for x in child[1:]: if not self.is_valid_noteitem(x): raise exceptions.SemanticError('Invalid Noteitem.') return True
def measure_to_signal(self, tree): if not self.is_valid_measure(tree): raise exceptions.SemanticError("Invalid measure") return [] signals = [] signals.append({'type':'measure', 'start':True}) for i in tree.children: if i.data == 'instrumentation': signals += self.instrumentation_to_signal(i) signals.append({'type':'measure', 'start':False}) return signals
def chord_to_signal(self, tree): if tree.data != 'chord': raise exceptions.SemanticError(tree.data + ' given where chord is expected.') notes = [] for i in tree.children: # only children of a chord are notenames if i.data == 'notename': notes.append(self.collect_notename(i)) else: raise exceptions.SignalConversionError('Invalid chord contents.') return notes
def is_valid_chord(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if not tree.data == 'chord': return False try: for child in tree.children: if not child.data == 'notename': return False if not self.is_valid_notename(child): raise SemanticError except: raise exceptions.SemanticError('Chords should only contain notes.') return True
def binary(tree, op, overrideType=None, typeChecker=sameTypeChecker): a, b = tree.children if isinstance(a, Tree) or isinstance(b, Tree): return tree elif not a.isConstNumber() or not b.isConstNumber(): return tree else: if typeChecker(a, b): newType = a.getType() if overrideType is not None: newType = overrideType sa = signExpand(a.getType(), a.getSource()) sb = signExpand(b.getType(), b.getSource()) return _const(Position.fromAny(tree), newType, op(sa, sb)) else: raise exceptions.SemanticError( Position.fromAny(tree), "Incompatible types in an expression")
def tuple_to_signal(self, tree): if tree.data != 'tuple': raise exceptions.SemanticError(tree.data + ' given where tuple is expected.') # put dummy data in a tuple signal because we don't like them much notes = [] for i in tree.children: if i.data == 'notename': notes.append({'type' : 'note', 'value' : self.collect_notename(i)}) elif i.data == 'chord': notes.append({'type' : 'chord', 'value' : self.chord_to_signal(i)}) else: raise exceptions.SignalConversionError('Invalid tuple contents.') return notes
def is_valid_dynamic(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if tree.data != 'dynamic': return False item = tree.children[0].data if item == 'inlinedynamic': d = tree.children[0].children[0].lower() if d not in self.valid_levels: raise exceptions.DynamicError('Incorrect inline dynamic.') elif item == 'id': return Semantic.is_valid_identifier(self, tree) else: raise exceptions.SemanticError('Inline dynamic or identifier expected, not given.') return True
def noteitem_to_signal(self,tree): if not self.is_valid_noteitem(tree): raise exceptions.SemanticError(tree.data + ' given where noteitem is expected.') return False signals = [] for i in tree.children: # possible noteitem children : note , inlinedynamic if i.data == 'note': signals += (self.note_to_signal(i)) elif i.data == 'inlinedynamic': signals += (self.inlinedynamic_to_signal(i)) else: raise exceptions.SignalConversionError('Invalid noteitem given.') return signals
def instrumentation_to_signal(self, tree): if not self.is_valid_instrumentation(tree): raise exceptions.SemanticError(tree.data + ' given where instrumentation is expected.') signals = [] name = tree.children[0] signals.append({'type':'instrument', 'name':str(name)}) if tree.children[0] in instrumentToNumber: for i in tree.children[1:]: signals += self.noteitem_to_signal(i) else: raise exceptions.SignalConversionError('Invalid instrument given.') return signals
def is_valid_tree(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if tree.data != 'start': return False for i in range(len(tree.children[:-1])): if tree.children[i].data == 'id': if tree.children[i+1].data != 'rhs': raise exceptions.ValidationError('Assignment right-hand side not found.') if tree.children[i].data == 'rhs': if tree.children[i-1].data != 'id': raise exceptions.ValidationError('Assignment identifier not found.') if tree.children[-1].data != 'compose': raise exceptions.SemanticError('Compose statement not found.') return True
def is_valid_notename(self, tree): if not type(tree) is self.treetype: raise exceptions.ValidationError('Type mismatch: ' + str(type(tree)) + ' is not ' + str(self.treetype) + '.') if not tree.data == 'notename': return False if not (len(tree.children) == 3 or len(tree.children) == 2): raise exceptions.SemanticError('2 or 3 children expected, ' + len(tree.children[0].children) + ' given.') n = tree.children[0] n.upper() validNoteLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G'] if n not in validNoteLetters: raise exceptions.NoteError('Invalid note letter.') if len(tree.children) == 3: #Has accidental if tree.children[1].data != 'accidental': raise exceptions.NoteError('Accidental expected, not given.') if tree.children[2].data != 'number': raise exceptions.NoteError('Octave number expected, not given') acc = tree.children[1].children[0].value if acc != '#' and acc != 'b': raise exceptions.NoteError('Incorrect accidental symbol given, \'b\' or \'#\' expected.') octave = int(tree.children[2].children[0].value) if 9 > octave < 0: raise exceptions.NoteError('Invalid note octave.') elif len(tree.children) == 2: #No accidental or rest if tree.children[1].data != 'number': raise exceptions.NoteError('Octave number expected, not given') octave = int(tree.children[1].children[0].value) if 9 > octave < 0: raise exceptions.NoteError('Invalid note octave.') else: #Invalid length raise exceptions.NoteError('Invalid note syntax') return False return True
def is_valid_program(self, tree): if not type(tree) is self.treetype: raise exceptions.SemanticError("Not a tree")
def p_arrow(self, tree): try: ts = _typeof(tree.children[0]) return PtrType(ts.deref().getFieldType(tree.children[1])) except LookupError as e: raise exceptions.SemanticError(Position.fromAny(tree), str(e))