def _parse(self, usrStr): # divide all groups into pairs of key, {}-enclosed values # all elements of notation are <key>{<value>} pairs # this notation has two types: symbol definitions and weight definitions # symbol defs: keys are alphabetic, values can be anything (incl lists) # name{symbol} # weight defs: keys are source transitions statments w/ step indicator : # transition{name=weight|name=weight} # support for limited regular expressions in weight defs # t:*:t match any one in the second palce; not e same as zero or more # t:-t:t match anything that is not t # t:w|q:t match either (alternation) # note: this will remove all spaces in all keys and all values self._parseValidate(usrStr) usrStr = self._parseClean(usrStr) pairSymbol = {} pairWeight = {} groups = usrStr.split(self.CLOSE) for double in groups: if self.OPEN not in double: continue try: key, value = double.split(self.OPEN) except: # possible syntax error in formationi raise error.TransitionSyntaxError, "badly placed delimiters" # key is always a symbol def: will change case and remove spaces key = drawer.strScrub(key, 'lower', [' ']) # rm spaces from key # split into 2 dictionaries, one w/ symbol defs, one w/ weights # if it is or has a step indicator (:), it is not a def if self.STEP in key or self.ASSIGN in value: # it is a weight # store weights values in lower self._checkSymbolFormWeightKey(key) pairWeight[key] = drawer.strScrub(value, 'lower', [' ']) else: # must be a symbol def self._checkSymbolFormDef( key) # will raise exception on bad key pairSymbol[key] = drawer.strScrub(value, None, [' ']) # this initializes symbol table if pairSymbol == {}: raise error.TransitionSyntaxError, "no symbols defined" self._symbols = pairSymbol # pass the pair dictionary to weight parser if pairWeight == {}: raise error.TransitionSyntaxError, "no weights defined" self._parseWeightValue(pairWeight) # check symbol usage and determine orders self._checkSymbolUsage()
def _parse(self, usrStr): # divide all groups into pairs of key, {}-enclosed values # all elements of notation are <key>{<value>} pairs # this notation has two types: symbol definitions and weight definitions # symbol defs: keys are alphabetic, values can be anything (incl lists) # name{symbol} # weight defs: keys are source transitions statments w/ step indicator : # transition{name=weight|name=weight} # support for limited regular expressions in weight defs # t:*:t match any one in the second palce; not e same as zero or more # t:-t:t match anything that is not t # t:w|q:t match either (alternation) # note: this will remove all spaces in all keys and all values self._parseValidate(usrStr) usrStr = self._parseClean(usrStr) pairSymbol = {} pairWeight = {} groups = usrStr.split(self.CLOSE) for double in groups: if self.OPEN not in double: continue try: key, value = double.split(self.OPEN) except: # possible syntax error in formationi raise error.TransitionSyntaxError, "badly placed delimiters" # key is always a symbol def: will change case and remove spaces key = drawer.strScrub(key, 'lower', [' ']) # rm spaces from key # split into 2 dictionaries, one w/ symbol defs, one w/ weights # if it is or has a step indicator (:), it is not a def if self.STEP in key or self.ASSIGN in value: # it is a weight # store weights values in lower self._checkSymbolFormWeightKey(key) pairWeight[key] = drawer.strScrub(value, 'lower', [' ']) else: # must be a symbol def self._checkSymbolFormDef(key) # will raise exception on bad key pairSymbol[key] = drawer.strScrub(value, None, [' ']) # this initializes symbol table if pairSymbol == {}: raise error.TransitionSyntaxError, "no symbols defined" self._symbols = pairSymbol # pass the pair dictionary to weight parser if pairWeight == {}: raise error.TransitionSyntaxError, "no weights defined" self._parseWeightValue(pairWeight) # check symbol usage and determine orders self._checkSymbolUsage()
def pmtrNameToPmtrLib(pmtrName): """For a given PO name, return the appropriate library key. Return None if no match >>> pmtrNameToPmtrLib('ru') 'genPmtrObjs' >>> pmtrNameToPmtrLib('basketgen') 'genPmtrObjs' >>> pmtrNameToPmtrLib('filterDivideAnchor') 'filterPmtrObjs' >>> pmtrNameToPmtrLib('ru,0,1') # permit accepting full definitons 'genPmtrObjs' """ pmtrName = drawer.strScrub(pmtrName, 'lower', rm=[' ']) if ',' in pmtrName: # if a comma pmtrName = pmtrName.split(',')[0] # just get first, strip args found = None for libName in list(pmtrLibNames.values()): pmtrNamesDict = pmtrLibNameToDict(libName) for key, value in list(pmtrNamesDict.items()): if pmtrName == key.lower() or pmtrName == value.lower(): found = libName break return found
def factory(request): # all will get all ouput formats if drawer.isStr(request): request = drawer.strScrub(request, 'L') if request == 'all': request = outputFormatNames.values() # if other string given, add to a list else: request = [request] # load objects reqArray = [] for name in request: name = outputFormatParser(name) if name == None: continue # user strings have lower case first char w/ format prefix className = 'Format' + name[0].upper() + name[1:] # get module attribute for class modAttr = globals()[className] reqArray.append(modAttr()) if len(reqArray) == 1: return reqArray[0] else: return reqArray
def pmtrNameToPmtrLib(pmtrName): """For a given PO name, return the appropriate library key. Return None if no match >>> pmtrNameToPmtrLib('ru') 'genPmtrObjs' >>> pmtrNameToPmtrLib('basketgen') 'genPmtrObjs' >>> pmtrNameToPmtrLib('filterDivideAnchor') 'filterPmtrObjs' >>> pmtrNameToPmtrLib('ru,0,1') # permit accepting full definitons 'genPmtrObjs' """ pmtrName = drawer.strScrub(pmtrName, 'lower', rm=[' ']) if ',' in pmtrName: # if a comma pmtrName = pmtrName.split(',')[0] # just get first, strip args found = None for libName in pmtrLibNames.values(): pmtrNamesDict = pmtrLibNameToDict(libName) for key, value in pmtrNamesDict.items(): if pmtrName == key.lower() or pmtrName == value.lower(): found = libName break return found
def factory(request): # all will get all ouput formats if drawer.isStr(request): request = drawer.strScrub(request, 'L') if request == 'all': request = list(outputFormatNames.values()) # if other string given, add to a list else: request = [request] # load objects reqArray = [] for name in request: name = outputFormatParser(name) if name == None: continue # user strings have lower case first char w/ format prefix className = 'Format' + name[0].upper() + name[1:] # get module attribute for class modAttr = globals()[className] reqArray.append(modAttr()) if len(reqArray) == 1: return reqArray[0] else: return reqArray
def _guessType(self): """try to determine what kind of pitch data is being provided psReal is default for any integer midi values must be marked some other way (w/ an m?) """ data = copy.copy(self.srcData) if drawer.isStr(data): data = drawer.strScrub(data, 'L') if len(data) == 0: return None # no data found if data[0] in REFdiaNameToPc: return 'psName' elif data.find('m') >= 0 or data.find('midi') >= 0: # an m designates a midi note number return 'midi' elif data.find('pch') >= 0: # a pch designates a pch value return 'pch' elif data.find('hz') >= 0 or data.find('fq') >= 0: return 'fq' else: # assume other strings are psInts return 'psReal' if drawer.isInt(data): # midi int, or ps int return 'psReal' if drawer.isFloat(data): # assume it is a psReal value return 'psReal'
def _parseSetInputType(self, usrStr, termObj): """determine which set input is being provided by user termObj may be None; if not interactive, not allow import """ usrStr = drawer.strScrub(usrStr, 'L') for char in usrStr: if char in ['@','&', '|',]: # removed ,'(',')' return 'sieve' # if a complete user string, get a file dialog if usrStr in ['file', 'import', 'spectrum']: if not termObj.interact: return None # cant import w/ not interactive return 'import' if usrStr.find('.txt') >= 0: # assume its a file path return 'txt' # import a spectrum if usrStr.find('m') >= 0: return 'midi' if usrStr.find('hz') >= 0 or usrStr.find('fq') >= 0: return 'fq' # the first character of a set class must always be a number # 10, 11, and 12 should be in this list, but requires two characters # there must be a dash (not leading), no comas, no periods, if (usrStr[0] in ['1','2','3','4','5','6','7','8','9',] and usrStr.find('-') != -1 and usrStr.find(',') == -1 and usrStr.find('.') == -1 and usrStr[0] != '-'): # no other characters should be in this return 'forte' else: for char in usrStr.lower(): # check if it has characters if char in pitchTools.REFdiaNameToPc.keys(): return 'psName' return 'psReal' # assume pset numbers
def decodePmtrName(self, usrStr, style='cmd'): """translates user string to proper parameter key style = cmd uses parenthesis to show command name str provides simples string usr provides aux/text numbers w/ aprop shift >>> a = Clone() >>> a.decodePmtrName('c') ('acc', 'a(c)cent') """ if usrStr == None: return None, '' p = drawer.strScrub(usrStr, 'lower') refNo = None # only used for aux, texture if p in ( 't', 'time', ): attrName = 'time' label = '(t)ime' elif p in ('u', 'sustain', 'sus'): attrName = 'sus' label = 's(u)stain' elif p in ('c', 'accent', 'acc'): attrName = 'acc' label = 'a(c)cent' elif p in ('f', 'field', 'fieldq'): attrName = 'fieldQ' label = 'local (f)ield' elif p in ('o', 'oct', 'octq'): attrName = 'octQ' label = 'local (o)ctave' elif p in ('a', 'amp', 'ampq'): attrName = 'ampQ' label = '(a)mplitude' elif p in ('n', 'pan', 'panq'): attrName = 'panQ' label = 'pan(n)ing' elif p[:1] == 'x' or p[:3] == 'aux': strNum, strLet = drawer.strExtractNum(p) attrName = 'auxQ' + strNum label = 'au(x)iliary' refNo = self._pmtrNumberToUsr(strNum, 0, style) elif p[:1] == 's' or p[:1] == 'c' or p[:5] == 'clone': strNum, strLet = drawer.strExtractNum(p) attrName = 'cloneQ' + p[1:] label = 'clone (s)tatic' refNo = self._pmtrNumberToUsr(strNum, 0, style) else: attrName = None label = '' if style == 'cmd': # leave parenthesis in names pass elif style in ['str', 'usr']: # remove parenthesis label = label.replace('(', '') label = label.replace(')', '') if style == 'usr' and refNo != None: label = '%s %s' % (label, refNo) return attrName, label
def decodePmtrName(self, usrStr, style='cmd'): """translates user string to proper parameter key style = cmd uses parenthesis to show command name str provides simples string usr provides aux/text numbers w/ aprop shift >>> a = Clone() >>> a.decodePmtrName('c') ('acc', 'a(c)cent') """ if usrStr == None: return None, '' p = drawer.strScrub(usrStr, 'lower') refNo = None # only used for aux, texture if p in ('t', 'time',): attrName = 'time' label = '(t)ime' elif p in ('u', 'sustain', 'sus'): attrName = 'sus' label = 's(u)stain' elif p in ('c', 'accent', 'acc'): attrName = 'acc' label = 'a(c)cent' elif p in ('f', 'field', 'fieldq'): attrName = 'fieldQ' label = 'local (f)ield' elif p in ('o', 'oct', 'octq'): attrName = 'octQ' label = 'local (o)ctave' elif p in ('a', 'amp', 'ampq'): attrName = 'ampQ' label = '(a)mplitude' elif p in ('n', 'pan', 'panq'): attrName = 'panQ' label = 'pan(n)ing' elif p[:1] == 'x' or p[:3] == 'aux': strNum, strLet = drawer.strExtractNum(p) attrName = 'auxQ' + strNum label = 'au(x)iliary' refNo = self._pmtrNumberToUsr(strNum, 0, style) elif p[:1] == 's' or p[:1] == 'c' or p[:5] == 'clone': strNum, strLet = drawer.strExtractNum(p) attrName = 'cloneQ' + p[1:] label = 'clone (s)tatic' refNo = self._pmtrNumberToUsr(strNum, 0, style) else: attrName = None label = '' if style == 'cmd': # leave parenthesis in names pass elif style in ['str', 'usr']: # remove parenthesis label = label.replace('(','') label = label.replace(')', '') if style == 'usr' and refNo != None: label = '%s %s' % (label, refNo) return attrName, label
def convertBoolCancel(usrData): """converts arg strings: on, off, or cancel or numbers 0, 1 get strings from language; check english for preferences >>> convertBoolCancel('y') 1 >>> convertBoolCancel('no') 0 >>> convertBoolCancel(-1) -1 """ if drawer.isNum(usrData): usrStr = str(int(round(usrData))) else: usrStr = drawer.strScrub(usrData, 'L') if usrStr == '': return None # off if (usrStr in ['0', lang.OFF.lower(), lang.NO.lower(), lang.FALSE.lower()] or usrStr[0] == lang.NO[0].lower()): return 0 if len(usrStr) >= len(lang.OFF): if usrStr[-len(lang.OFF):] == lang.OFF.lower(): return 0 if len(usrStr) >= 3: # check literal english if usrStr[-3:] == 'off': return 0 # on if (usrStr in ['1', lang.ON.lower(), lang.YES.lower(), lang.TRUE.lower()] or usrStr[0] == lang.YES[0].lower()): return 1 if len(usrStr) >= len(lang.ON): if usrStr[-len(lang.ON):] == lang.ON.lower(): return 1 if len(usrStr) >= 2: # check literal english if usrStr[-2:] == 'on': return 1 # cancel if (usrStr in ['-1', lang.CANCEL.lower(), lang.BREAK.lower()] or usrStr[0] == lang.CANCEL[0].lower()): return -1 # if no match return None return None
def _parsePsName(self, usrStr): """convert a list of pitch names to a ps middle c == c4 == midi 60 == 0 """ #usrStr = self._scrubUsrStr(usrStr) usrList = drawer.strToListFlat(usrStr, 'L') psList = [] for elem in usrList: # may be int or float elem = drawer.strScrub(elem) if elem == '': continue elif elem[0] not in list(pitchTools.REFdiaNameToPc.keys()): continue else: # this should never raise an error psList.append(pitchTools.psNameToPs(elem)) return psList
def _parsePsName(self, usrStr): """convert a list of pitch names to a ps middle c == c4 == midi 60 == 0 """ #usrStr = self._scrubUsrStr(usrStr) usrList = drawer.strToListFlat(usrStr, 'L') psList = [] for elem in usrList: # may be int or float elem = drawer.strScrub(elem) if elem == '': continue elif elem[0] not in pitchTools.REFdiaNameToPc.keys(): continue else: # this should never raise an error psList.append(pitchTools.psNameToPs(elem)) return psList
def pmtrTypeParser(typeName, libName='genPmtrObjs'): """utility functions for parsing user paramter strings into proper parameter names. accepts short names and long names, regardless of case does not raise an error if no match: returns string unmodified parameters can have the same abbreviation if they are in different libraries >>> pmtrTypeParser('ru', 'genPmtrObjs') 'randomUniform' >>> pmtrTypeParser('ru', None) 'randomUniform' >>> pmtrTypeParser('gr', None) 'gaRhythm' """ if typeName == None: raise Exception('got a type name of none') #print _MOD, 'pmtrTypeParser', typeName, libName usrStr = drawer.strScrub(typeName, 'lower') # get all parameter names in a dictionary if libName == 'genPmtrObjs': pmtrNames = genPmtrNames elif libName == 'rthmPmtrObjs': pmtrNames = rthmPmtrNames elif libName == 'textPmtrObjs': pmtrNames = textPmtrNames elif libName == 'clonePmtrObjs': pmtrNames = clonePmtrNames elif libName == 'filterPmtrObjs': pmtrNames = filterPmtrNames elif libName == None: pmtrNames = allPmtrNames else: raise error.ParameterObjectSyntaxError( 'no parameter library named: %r' % libName) for key in list(pmtrNames.keys()): className = pmtrNames[key] if usrStr == key: return className elif usrStr == className.lower(): return className # if not mattched, raise an error raise error.ParameterObjectSyntaxError('no parameter named %r in %s' % (usrStr, pmtrLibTitle(libName)))
def _pmtrNumberToUsr(self, pmtr, shift, style='str'): """convert a parameter number string into data numbers are returned as numbers, strings as strings str, and cmd produce un-altered numbers usr wil shift by appropriate values""" if drawer.isNum(pmtr): if style in ['str', 'cmd']: return pmtr elif style == 'usr': return pmtr + shift if drawer.isStr(pmtr): if style in ['str', 'cmd']: return pmtr elif style == 'usr': pmtr = drawer.strScrub(pmtr, 'lower') pmtr = pmtr.replace('q', '') return str(int(pmtr) + shift)
def pmtrTypeParser(typeName, libName='genPmtrObjs'): """utility functions for parsing user paramter strings into proper parameter names. accepts short names and long names, regardless of case does not raise an error if no match: returns string unmodified parameters can have the same abbreviation if they are in different libraries >>> pmtrTypeParser('ru', 'genPmtrObjs') 'randomUniform' >>> pmtrTypeParser('ru', None) 'randomUniform' >>> pmtrTypeParser('gr', None) 'gaRhythm' """ if typeName == None: raise Exception('got a type name of none') #print _MOD, 'pmtrTypeParser', typeName, libName usrStr = drawer.strScrub(typeName, 'lower') # get all parameter names in a dictionary if libName == 'genPmtrObjs': pmtrNames = genPmtrNames elif libName == 'rthmPmtrObjs': pmtrNames = rthmPmtrNames elif libName == 'textPmtrObjs': pmtrNames = textPmtrNames elif libName == 'clonePmtrObjs': pmtrNames = clonePmtrNames elif libName == 'filterPmtrObjs': pmtrNames = filterPmtrNames elif libName == None: pmtrNames = allPmtrNames else: raise error.ParameterObjectSyntaxError, 'no parameter library named: %r' % libName for key in pmtrNames.keys(): className = pmtrNames[key] if usrStr == key: return className elif usrStr == className.lower(): return className # if not mattched, raise an error raise error.ParameterObjectSyntaxError, 'no parameter named %r in %s' % (usrStr, pmtrLibTitle(libName))
def getNoteNameFromPercName(percStr): "for a given percussion name, find what note name is needed" foundName = None percStr = drawer.strScrub(percStr, 'L') for name in gmPercussionNames.keys(): if percStr == name.lower(): foundName = name break if foundName == None: # check again for partial matches for name in gmPercussionNames.keys(): name = name.lower() if name.find(percStr) >= 0: foundName = name break if foundName == None: print _MOD, 'cant find:', percStr midiInt = gmPercussionNames[foundName] noteName = pitchTools.midiToNoteName(midiInt) return noteName # may be None on error
def findCloneStaticLabel(self, usrStr): """find proper label for clone static options >>> a = Clone() """ if usrStr not in self.cloneLabels: # try to match by parameter obj name usrStr = drawer.strScrub(usrStr, 'lower') for key in parameter.clonePmtrNames.keys(): # keys are short if usrStr == key: # get long name usrStr = parameter.clonePmtrNames[key] break found = 0 # check for parameter names for key in self.cloneLabels: if usrStr.lower() == self.pmtrObjDict[key].type.lower(): usrStr = key found = 1 break if not found: raise ValueError, 'bad label name for clone pmtr data: %s' % usrStr return usrStr
def getPgmNumber(usrStr): if usrStr == '': return None try: numVal = int(usrStr) except (ValueError, TypeError): numVal = -1 if numVal >= 0: # its a number, try to use return getPgmName(numVal), numVal # its a string usrStr = drawer.strScrub(usrStr, 'L') scoreDict = {} for name in gmProgramNames.keys(): nameTest = name.lower() scoreDict[name] = nameTest.count(usrStr) # counts instances best = ('', 0) # name, score # go basck over items; name does have case for name, score in scoreDict.items(): if score > best[1]: best = (name, score) if best[0] == '': # nothing found return None else: return best[0], gmProgramNames[best[0]] # name, pgmNum
def _parse(self, usrStr): ''' >>> g = Grammar() >>> g._parse('a{3}b{4} @ a{b}b{a|b}') >>> g._parse('a{3}b{4} @ a{b}b{a|b|c}') Traceback (most recent call last): TransitionSyntaxError: destination rule component ([('a', 1), ('b', 1), ('c', 1)]) references an undefined symbol >>> g._parse('a{3}b{4}c{3} @ a{b}b{a|b|c}') >>> g._parse('a{3}b{4}c{3} @ a{b}d{a|b|c}') Traceback (most recent call last): TransitionSyntaxError: source rule component (d) references an undefined symbol >>> g._symbols {'a': '3', 'c': '3', 'b': '4'} >>> g._parse('a{3}b{4}c{3} @ a{bb}b{aa|b|c}') >>> g._symbols {'a': '3', 'c': '3', 'b': '4'} >>> g._rules {'a': [('bb', 1)], 'b': [('aa', 1), ('b', 1), ('c', 1)]} >>> g._parse('a{3}b{4} @ a{b}b{a|b} @ b') >>> g._axiom 'b' >>> g._parse('a{3}b{4} @ a{b}b{a|b} @ baab') >>> g._axiom 'baab' >>> g._parse('a{3}b{4} @ a{b}ac{a|b} @ baab') Traceback (most recent call last): TransitionSyntaxError: source rule component (ac) references an undefined symbol >>> g._parse('a{3}b{4} @ *{b} @ baab') # * can be source, not dst >>> g._parse('a{3}b{4} @ a{*} @ baab') # * cannot be destination Traceback (most recent call last): TransitionSyntaxError: destination rule component ([('*', 1)]) references an undefined symbol ''' # divide all groups into pairs of key, {}-enclosed values # all elements of notation are <key>{<value>} pairs self._parseValidate(usrStr) usrStr = self._parseClean(usrStr) pairSymbol = {} pairRule = {} if usrStr.count(self.SPLIT) not in [1, 2]: # must be 1 or 2 raise error.TransitionSyntaxError("must include exactly one split delimiter (%s)" % self.SPLIT) if usrStr.count(self.SPLIT) == 1: partSymbol, partRule = usrStr.split(self.SPLIT) partAxiom = None elif usrStr.count(self.SPLIT) == 2: # split into three partSymbol, partRule, partAxiom = usrStr.split(self.SPLIT) for subStr, dst in [(partSymbol, 'symbol'), (partRule, 'rule')]: groups = subStr.split(self.CLOSE) for double in groups: if self.OPEN not in double: continue try: key, value = double.split(self.OPEN) except: # possible syntax error in formationi raise error.TransitionSyntaxError("badly placed delimiters") # key is always a symbol def: will change case and remove spaces key = drawer.strScrub(key, 'lower', [' ']) # rm spaces from key # split into 2 dictionaries, one w/ symbol defs, one w/ rules # symbol defs must come before if dst == 'symbol': self._checkSymbolFormDef(key) # will raise exception on bad key pairSymbol[key] = drawer.strScrub(value, None, [' ']) elif dst == 'rule': self._checkSymbolFormRuleKey(key) pairRule[key] = drawer.strScrub(value, 'lower', [' ']) # this initializes symbol table if pairSymbol == {}: raise error.TransitionSyntaxError("no symbols defined") self._symbols = pairSymbol # pass the pair dictionary to weight parser if pairRule == {}: raise error.TransitionSyntaxError("no rules defined") self._parseRuleValue(pairRule) # assigns to self._rules # check symbol usage and determine orders self._checkRuleReference() # assigns axiom value self._parseAxiom(partAxiom)
def _parse(self, usrStr): ''' >>> g = Grammar() >>> g._parse('a{3}b{4} @ a{b}b{a|b}') >>> g._parse('a{3}b{4} @ a{b}b{a|b|c}') Traceback (most recent call last): TransitionSyntaxError: destination rule component ([('a', 1), ('b', 1), ('c', 1)]) references an undefined symbol >>> g._parse('a{3}b{4}c{3} @ a{b}b{a|b|c}') >>> g._parse('a{3}b{4}c{3} @ a{b}d{a|b|c}') Traceback (most recent call last): TransitionSyntaxError: source rule component (d) references an undefined symbol >>> g._symbols {'a': '3', 'c': '3', 'b': '4'} >>> g._parse('a{3}b{4}c{3} @ a{bb}b{aa|b|c}') >>> g._symbols {'a': '3', 'c': '3', 'b': '4'} >>> g._rules {'a': [('bb', 1)], 'b': [('aa', 1), ('b', 1), ('c', 1)]} >>> g._parse('a{3}b{4} @ a{b}b{a|b} @ b') >>> g._axiom 'b' >>> g._parse('a{3}b{4} @ a{b}b{a|b} @ baab') >>> g._axiom 'baab' >>> g._parse('a{3}b{4} @ a{b}ac{a|b} @ baab') Traceback (most recent call last): TransitionSyntaxError: source rule component (ac) references an undefined symbol >>> g._parse('a{3}b{4} @ *{b} @ baab') # * can be source, not dst >>> g._parse('a{3}b{4} @ a{*} @ baab') # * cannot be destination Traceback (most recent call last): TransitionSyntaxError: destination rule component ([('*', 1)]) references an undefined symbol ''' # divide all groups into pairs of key, {}-enclosed values # all elements of notation are <key>{<value>} pairs self._parseValidate(usrStr) usrStr = self._parseClean(usrStr) pairSymbol = {} pairRule = {} if usrStr.count(self.SPLIT) not in [1, 2]: # must be 1 or 2 raise error.TransitionSyntaxError( "must include exactly one split delimiter (%s)" % self.SPLIT) if usrStr.count(self.SPLIT) == 1: partSymbol, partRule = usrStr.split(self.SPLIT) partAxiom = None elif usrStr.count(self.SPLIT) == 2: # split into three partSymbol, partRule, partAxiom = usrStr.split(self.SPLIT) for subStr, dst in [(partSymbol, 'symbol'), (partRule, 'rule')]: groups = subStr.split(self.CLOSE) for double in groups: if self.OPEN not in double: continue try: key, value = double.split(self.OPEN) except: # possible syntax error in formationi raise error.TransitionSyntaxError( "badly placed delimiters") # key is always a symbol def: will change case and remove spaces key = drawer.strScrub(key, 'lower', [' ']) # rm spaces from key # split into 2 dictionaries, one w/ symbol defs, one w/ rules # symbol defs must come before if dst == 'symbol': self._checkSymbolFormDef( key) # will raise exception on bad key pairSymbol[key] = drawer.strScrub(value, None, [' ']) elif dst == 'rule': self._checkSymbolFormRuleKey(key) pairRule[key] = drawer.strScrub(value, 'lower', [' ']) # this initializes symbol table if pairSymbol == {}: raise error.TransitionSyntaxError("no symbols defined") self._symbols = pairSymbol # pass the pair dictionary to weight parser if pairRule == {}: raise error.TransitionSyntaxError("no rules defined") self._parseRuleValue(pairRule) # assigns to self._rules # check symbol usage and determine orders self._checkRuleReference() # assigns axiom value self._parseAxiom(partAxiom)