0

次のチュートリアルの詳細を使用してパーサーを作成しようとしています

コードの多くはチュートリアルから直接コピーされ、いくつかの名前が変更されています。

import qualified Text.ParserCombinators.Parsec.Token as P 

reserved   = P.reserved   lexer  
integer    = P.integer    lexer
whiteSpace = P.whiteSpace lexer
identifier = P.identifier lexer

data Express = Seq [Express]
          | ID String
          | Num Integer
          | BoolConst Bool
          deriving (Show)

whileParser :: Parser Express
whileParser = whiteSpace >> expr7

expr7 = seqOfStmt 
    <|> expr8        

seqOfStmt =         
    do list <- (sepBy1 expr8 whiteSpace)
    return $ if length list == 1 then head list else Seq list

expr8 :: Parser Express
expr8 = name 
    <|> number
    <|> bTerm

name :: Parser Express
name = fmap ID identifier

number :: Parser Express
number = fmap Num integer

bTerm :: Parser Express
bTerm = (reserved "True"  >> return (BoolConst True ))
    <|> (reserved "False" >> return (BoolConst False))

このコードは笑えるかもしれないことは理解していますが、どこが間違っているのかについてもう少し学びたいと思います。また、これで十分な情報が得られると思いますが、そうでない場合はお知らせください。

Error:
parse error on input `return'  

エラーはさまざまなリターンタイプに関係していると思います。これは、投稿の冒頭にあるチュートリアルをすべての試みの基礎として使用しようとしたため、奇妙なことです。

前もって感謝します、

セアン

4

1 に答える 1

3

レイアウトルールに慣れていない場合は、別の構文を使用することもできます。

seqOfStmt =         
   do { list 
 <- (sepBy1 expr8 whiteSpace);
       return $ if length 
            list == 1 
        then head list else Seq list;}

ただし、中括弧とセミコロンのないレイアウトは、次の2つの理由で優れていると見なされます。

  1. 醜い入力する必要はありません; 中かっこ
  2. 上記の例で示した歪んだがらくたとは異なり、(ほとんど)読み取り可能なコードを書く必要があります。

そして、ルールは本当に簡単です:

  1. タブを使用せず、スペースを使用してください。いつも。(編集者はそれを行うことができますが、そうでない場合は、それを捨ててください、それはクラップウェアです。)
  2. 一緒に属するものは、同じ列に配置する必要があります。

たとえば、doブロックに属する2つのステートメントがあるため、それらは同じ列に配置する必要があります。ただし、をと整列させreturnているdoため、コンパイラはこれを次のように認識します。

do { list <- sepBy1 expr8 whiteSpace; };
return $  ....;

しかし、あなたが欲しいのはこれです:

do {
    list <- sepBy1 ....;
    return $ .....;
}

(中括弧とセミコロンは省略できますが、インデントをそのままにしておけば問題ありません。

于 2013-02-28T11:19:26.680 に答える