# File Parser.rb, line 49 def parse(str) zust = @start left = Array.new right = Array.new regs = Array.new # Für alle Symbole den passenden regulären Ausdruck in regs ablegen @symbols.each {|symb| if symb == "." or symb == "|" or symb == "(" or symb ==")" or symb == "[" or symb == "{" or symb == "+" or symb == "\\" or symb == "^" or symb == "$" or symb == "*" or symb == "?" symb = "\\" + symb end regs.push(Regexp.new(symb)) } scanner = Scanner.new([@symbols , regs]) begin middle = scanner.zerlege(str) rescue return nil end middle.push("#") progress = true # Nach Initialisierung: # zust = Startzustand # left, right = leer # middle = Array aller gescannten Symbole aus dem Ausdruck # progress = true # # Schleife führt die Aktionen der Aktionstabelle @atable aus und berechnet für # jeden Durchlauf den aktuellen Zustand(zust), die eingelesenen Symbole(left), # die noch einzulesenden Symbole(middle) und die bereits durchgeführten # Reduktionen(right) solange bis der Ausdruck komplett durchgelaufen ist oder # er nicht zur Grammatik passt. while progress # Prüft ob der aktuelle Zustand bzw. die Zeile der Aktionstabelle leer ist # (könnte bei nicht akzeptablen Ausdruck auftreten) if @atable.gettabelle[zust] != nil and zust != nil action = @atable.gettabelle[zust][middle[0]] # In der Aktionstabelle wird die Aktion gesucht die in der Zeile zust in der Spalte # des ersten Symbols aus middle steht. Abhängig von der dort stehenden Aktion wird # weiter verfahren. case action # Wenn in der Tabelle an der angegebenen Stelle "error" steht, kann das nächste Symbol # nach der Grammatik nicht als nächstes auftreten. Es wird abgebrochen und nil # zurückgegeben. when "error" return nil # Wenn in der Tabelle an der angegebenen Stelle "accept" steht, wurde der Komplette Ausdruck # akzeptiert und die Reduktionsschritte gesammelt. Die Schleife kann verlassen werden # (progress = false) when "accept" progress = false # Wenn in der Tabelle an der angegebenen Stele "shift" steht, wird das nächste einzulesende # Symbol gelesen (das erste Element von middle wird als letztes Element von left angeführt und # aus middle gelöscht) Der neue Zustand ergibt sich aus aktueller Zustand / eingelesenes Symbol # in der Übergangstabelle when "shift" left.push(middle[0]) zust = @utable.gettabelle[zust][middle[0]] middle.slice!(0) # Wenn keiner der drei oberen Fälle aufgetreten ist, kann nur noch eine Reduktion an der # angegebenen Stelle angegeben sein. Der Tabelleneintrag wird zu right hinzugefügt. # Anhand der Reduktionsregel werden die eingelsenen Symbole else right.push(action) links,rechts = action.split "->" links = links.gsub("red[" , "").strip rechts = rechts.gsub(".]", "").strip rArray = scanner.zerlege(rechts) # Lösche jedes gescannte Symbol der rechten Reduktionsseite von links aus left # wenn sie übereinstimmen. Ansonsten wird abgebrochenund nil zurückgegeben rArray.reverse_each { |symb| (symb == left.last) ? (left.delete_at((left.length) -1)) : (return nil) } left.push(links) zust = @start # Nach der Reduktion muss der neue Zustand gefunden werden. Dafür wird zust # mit dem Startzustand initialisiert und für jedes Symbol von left werden # anhand der Übergangstabelle die Zustände weitergeschaltet left.each { |symb| zust = @utable.gettabelle[zust][symb] } end # Bricht ab fals der Zustand = nil ist und gibt nil zurück else return nil end end right.reverse end