Parsec разбор многих вопросов - PullRequest
2 голосов
/ 30 октября 2010

Мне нужно создать парсер для языка программирования.До сих пор это сделано на 95%, я бы сказал, за исключением крошечной детали.

Программа, написанная на этом языке, имеет следующую структуру:

outputs
inputs
expressions

Требуется, чтобы выходные данныенельзя смешивать с входами.Например:

x := output of int;
y := output of in;
.....
z := input of int;
t := input of in;
.....
expressions

Я могу очень хорошо разобрать один выход, но если я попытаюсь использовать (вывод many1), чтобы разрешить несколько выходов, он не будет работать, потому что он пытается проанализировать входы как выходы.

Мой основной синтаксический анализатор выглядит так:

prog =
    do outs <- many1 output
       ins <- many1 input
       exs <- expressions
       eof
       return (Prog outs ins exs) 

Я знаю, это кажется легким, но я много чего перепробовал и просто не могу заставить его работать.Пожалуйста, помогите.

Ответы [ 2 ]

3 голосов
/ 30 октября 2010

Если ваше правило для вывода выглядит примерно так:

output = do name <- ident
            string ":= output of"
            type <- ident
            char ';'
            return $ Out name type

и ваше правило ввода выглядит одинаково, за исключением «input of», тогда проблема в том, что оба правила начинаются с ident итак как parsec не возвращает автоматически, он сначала попытается применить output, потребляя ident, а затем потерпит неудачу, когда не может соответствовать «output of».

Чтобы это исправить, вы можете простообернуть output и input в try, т.е.

outs <- many1 (try output)
ins <- many1 (try input)
0 голосов
/ 30 октября 2010

Хотя ответ sepp2k работает, я лично хотел бы инкапсулировать обратный трекинг внутри анализаторов вывода и ввода.

Хотя это добавляет код в анализаторы, он делает их более устойчивыми:

output = do name <- try prefix
            type <- ident
            char ';'
            return $ Out name type
  where
    prefix = do name <- ident
                string ":= output of"
                return name

В Parsec лучше избегать try за исключением парсеров Char и использовать левую разметку для улучшения грамматики ( try может сделать парсеры очень хрупкими).К сожалению, грамматика, с которой вы работаете, не особенно удобна для левого факторинга, и в этом случае ее, вероятно, не стоит беспокоить.

...