43. Grammar revisited

class Grammar:
  def __init__(self, sourceName,
      ruleString=None):
    self.ruleDict = {}
    if not sourceName is None:
      ruleString = open(sourceName).read()
    self._parseRules(ruleString)

  def __str__(self):
    return "\n".join(
      map(str,
        reduce(operator.add,
          self.ruleDict.values())))

  def _parseRules(self, ruleString):
    for rawRule in filter(operator.truth,
        map(str.strip,
        ruleString.split("\n"))):
      if rawRule.startswith("="):
        self._setStartSymbol(symbol.NonTerminal(
          rawRule[1:].strip()))
      else:
        self._addRule(Rule(rawRule))

  def _addRule(self, rule):
    self.ruleDict.setdefault(rule.getLeft(),
      []).append(rule)
  def _setStartSymbol(self, startSymbol):
    self.startSymbol = startSymbol

  def getRulesForNonTerm(self, nonTerm):
    return self.ruleDict.get(nonTerm, [])

  def getStartSymbol(self):
    try:
      return self.startSymbol
    except AttributeError:
      return None

  def deriveLeft(self, nonTerm, word,
    yieldRules=None):
    res = []
    for rule in self.getRulesForNonTerm(
       nonTerm):
      if yieldRules:
        res.append((rule,
          rule.applyToLeftmost(word)))
      else:
        res.append(rule.applyToLeftmost(word))
    return res

Das sieht fürchterlicher aus als es ist. Die grobe Struktur ist weiterhin die unserer alten, simplen Grammatikklasse. Wesentliche Neuerungen:

  • _parseRules räumt die Strings jetzt etwas besser auf und geht sorgfältiger mit dem Startsymbol um.
  • Wir haben ein vernünftiges Verhalten, wenn die Grammatik kein Startsymbol gibt – getStartSymbol gibt dann nämlich None zurück. Je nach Zweck wäre hier das Auslösen einer Exception auch denkbar gewesen, aber wir haben uns auf den Standpunkt gestellt, dass eine reine Regelmenge ohne Startsymbol durchaus auch sinnvoll sein kann.
  • deriveLeft hat ein zusätzliches Argument, bei dem auch noch ein =None dahintersteht. Was das ist, sehen wir auf der nächsten Folie, warum man yieldRules überhaupt haben will, etwas später.

Übungen zu diesem Abschnitt

Ihr solltet euch wenigstens an den rötlich unterlegten Aufgaben versuchen

(1)

Geht den Code durch und versucht, zu verstehen, was da jeweils passiert. Im Anhang dieser Seite gibt es das ganze auch kommentiert.

Dateien zu diesem Abschnitt


Markus Demleitner

Copyright Notice