module Example3 where import ParserCombinators import Char -- Abstrakte Syntax, wie gehabt. data Expr = Plus Expr Expr | Times Expr Expr | Var String deriving (Eq, Show) -- Token: entweder eine Variable, oder ein einzelnes Zeichen data Token = TokVar String | TokSym Char deriving (Eq, Show) -- Der Lexer: entfernt Leerzeichen, fasst Sequenzen von Buchstaben -- zu Variablen-Token zusammen. lexer :: String-> [Token] lexer [] = [] lexer (x:xs) | isSpace x = lexer xs | isAlpha x = let (more, rest)= span isAlpha xs in TokVar (x:more) : lexer rest | otherwise = TokSym x : lexer xs -- Zwei Hilfsfunktionen für den Lexer: isVar :: Token-> Bool isVar (TokVar _) = True isVar _ = False isSymbol :: Char-> Token-> Bool isSymbol c (TokSym d) = c == d isSymbol c _ = False -- Der eigentliche Parser. -- Die Typ ändern sich zu Parser Token Expr: pExpr :: Parse Token Expr pExpr = pTerm >* spot (isSymbol '+') >*> pExpr `use2` Plus `alt` pTerm pTerm :: Parse Token Expr pTerm = pFactor >* spot (isSymbol '*') >*> pTerm `use2` Times `alt` pFactor pFactor :: Parse Token Expr pFactor = spot isVar `use` (\(TokVar name)-> Var name) `alt` spot (isSymbol '(') *> pExpr >* spot (isSymbol ')') -- Die Hauptfunktion. Ruft zuerst den Lexer, und damit den Parser auf; -- der Rest bleibt. parse :: String-> Expr parse i = case filter (null. snd) (pExpr (lexer i)) of [] -> error "Input does not parse." [(e, _)] -> e _ -> error "Input is ambiguous."