2013-07-04 4 views
7

Генераторы парсеров на основе PEG обычно предоставляют ограниченную отчетность об ошибках на недопустимых входах. Из того, что я читал, диалоги разбора ребола вдохновлены грамматиками ПЭГ, расширенными регулярными выражениями.Сообщение об ошибке при неудаче совпадения в Rebol Parse

Например, введя в JavaScript:

d8> function() {} 

дает следующее сообщение об ошибке, потому что идентификатор не был представлен в объявлении глобальной функции:

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

Анализатор способен точно определить, положение во время разбора, где отсутствует ожидаемый токен. Позиция символа ожидаемого токена используется для размещения стрелки в сообщении об ошибке.

Разбор диалемента в rebol предоставляет встроенные средства для сообщения ошибок строки и столбца на недопустимых входах?

В противном случае существуют ли примеры пользовательских правил разбора, которые предоставляют такую ​​отчетность об ошибках?

+0

Вы спрашиваете «строка и столбец недействительного токена/правила». Вы спрашиваете, как сказать, когда есть проблема с набранным блоком правил, который вы проходите, или инструментами, которые эти правила могут использовать для сообщения о проблемах во входном сигнале для самого процесса анализа? Редактирование этого вопроса для добавления идеализированного примера того, что вы ищете, может быть полезным. – HostileFork

+0

@HostileFork Я прошу второй случай, когда вход недействителен. – Erick

ответ

7

Я сделал очень продвинутые синтаксические анализаторы Rebol, которые управляют живыми и критичными TCP-серверами и делают правильную отчетность об ошибках. Так что это важно!

Возможно, одним из самых уникальных аспектов PARSE Ребола является то, что вы можете включать прямую оценку в правила. Таким образом, вы можете установить переменные для отслеживания позиции синтаксического анализа или сообщений об ошибках и т. Д. (Это очень просто, потому что характер Rebol заключается в том, что код смешивания и данные как одна и та же вещь являются основной идеей.)

So вот как я это сделал. Перед попыткой каждого правила сопоставления я сохраняю позицию синтаксического анализа в «здесь» (путем записи here:), а затем также сохраняю ошибку в переменной с помощью выполнения кода (путем помещения (error: {some error string}) в круглые скобки, чтобы он выполнял диалоги на основе анализа). Если правило совпадения выполняется успешно, нам не нужно использовать ошибку или позицию ... и мы просто переходим к следующему правилу. Но если это не удастся, мы получим последнее состояние, которое мы установили для отчета после сбоя.

Таким образом, картина в синтаксическое диалекте просто:

; 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}] 

Это в основном то, что вам нужно сделать.Вот пример телефонных номеров:

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) 
] 

Тогда вы можете увидеть его в действии. Обратите внимание, что мы не устанавливаем ошибку в none, если мы достигнем конца правил разбора. PARSE вернет ложь, если есть еще больший вклад в процесс, так что если мы замечаем, что нет никакой ошибки установлен, но PARSE возвращает ложь в любом случае ... мы не смогли, потому что было слишком много дополнительного входа:

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

выше будет распечатаны следующие:

error at position: 4 

expecting 3 digits 
800-22r2-3333 
    ^

Очевидно, что вы могли бы сделать гораздо более мощное вещество, так как все, что вы положили в круглые скобки будут оценены только как обычный исходный код Rebol. Это действительно гибко. У меня даже есть парсеры, которые обновляют индикаторы выполнения при загрузке огромных наборов данных ... :-)

+0

Извините за все переписывание, но я подумал, что это хороший пример, чтобы объяснить немного больше. :-) – HostileFork

+0

Я знаю, что вы пришли с языка, для которого его естественным, пожалуйста, не начинайте добавлять двойные полуколоны, как уродливые, так и необученные. – moliad

+0

Буду честным, я старался держать его простым и прямым. это было непродолжительное и сладкое, слишком много текста, и иногда оно становится менее доступным (это делает его похожим на синтаксический анализ). Я оставлю его, как вы отредактировали ... на этот раз (гордость ранена ;-) (хотя удалена двойная двоеточие) ;-P – moliad

3

Вот простой пример нахождения позиции при разборе строки, которая может использоваться для выполнения заданий.

Скажем, что наш код действителен только в том случае, если он содержит символы a и b, все остальное будет незаконным.

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

Давайте проверим, что с каким-то действительным кодом

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

Теперь мы можем попробовать еще раз с некоторым недопустимым вводом

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

Это довольно упрощенным примером язык, но это должно быть легко чтобы перейти к более сложному примеру.

+0

Вы можете поприветствовать вас и поговорить об этом и о других способах использования синтаксического анализа в нашем чате-чате. Http://chat.stackoverflow.com/rooms/291/rebol-and-red – johnk

+1

На самом деле мне нужно было 20 очков репутации, прежде чем в состоянии отправить там. Спасибо всем ответчикам за то, что он подтолкнул меня к 20 пунктам ;-). – Erick