2010-05-12 2 views
5
val uninterestingthings = ".".r 
val parser = "(?ui)(regexvalue)".r | (uninterestingthings~>parser) 

Dieser rekursive Parser versucht, "(? Ui) (regexvalue)". R bis zum Ende der Eingabe zu analysieren. Gibt es in scala eine Möglichkeit, das Parsen zu verhindern, wenn eine bestimmte Anzahl von Zeichen von "uninteressanthings" verbraucht wurde?Erweiterte Kontrolle des rekursiven Parsers in der Skala

UPD: Ich habe eine schlechte Lösung:

object NonRecursiveParser extends RegexParsers with PackratParsers{ 
    var max = -1 
    val maxInput2Consume = 25 
    def uninteresting:Regex ={ 
    if(max<maxInput2Consume){ 
    max+=1 
    ("."+"{0,"+max.toString+"}").r 
    }else{ 
     throw new Exception("I am tired") 
    } 
    } 
    lazy val value = "itt".r 
    def parser:Parser[Any] = (uninteresting~>value)|parser 
    def parseQuery(input:String) = { 
     try{ 
     parse(parser, input) 
     }catch{ 
      case e:Exception => 
     } 
    } 
} 

Nachteile:
- nicht alle Mitglieder sind faul vals so PackratParser einige Zeit Strafe
haben - regexps auf jedem "uninteressant" Methodenaufruf Konstruktion - Zeitstrafe
- Verwenden von Ausnahme zu Programm - Code-Stil und Zeitstrafe

+0

Wie würden Sie dieses Problem mit anderen Parser-Bibliotheken, Generatoren oder Frameworks lösen? –

+0

Was versuchst du eigentlich zu tun? –

Antwort

3

Die Quick-n-Dirty-Antwort ist nur die Anzahl der Zeichen in Ihrer Regex für uninteressantthings begrenzen und machen es nicht rekursiv:

val uninterestingthings = ".{0,60}".r // 60-chars max 
val parser = (uninterestingthings~>"(?ui)(regexvalue)".r)* 

Basierend auf dem Kommentar über greediness Essen der regexvalue, schlage ich eine einzelne Regex:

val parser = ("(?.{0,60}?)(?ui)(regexvalue)".r)* 

Aber wir scheinen außerhalb des Bereichs der scala zu gewagt Parser in Regex Minutien. Ich wäre an anderen Ergebnissen interessiert.

+0

Es wird nicht funktionieren, weil "uninteressingthings" gierig ist und immer 60 Zeichen der Eingabe verbrauchen wird – Jeriho

0

Verwenden Sie einen Tokenizer, um die Dinge zuerst zu lösen, indem Sie alle Regexps für interessante Dinge verwenden, die Sie bereits kennen. Verwenden Sie eine einzelne ".".r, um uninteressante Dinge zu finden, wenn sie für Ihre Grammatik von Bedeutung sind. (Oder sie wegwerfen, wenn sie für die Grammatik nicht von Bedeutung sind.) Ihre interessanten Dinge haben nun bekannte Typen, und sie werden vom Tokenizer mit einem anderen Algorithmus als dem Parsing identifiziert. Da alle Lookahead-Probleme durch den Tokenizer gelöst werden, sollte der Parser einfach sein.