def DivideCV(self): """Divide the word among C and V groups to fill the sylBounds list. Here, and here alone, we need to catch e-with-grave-accent to count it as not only a vowel but syllabic ('an aged man' vs. 'aged beef'). Other special characters might be useful to recognize, but won't make the same syllabic difference. """ unicodeVowels = u"[ae\N{LATIN SMALL LETTER E WITH GRAVE}iouy]+" uniConsonants = u"[^ae\N{LATIN SMALL LETTER E WITH GRAVE}iouy]+" firstvowel = sre.search(unicodeVowels, self.wd).start() for v in sre.finditer(unicodeVowels, self.wd): lastvowel = v.end() # replaced for each group, last sticks disyllabicvowels = self.sylvowels.search(v.group()) if disyllabicvowels: self.sylBounds.append(v.start() + disyllabicvowels.start() + 1) for cc in sre.finditer(uniConsonants, self.wd): if cc.start() < firstvowel or cc.end() >= lastvowel: continue numcons = len(cc.group()) if numcons < 3: pos = cc.end() - 1 # before single C or betw. 2 elif numcons > 3: pos = cc.end() - 2 # before penult C else: # 3 consonants, divide 1/2 or 2/1? cg = cc.group() # our CCC cluster if cg[-3] == cg[-2] or self.splitLeftPairs.search(cg): pos = cc.end() - 2 # divide 1/2 else: pos = cc.end() - 1 # divide 2/1 if not self.wd[pos-1].isalpha() and not self.wd[pos].isalpha(): self.sylBounds.append(pos-1) else: self.sylBounds.append(pos)
def TestLengthAndDice(self, logger): normlen = (self.LD.data['lfeet'] - len(self.LD.data['footlist'])) * 2 if self.LD.data['lastfoot']: normlen -= 2 start = self.LD.data['midremain'][0] end = self.LD.data['midremain'][1] currlen = end - start logger.ExpFootDivision(currlen, normlen) marks = self.P.GetMarks() if currlen == normlen: for (footname, sylinx) \ in footfinder(footDict, marks, 2, start, end): if footname: self.LD.appendFoot(footname) else: return self.P.GetScanString(), False if sylinx < end: # not at end of line or where lastfoot starts self.P.AddFootDivMark(sylinx + self.LD.data['midremain'][0]) elif currlen < normlen: candidate = marks.find('x//', start, end) if candidate % 2 != 0: # 'x//' at odd pos hopelessly messy logger.Explain("\nFAIL! no good position " + "for single-stress foot") return self.P.GetScanString(), False candidate += 2 # point directly at defective foot for (footname, sylinx) \ in footfinder(footDict, marks, 2, start, candidate): if footname: self.LD.appendFoot(footname) else: return self.P.GetScanString(), False self.P.AddFootDivMark(sylinx) self.LD.appendFoot('defective') self.P.AddFootDivMark(candidate+1) for (footname, sylinx) \ in footfinder(footDict, marks, 2, candidate+1, end): if footname: self.LD.appendFoot(footname) else: return self.P.GetScanString(), False if sylinx < end: self.P.AddFootDivMark(sylinx) else: # anapest(s) need = currlen - normlen candidates = [p.start()+1 for p in sre.finditer(r'(?=/xx/)',marks)] if len(candidates) < need: morecands = [p.start() for p in sre.finditer(r'(?=xx/)',marks)] candidates += morecands while start < end: if need and (start in candidates): foot = marks[start:start+3] if footDict.has_key(foot): self.LD.appendFoot(footDict[foot]) else: return self.P.GetScanString(), False start += 3 need -= 1 else: foot = marks[start:start+2] if footDict.has_key(foot): self.LD.appendFoot(footDict[foot]) else: return self.P.GetScanString(), False start += 2 if start < end: self.P.AddFootDivMark(start) if self.LD.data['lastfoot']: self.LD.appendFoot(self.LD.data['lastfoot']) return self.P.GetScanString(), True
def depend(self, filename): if filename != '-': fp = open(filename, "r") body = fp.read() fp.close() else: body = sys.stdin.read() pass files = [filename] for ssi in re.finditer("<!--#(\w+)\s+(.*)\s*-->", body): element = ssi.expand("\\1") attrs = self.__parse_attribute(ssi.expand("\\2")) if element == "include": l = self.depend(os.path.normpath(self.document_root + attrs["virtual"])) files.append(l) elif element == "set": value = self.__interpolate_variable(attrs["value"]) self.variables.update({attrs["var"]: value}) elif element == "echo": pass else: print >>sys.stderr, "Unsupported SSI element", element, "in", body[ssi.start():ssi.end()] raise AttributeButton pass return (files)
def __interpolate_variables(self, name): s = "" _last = 0 for l in re.finditer("\${(\w+)}|\$(\w+)", name): s += name[_last:l.start()] v = filter(lambda x: x != None, l.groups()) v = v[0] s += self.variables[v] _last = l.end() pass s += name[_last:] return (s)
def parse(self, filename): if filename != '-': fp = open(filename, "r") body = fp.read() fp.close() else: body = sys.stdin.read() pass _last = 0 output = "" #matches = re.findall("<!--#(\w+)\s+(.*)\s*-->", body) #for ssi in matches: for ssi in re.finditer("<!--#(\w+)\s+(.*)\s*-->", body): output += body[_last:ssi.start()] element = ssi.expand("\\1") attrs = self.__parse_attribute(ssi.expand("\\2")) if element == "include": output += self.parse(os.path.normpath(self.document_root + attrs["virtual"])) elif element == "set": value = self.__interpolate_variables(attrs["value"]) self.variables.update({attrs["var"]: value}) elif element == "echo": output += self.__interpolate_variables(attrs["var"]) else: print >>sys.stderr, "Unsupported SSI element", element, "in", body[ssi.start():ssi.end()] raise AttributeError _last = ssi.end() pass output += body[_last:] return (output)
def DoAlgorithm(self, whichAlgorithm, scansion): """Run through whole iambic scansion, either algorithm, silently. Called by top-level DeduceParameters to figure metron. After, if iambic, called by ChooseAlgorithm to try each approach. If global-to-module linelength not set, figure it (not reliably!) and set it for step-by-steps. Note that when call is from DeduceParameters, lfeetset is *false*. """ ## whichAlgorithm = 1 # TESTTESTTEST if not lineDat['lfeetset']: if len(scansion) // 2 >= 2: linefeet = len(scansion) // 2 # crude! but can't find reliable improvement lineDat['lfeet'] = linefeet # was not set before; set for all following else: return ([], []) else: linefeet = lineDat['lfeet'] footlist = [] if whichAlgorithm == 1: normlen = linefeet * 2 currlen = len(scansion) if (currlen > (normlen + 1)) and (scansion[-4:] in ('x/xx', 'xx/x')): lastfoot = footDict[scansion[-4:]] linefeet -= 1 # only in local copy! scansion = scansion[:-4] elif currlen >= normlen and scansion[-3:] in ('x/x', '//x'): lastfoot = footDict[scansion[-3:]] linefeet -= 1 scansion = scansion[:-3] else: lastfoot = '' normlen = linefeet * 2 # unnec. if no special feet, but currlen = len(scansion) if currlen <= normlen and scansion[:4] in ('/x/x', '/xxx'): footlist.append('defective') linefeet -= 1 scansion = scansion[1:] # end of special-first-last-feet section if currlen == normlen: # simple disyllables for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, len(scansion)): if footname: footlist.append(footname) else: return ([], []) elif currlen < normlen: # defective somewhere candidate = scansion.find('x//') if candidate % 2 != 0: return ([], []) for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, candidate): if footname: footlist.append(footname) else: return ([], []) footlist.append('defective') for (footname, sylinx) in footfinder(footDict, scansion, 2, candidate+1, len(scansion)): if footname: footlist.append(footname) else: return ([], []) else: # anapests need = currlen - normlen candidates = [] for p in sre.finditer(r'(?=/xx/)', scansion): candidates.append(p.start() + 1) if len(candidates) < need: for p in sre.finditer(r'(?=xx/)', scansion): candidates.append(p.start()) i = 0 while i < currlen: if i in candidates: footlist.append('anapest') i += 3 else: if footDict.has_key(scansion[i:i+2]): footlist.append(footDict[scansion[i:i+2]]) else: return ([], []) i += 2 if lastfoot: footlist.append(lastfoot) else: # algorithm 2 (startoflongest, longest) = longestMatch(self.possIambRE, scansion) if startoflongest is None: return ([], []) if startoflongest % 2 == 0: # divide head into disyllables for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, startoflongest): if footname: footlist.append(footname) else: return ([], []) elif scansion[:2] == '/x': # headless, I guess # could use better test from alg 1: sc[:4] in ('/xxx', '/x/x'), IFF 3+ syls!! footlist.append('defective') for (footname, sylinx) in footfinder(footDict, scansion, 2, 1, startoflongest): if footname: footlist.append(footname) else: return ([], []) else: anap = scansion.find('xx/', 0, startoflongest) if anap == -1: return ([],[]) for (footname, longest) in footfinder(footDict, scansion, 2, 0, anap): if footname: footlist.append(footname) else: return ([], []) footlist.append('anapest') for (footname, sylinx) in footfinder(footDict, scansion, 2, anap + 3, startoflongest): if footname: footlist.append(footname) else: return ([], []) for (footname, sylinx) in footfinder(footDict, scansion, 2, startoflongest, startoflongest + longest): if footname: footlist.append(footname) else: return ([], []) # to divide tail, check e-s endings, divide in pairs (anaps??) scansion = scansion[startoflongest + longest:] if len(scansion) > 0: lastfoot = '' if scansion[-1] == 'x' and len(scansion) > 2: if footDict.has_key(scansion[-3:]): lastfoot = footDict[scansion[-3:]] scansion = scansion[:-3] for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, len(scansion)): if footname: footlist.append(footname) else: return ([], []) if lastfoot: footlist.append(lastfoot) for inx, f in enumerate(footlist): if f == 'pyrrhic': if inx == len(footlist) - 1 or footlist[inx+1] != 'spondee': f = '(iamb)' test = self.P.FeetAtPunctBounds(footlist) return (footlist, test)
def TestLengthAndDice(self, logger): normlen = (self.LD.data['lfeet'] - len(self.LD.data['footlist'])) * 2 if self.LD.data['lastfoot']: normlen -= 2 start = self.LD.data['midremain'][0] end = self.LD.data['midremain'][1] currlen = end - start logger.ExpFootDivision(currlen, normlen) marks = self.P.GetMarks() if currlen == normlen: for (footname, sylinx) \ in footfinder(footDict, marks, 2, start, end): if footname: self.LD.appendFoot(footname) else: return self.P.GetScanString(), False if sylinx < end: # not at end of line or where lastfoot starts self.P.AddFootDivMark(sylinx + self.LD.data['midremain'][0]) elif currlen < normlen: candidate = marks.find('x//', start, end) if candidate % 2 != 0: # 'x//' at odd pos hopelessly messy logger.Explain("\nFAIL! no good position " + "for single-stress foot") return self.P.GetScanString(), False candidate += 2 # point directly at defective foot for (footname, sylinx) \ in footfinder(footDict, marks, 2, start, candidate): if footname: self.LD.appendFoot(footname) else: return self.P.GetScanString(), False self.P.AddFootDivMark(sylinx) self.LD.appendFoot('defective') self.P.AddFootDivMark(candidate + 1) for (footname, sylinx) \ in footfinder(footDict, marks, 2, candidate+1, end): if footname: self.LD.appendFoot(footname) else: return self.P.GetScanString(), False if sylinx < end: self.P.AddFootDivMark(sylinx) else: # anapest(s) need = currlen - normlen candidates = [ p.start() + 1 for p in sre.finditer(r'(?=/xx/)', marks) ] if len(candidates) < need: morecands = [ p.start() for p in sre.finditer(r'(?=xx/)', marks) ] candidates += morecands while start < end: if need and (start in candidates): foot = marks[start:start + 3] if footDict.has_key(foot): self.LD.appendFoot(footDict[foot]) else: return self.P.GetScanString(), False start += 3 need -= 1 else: foot = marks[start:start + 2] if footDict.has_key(foot): self.LD.appendFoot(footDict[foot]) else: return self.P.GetScanString(), False start += 2 if start < end: self.P.AddFootDivMark(start) if self.LD.data['lastfoot']: self.LD.appendFoot(self.LD.data['lastfoot']) return self.P.GetScanString(), True
def DoAlgorithm(self, whichAlgorithm, scansion): """Run through whole iambic scansion, either algorithm, silently. Called by top-level DeduceParameters to figure metron. After, if iambic, called by ChooseAlgorithm to try each approach. If global-to-module linelength not set, figure it (not reliably!) and set it for step-by-steps. Note that when call is from DeduceParameters, lfeetset is *false*. """ ## whichAlgorithm = 1 # TESTTESTTEST if not self.LD.data['lfeetset']: if len(scansion) // 2 >= 2: # crude! but can't find reliable improvement linefeet = len(scansion) // 2 # was not set before; set for all following self.LD.data['lfeet'] = linefeet else: return ([], []) else: linefeet = self.LD.data['lfeet'] footlist = [] if whichAlgorithm == 1: normlen = linefeet * 2 currlen = len(scansion) if ((currlen > (normlen + 1)) and (scansion[-4:] in ('x/xx', 'xx/x'))): lastfoot = footDict[scansion[-4:]] linefeet -= 1 # only in local copy! scansion = scansion[:-4] elif currlen >= normlen and scansion[-3:] in ('x/x', '//x'): lastfoot = footDict[scansion[-3:]] linefeet -= 1 scansion = scansion[:-3] else: lastfoot = '' normlen = linefeet * 2 # unnec. if no special feet, but currlen = len(scansion) if currlen <= normlen and scansion[:4] in ('/x/x', '/xxx'): footlist.append('defective') linefeet -= 1 scansion = scansion[1:] # end of special-first-last-feet section if currlen == normlen: # simple disyllables for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, len(scansion)): if footname: footlist.append(footname) else: return ([], []) elif currlen < normlen: # defective somewhere candidate = scansion.find('x//') if candidate % 2 != 0: return ([], []) for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, candidate): if footname: footlist.append(footname) else: return ([], []) footlist.append('defective') for (footname, sylinx) in footfinder(footDict, scansion, 2, candidate + 1, len(scansion)): if footname: footlist.append(footname) else: return ([], []) else: # anapests need = currlen - normlen candidates = [] for p in sre.finditer(r'(?=/xx/)', scansion): candidates.append(p.start() + 1) if len(candidates) < need: for p in sre.finditer(r'(?=xx/)', scansion): candidates.append(p.start()) i = 0 while i < currlen: if i in candidates: footlist.append('anapest') i += 3 else: if footDict.has_key(scansion[i:i + 2]): footlist.append(footDict[scansion[i:i + 2]]) else: return ([], []) i += 2 if lastfoot: footlist.append(lastfoot) else: # algorithm 2 (startoflongest, longest) = longestMatch(self.possIambRE, scansion) if startoflongest is None: return ([], []) if startoflongest % 2 == 0: # divide head into disyllables for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, startoflongest): if footname: footlist.append(footname) else: return ([], []) elif scansion[:2] == '/x': # headless, I guess # could use better test from alg 1: sc[:4] in ('/xxx', '/x/x'), IFF 3+ syls!! footlist.append('defective') for (footname, sylinx) in footfinder(footDict, scansion, 2, 1, startoflongest): if footname: footlist.append(footname) else: return ([], []) else: anap = scansion.find('xx/', 0, startoflongest) if anap == -1: return ([], []) for (footname, longest) in footfinder(footDict, scansion, 2, 0, anap): if footname: footlist.append(footname) else: return ([], []) footlist.append('anapest') for (footname, sylinx) in footfinder(footDict, scansion, 2, anap + 3, startoflongest): if footname: footlist.append(footname) else: return ([], []) for (footname, sylinx) in footfinder(footDict, scansion, 2, startoflongest, startoflongest + longest): if footname: footlist.append(footname) else: return ([], []) # to divide tail, check e-s endings, divide in pairs (anaps??) scansion = scansion[startoflongest + longest:] if len(scansion) > 0: lastfoot = '' if scansion[-1] == 'x' and len(scansion) > 2: if footDict.has_key(scansion[-3:]): lastfoot = footDict[scansion[-3:]] scansion = scansion[:-3] for (footname, sylinx) in footfinder(footDict, scansion, 2, 0, len(scansion)): if footname: footlist.append(footname) else: return ([], []) if lastfoot: footlist.append(lastfoot) for inx, f in enumerate(footlist): if f == 'pyrrhic': if inx == len(footlist) - 1 or footlist[inx + 1] != 'spondee': f = '(iamb)' test = self.P.FeetAtPunctBounds(footlist) return (footlist, test)