2013-07-04 11 views
7

Generatory analizatorów opartych na PEG zwykle udostępniają ograniczone raporty błędów dotyczące nieprawidłowych danych wejściowych. Z tego, co przeczytałem, dialekt gwarowy rebola jest inspirowany przez gramatykę PEG rozszerzoną o wyrażenia regularne.Komunikat o błędzie podczas niepowodzenia testu w Rebol Parse

Na przykład, wpisując w javascript:

d8> function() {} 

daje następujący błąd, ponieważ nie identyfikator został dostarczony w deklarując globalną funkcję:

(d8):1: SyntaxError: Unexpected token (
function() {} 
     ^

Parser jest w stanie dokładnie zlokalizować pozycja podczas analizowania w przypadku braku oczekiwanego tokena. Pozycja znaku oczekiwanego tokena służy do ustawiania strzałki w komunikacie o błędzie.

Czy dialekt w rebola zapewnia wbudowane funkcje zgłaszania błędów linii i kolumn na błędnych danych wejściowych?

Czy istnieją przykłady niestandardowych implementowanych reguł analizy składni, które zapewniają takie zgłaszanie błędów?

+0

Pytasz "wiersz i kolumnę nieprawidłowego tokena/reguły". Czy pytasz o to, jak określić, kiedy pojawia się problem z wybranym blokiem reguł, które przekazujesz, lub narzędziami, których te reguły mogą użyć do zgłaszania problemów w danych wejściowych do samego procesu parsowania? Edytowanie tego pytania w celu dodania wyidealizowanego przykładu tego, czego szukasz, może być pomocne. – HostileFork

+0

@HostileFork Proszę o drugi przypadek, gdy dane wejściowe są nieprawidłowe. – Erick

Odpowiedz

7

Zrobiłem bardzo zaawansowane parsery Rebol, które zarządzają serwerami TCP na żywo i krytycznymi operacjami, i wymagane było poprawne raportowanie błędów. To ważne!

Prawdopodobnie jednym z najbardziej unikalnych aspektów PARSU Rebola jest możliwość włączenia bezpośredniej oceny do reguł. Więc można ustawić zmienne do śledzenia położenia składniowy lub komunikaty o błędach itd (Jest to bardzo łatwe, ponieważ charakter REBOL jest to, że mieszanie kodu i danych, jak samo jest podstawowym pomysłem.)

tak oto sposób, w jaki to zrobiłem. Przed podjęciem każdej reguły dopasowania zapisuję pozycję parsowania w "tutaj" (pisząc here:), a następnie zapisuję błąd w zmiennej za pomocą kodu (umieszczając (error: {some error string}) w nawiasach, tak aby dialekt parse działał). Jeśli reguła dopasowania się powiedzie, nie musimy używać błędu ani pozycji ... i przechodzimy do następnej reguły. Jeśli jednak zawiedzie, będziemy mieli ostatni stan, który ustawimy do zgłoszenia po awarii.

Zatem wzór w dialekcie parse jest prosta:

; use PARSE dialect handling of "set-word!" instances to save parse 
; position into variable named "here" 

here: 

; escape out of the parse dialect using parentheses, and into the DO 
; dialect to run arbitrary code. Here we run code that saves an error 
; message string into a variable named "error" 

(error: "<some error message relating to rule that follows>") 

; back into the PARSE dialect again, express whatever your rule is, 
; and if it fails then we will have the above to use in error reporting 

what: (ever your) [rule | {is}] 

To w zasadzie to, co trzeba zrobić.Oto przykład numerów telefonów:

digit: charset "" 

phone-number-rule: [ 
    here: 
    (error: "invalid area code") 
    ["514" | "800" | "888" | "916" "877"] 

    here: 
    (error: "expecting dash") 
    "-" 

    here: 
    (error: "expecting 3 digits") 
    3 digit 

    here: 
    (error: "expecting dash") 
    "-" 

    here: 
    (error: "expecting 4 digits") 
    4 digit 

    (error: none) 
] 

Następnie można go zobaczyć w akcji. Zauważ, że ustawiamy błąd na none, jeśli dojdziemy do końca reguł parsowania. PARSE zwróci false, jeśli jest jeszcze bardziej wejście do procesu, więc jeśli zauważymy, nie ma błędu ustawienia ale PARSE zwraca fałsz w każdym razie ... nie udało, bo nie było zbyt dużo dodatkowy wkład:

input: "800-22r2-3333" 

if not parse input phone-number-rule [ 
    if none? error [ 
     error: "too much data for phone number" 
    ] 
] 

either error [ 
    column: length? copy/part input here newline 
    print rejoin ["error at position:" space column] 
    print error 
    print input 
    print rejoin [head insert/dup "" space column "^^"} 
    print newline 
][ 
    print {all good} 
] 

Powyższy wola wydrukować następujące:

error at position: 4 

expecting 3 digits 
800-22r2-3333 
    ^

Oczywiście, można zrobić dużo silniejsze rzeczy, ponieważ cokolwiek umieścić w parens będą oceniane tak jak normalnego kodu źródłowego REBOL. Jest bardzo elastyczny. Mam nawet parsery, które aktualizują paski postępu podczas ładowania ogromnych zestawów danych ... :-)

+0

Przepraszam za przepisanie, ale pomyślałem, że to dobry przykład, żeby wyjaśnić trochę więcej. :-) – HostileFork

+0

Wiem, że pochodzisz z języka, dla którego jest to naturalne, proszę nie zaczynaj dodawać podwójnych średników, zarówno brzydkich, jak i niepotrzebnych. – moliad

+0

Będę szczery, starałem się zachować prostotę i bezpośredniość. był krótki i słodko celowo, za dużo tekstu, a czasem staje się mniej dostępny (sprawia, że ​​wygląda na złożoną). Zostawię to tak, jak edytowałeś ... tym razem (duma była zraniona ;-) (aczkolwiek z podwójnym średnikiem usuniętym) ;-P – moliad

3

Oto prosty przykład znalezienia pozycji podczas analizowania łańcucha, który można wykorzystać do zrobienia tego, o co prosisz.

Powiedzmy, że nasz kod jest ważny tylko wtedy, gdy zawiera znaki a i b, wszystko inne może być nielegalne.

code-rule: [ 
    some [ 
     "a" | 
     "b" 
    ] 
    [ end | mark: (print [ "Failed at position" index? mark ]) ] 
] 

Sprawdźmy, które z jakiegoś ważnego kodu

>> parse "aaaabbabb" code-rule 
== true 

Teraz możemy spróbować jeszcze raz z jakimś niepoprawnym wejściem

>> parse "aaaabbXabb" code-rule 
Failed at position 7 
== false 

Jest to dość uproszczony przykład język, ale to powinno być łatwe aby rozszerzyć bardziej złożony przykład.

+0

Zapraszamy do czatowania nad tym i innymi sposobami korzystania z analizy w naszym pokoju internetowym stackoverflow http://chat.stackoverflow.com/rooms/291/rebol-andredred – johnk

+1

Potrzebowałem 20 punktów reputacji, zanim w stanie opublikować tam. Dziękuję wszystkim, którzy odpowiedzieli za pchnięcie mnie ponad 20 punktów ;-). – Erick

Powiązane problemy