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

Ten rekursywny analizator składni będzie próbował przeanalizować "(? Ui) (regexvalue) .r r aż do końca wprowadzania. Czy w scala jest sposób na zabranianie analizowania, gdy pewna określona liczba znaków została skonsumowana przez "nieinteresujące rzeczy"?Zaawansowane sterowanie parser rekursywny w scala

UPD: Mam jedno słabe rozwiązanie:

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 => 
     } 
    } 
} 

Wady:
- nie wszyscy członkowie są leniwe vals tak PackratParser będzie miał trochę czasu kara
- konstruowaniu wyrażeń regularnych na każdym „nieciekawe” metody połączenia - kara czasowa
- używanie wyjątku do programu sterującego - styl kodowy i kara czasowa

+0

Jak rozwiązać ten problem z innymi bibliotekami parsera, generatorami lub frameworkami? –

+0

Co właściwie próbujesz zrobić? –

Odpowiedz

3

Szybka i nędzna odpowiedź polega na ograniczeniu liczby znaków w wyrażeniu regularnym na nieinteresujące rzeczy i sprawiają, że nie rekurencyjny:

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

oparciu o komentarz na temat chciwości jedzenia regexvalue proponuję pojedynczy regex:

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

Ale wydaje się, że odważył poza sferę Scala parsery do regex minutia. Byłbym zainteresowany widząc inne wyniki.

+0

Nie zadziała, ponieważ "nieinteresujące rzeczy" są chciwe i zawsze będą zużywać 60 znaków wejściowych – Jeriho

0

Użyj tokenarza, aby najpierw podzielić wszystko, korzystając z wszystkich wyrażeń regularnych, aby uzyskać interesujące rzeczy, które już znasz. Użyj pojedynczego ".".r, aby dopasować nieinteresujące rzeczy, jeśli są one znaczące dla twojej gramatyki. (Lub wyrzuć je, jeśli nie są znaczące dla gramatyki.) Twoje interesujące rzeczy mają teraz znane typy i są rozpoznawane przez tokenizera za pomocą innego algorytmu niż parsowanie. Ponieważ wszystkie problemy z wyprzedzeniem są rozwiązywane przez tokenizator, parser powinien być łatwy.