2016-05-14 14 views
1

Für ein Projekt haben wir die Aufgabe, einen Hakkel-Parser/Evaluator zu erstellen, der einen winzigen Arduino-Roboter steuert.Parsec: Das Erweitern eines funktionierenden Parsers führt zu ungeraden Ergebnissen

Also zu Beginn von, ich habe im Grunde einige Nachforschungen über bereits implementiert Parser-Setups, und stieß auf diese: https://wiki.haskell.org/Parsing_a_simple_imperative_language.

Nachdem (zugegebenermaßen) Kopieren Sie den Code, begann ich es zu testen. Und es hat funktioniert. Jetzt war es an der Zeit, seine Funktionalität zu erweitern.

Edited Code:

data Stmt = Seq [Stmt] 
    | Assign String AExpr 
    | If BExpr Stmt Stmt 
    | While BExpr Stmt 
    | Motor String AExpr 
    | Skip 
     deriving (Show) 

Token.reservedNames = [ "if" 
           , "then" 
           , "else" 
           , "while" 
           , "do" 
           , "skip" 
           , "true" 
           , "false" 
           , "not" 
           , "and" 
           , "or", "set" , "to" 
           ] 
statement' :: Parser Stmt 
statement' = ifStmt 
     <|> whileStmt 
     <|> skipStmt 
     <|> assignStmt 
     <|> motorStatement 

motorStatement :: Parser Stmt 
motorStatement = 
    do reserved "set" 
    var <- identifier 
    reserved "to" 
    expr <- aExpression 
    return $ Motor var expr 

Dies sind die einzigen Teile des Codes I bearbeitet. alles zu testen, habe ich eine kleine testdat:

x := 4; 
x := 6; 

Der obige Code beatifully vor meinen Änderungen analysiert, aber nachdem ich die Änderungen hinzugefügt bekomme ich folgende Fehler

< (line 3, column 1): 
< unexpected end of input 
< expecting "if", "while", "skip", identifier or "set" 

Mit meinem begrenzten Wissen von Haskell kann ich nicht herausfinden, warum das "unexpected end of input" passiert.

Vielleicht kann mir hier ein Haskeller den Fehler zeigen.

Antwort

2

Ich bin nicht davon überzeugt, dass Ihre Eingabe korrekt analysiert wurde, bevor Sie die Änderungen vorgenommen haben. Eine Liste von Aussagen wird analysiert, mit sepBy1:

sequenceOfStmt = 
    do list <- (sepBy1 statement' semi) 
    -- If there's only one statement return it without using Seq. 
    return $ if length list == 1 then head list else Seq list 

sequenceOfStmt, dass gierig ist, wenn es ein Semikolon sieht es erwarten wird eine weitere statement' zu sehen. Daher sollte ein Semikolon als Anweisungstrennzeichen im Gegensatz zu einem Anweisungsabschluss betrachtet werden.

Versuchen Sie, diese Tests laufen, um zu sehen, wie sepBy1 verhält:

import Text.Parsec 
import Text.Parsec.Combinator 

p1 = sepBy1 (char 'a') (char ';') 

test1 = parseTest p1 "a;a"  -- OK 
test2 = parseTest p1 "a;a;"  -- FAILS 

Um dieses Problem zu erforschen, ich die Quelle für die Sprache ParseWhile gesetzt haben auf lpaste.net: http://lpaste.net/163332

+0

Lesen Ihrer Antwort gemacht Ich merke schnell meinen "Fehler". Jedes Semikolon macht es so, dass es eine andere Zeile/Aussage braucht/braucht. Und weil eine leere Zeile nicht in einen Typ konvertiert werden kann, ist sie fehlerhaft. Danke mein Herr! – MrKickkiller