plint

French poetry validator (local mirror of https://gitlab.com/a3nm/plint)
git clone https://a3nm.net/git/plint/
Log | Files | Refs | README

commit 1684e813aa5fc22318fcca74764858ad7e725638
parent adb3aff10a7284eac1a1f1b3a813a5d49be7643f
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Sun, 31 Jul 2011 16:28:12 -0400

fixes and stuff

Diffstat:
error.py | 45++++++++++++++++++++++++++++-----------------
metric.py | 12++++++++----
poetlint.py | 9+++++----
template.py | 17+++++++++++++++--
4 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/error.py b/error.py @@ -1,3 +1,5 @@ +import common +import hemistiches class Error: def __init__(self): @@ -13,13 +15,15 @@ class Error: self.prefix = "stdin:%d: " % self.line_no def say(self, l): - print(self.prefix + l) + return self.prefix + l def report(self, s, t = []): - self.say("error: %s" % (s)) - self.say("Line is: %s" % (self.line)) - for l in t: - self.say(l) + l = [] + l.append(self.say("error: %s" % (s))) + l.append(self.say("Line is: %s" % (self.line))) + for x in t: + l.append(self.say(x)) + return '\n'.join(l) class ErrorBadRhyme(Error): def __init__(self, expected, inferred): @@ -28,13 +32,16 @@ class ErrorBadRhyme(Error): self.inferred = inferred def report(self): - Error.report(self, "Bad rhyme %s for type %s (expected %s, inferred %s)" + return Error.report(self, "Bad rhyme %s for type %s (expected %s, inferred %s)" % (self.kind, self.get_id(), self.fmt(self.expected), self.fmt(self.inferred))) class ErrorBadRhymeGenre(ErrorBadRhyme): def fmt(self, l): - return ' or '.join(list(l)) + result = ' or '.join(list(l)) + if result == '': + result = "?" + return result def get_id(self): return self.pattern.femid @@ -45,16 +52,18 @@ class ErrorBadRhymeGenre(ErrorBadRhyme): class ErrorBadRhymeSound(ErrorBadRhyme): def fmt(self, l): + #TODO handle other types pron, spel, constraint = l ok = [] if len(pron) > 0: ok.append("") + return '/'.join(list(pron)) def get_id(self): return self.pattern.myid def report(self): - Error.report(self, "Bad rhyme %s for type %s (expected %s)" + return Error.report(self, "Bad rhyme %s for type %s (expected %s)" % (self.kind, self.pattern.myid, self.fmt(self.expected))) @property @@ -78,7 +87,7 @@ class ErrorBadMetric(Error): for x in [''] + align: if isinstance(x, tuple): orig = "" - while len(line) > 0 and is_vowels(line[0]): + while len(line) > 0 and common.is_vowels(line[0]): orig += line[0] line = line[1:] l2 += ('{:^'+str(len(orig))+'}').format(str(x[1])) @@ -87,28 +96,30 @@ class ErrorBadMetric(Error): done = False else: orig = "" - while len(line) > 0 and not is_vowels(line[0]): + while len(line) > 0 and not common.is_vowels(line[0]): orig += line[0] line = line[1:] if count in hemis.keys() and not done: done = True summary.append(str(ccount)) ccount = 0 - summary.append(hemis_types[hemis[count]]) + summary.append(hemistiches.hemis_types[hemis[count]]) l2 += ('{:^'+str(len(orig))+'}' - ).format(hemis_types[hemis[count]]) + ).format(hemistiches.hemis_types[hemis[count]]) else: l2 += ' ' * len(orig) - summary.append(str(ccount)) + summary.append(str(ccount)+':') result = ''.join(l2) summary = ('{:^9}').format(''.join(summary)) return summary + result def report(self): num = min(len(self.possible), 4) - Error.report( + return Error.report( self, - ("Bad metric (expected %s, inferred %d options)" % - (self.pattern.metric, num)), - list(map(self.align, self.possible[:num]))) + ("Bad metric (expected %s, inferred %d option%s)" % + (self.pattern.metric, num, ('s' if len(self.possible) != 1 else + ''))), + list(map(self.align, self.possible[:num])) + ) diff --git a/metric.py b/metric.py @@ -48,10 +48,14 @@ def fit(chunks, pos, left): def feminine(align, verse): for a in sure_end_fem: if verse.endswith(a): - return True - if verse.endswith('ent') and align[-2][1] != 1: - return True - return False + return ['F'] + if verse.endswith('ent') and align[-2][1] == 0: + return ['F'] # mute -ent + if verse.endswith('ent') and align[-2][1] > 0 and align[-2][0] == 'e': + return ['M'] # non-mute "-ent" by the choice of metric + # and now, what? "tient" vs. "lient" for instance, + # TODO check pronunciation? :-/ + return ['M', 'F'] def parse(text, bound): """Return possible aligns for text, bound is an upper bound on the diff --git a/poetlint.py b/poetlint.py @@ -9,8 +9,8 @@ from pprint import pprint if len(sys.argv) != 2: print("Usage: %s TEMPLATE" % sys.argv[0], file=sys.stderr) - print("Check stdin according to template, report errors on stdout" - % sys.argv[0], file=sys.stderr) + print("Check stdin according to template, report errors on stdout", + file=sys.stderr) sys.exit(1) f = open(sys.argv[1]) @@ -22,8 +22,9 @@ def run(): line = sys.stdin.readline() if not line: break - for error in template.check(line): - error.report() + errors = template.check(line) + for error in errors: + print(error.report(), file=sys.stderr) run() diff --git a/template.py b/template.py @@ -31,6 +31,7 @@ class Template: self.position = 0 self.env = {} self.femenv = {} + self.reject_errors = False def load(self, stream): """Load from a stream""" @@ -110,7 +111,7 @@ class Template: self.femenv[pattern.femid] = x else: old = list(self.femenv[pattern.femid]) - new = list(set(['F' if x[1] else 'M' for (score, x) in possible])) + new = list(set(sum([x[1] for (score, x) in possible], []))) self.femenv[pattern.femid] &= set(new) if len(self.femenv[pattern.femid]) == 0: errors.append(error.ErrorBadRhymeGenre(old, new)) @@ -151,17 +152,26 @@ class Template: def get(self): """Get next state, resetting if needed""" + self.old_position = self.position + self.old_env = dict(self.env) + self.old_femenv = dict(self.femenv) if self.position >= len(self.template): self.reset_state() result = self.template[self.position] self.position += 1 return result + def back(self): + """Revert to previous state""" + self.position = self.old_position + self.env = dict(self.old_env) + self.femenv = dict(self.old_femenv) + def check(self, line): """Check line (wrapper)""" self.line_no += 1 line = line.rstrip() - if line == '': + if normalize(line) == '': return [] #possible = [compute(p) for p in possible] #possible = sorted(possible, key=rate) @@ -169,5 +179,8 @@ class Template: for error in errors: # update errors with line position and pattern error.pos(line, self.line_no, pattern) + if len(errors) > 0 and self.reject_errors: + self.back() + self.line_no -= 1 return errors