2010-10-30 4 views
2

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

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

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) 

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

ответ

3

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

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

и ваше правило ввода выглядит так же, за исключением того, с «входом», то проблема заключается в том, что оба правила начинаются с ident и так парсек Безразлично 't backtrack автоматически, он просто попытается применить output первым, потребляя ident, а затем сбой, если он не может соответствовать «output of».

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

outs <- many1 (try output) 
ins <- many1 (try input) 
+0

Большое спасибо. Это полностью исправлено. Я не понимал, что они оба начинаются с идентификатора, и он потребляется выходным синтаксическим анализатором. – HaskellNoob

0

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

Хотя это добавляет код парсеров это делает их более надежным:

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

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