2015-08-14 2 views
0

J'essayais de faire un analyseur d'expression pour deux opérateurs dont seul ^ est postfixe unaire, donc avec un opérande cela ressemblerait à R^.Analyseur d'expression pour opérateur unaire

Le problème est que chaque fois que l'opérateur ^ est rencontré ailleurs que dans la fin, il s'arrête juste là et renvoie tout ce qui a été analysé avec succès. Cela signifie "R;S;T^" analyse avec succès, mais "R^;S;T^" s'arrête à R. Cependant, "(R^);S;T^" fonctionne bien.

J'ai pris l'aide d'un poste en ligne qu'il utilisait pour moins unaire mais c'est un opérateur de préfixe (par exemple -X). Sa solution originale donnait des erreurs à reservedOp2, donc je l'ai modifié à reservedOp2 name = try (string name >> notFollowedBy (oneOf opChar)) et il produit la sortie mentionnée ci-dessus. J'en ai besoin pour travailler avec ou sans parenthèse.

import Control.Applicative 
import Text.ParserCombinators.Parsec hiding (many,optinal,(<|>)) 
import Text.ParserCombinators.Parsec.Expr 
import Text.Parsec.Language (haskell) 
import qualified Text.Parsec.Token as P 
import Text.Parsec.String (Parser) 

data RT = Comp RT RT   
     | Conv RT   
     | Var String 
     deriving (Show) 

whiteSpace = P.whiteSpace haskell 
word = P.identifier haskell 
parens = P.parens haskell 
opChar = "^;" 

reservedOp2 :: String -> CharParser st() 
reservedOp2 name = try (string name >> notFollowedBy (oneOf opChar) >> whiteSpace) 


term = parens relexpr 
     <|> Var <$> word 
     <?> "term" 

table = [ [postfix "^" Conv] 
     , [binary ";" Comp AssocLeft] 
     ] 

prefix name fun = Prefix $ reservedOp2 name >> return fun 
binary name fun = Infix $ reservedOp2 name >> return fun 
postfix name fun = Postfix $ reservedOp2 name >> return fun 

relexpr :: Parser RT 
relexpr = buildExpressionParser table term <?> "expression" 
+0

Votre définition de 'term' est-elle correcte? Ne devrait-il pas ressembler à parens relexpr <|> ... mot Var ... "terme" '? (Commentaire sur 'binary' et assoc supprimés) – ErikR

+0

@ user5402 Je pense que le terme est correctement défini, le problème est dans le reservedOp2. C'est le code complet. – Wazed

Répondre

1

Il échoue à analyser, par ex. "R^;S" car postfix "^" Conv échoue sur notFollowedBy (oneOf opChar) (puisque '^'est suivi de ';'). La solution est de retirer ';' de opChar:

opChar = "^" 

Ou, encore plus facile si vous pouvez simplement utiliser reservedOp de haskell:

reservedOp2 = P.reservedOp haskell 

Chacune de ces changements fixe l'analyse syntaxique de vos exemples.