2016-05-04 11 views
1

Ich versuche, einfache Ausdrücke zwischen Schrägstrichen zu analysieren. Beispiel: / 1+2*3 / sollte zu 7 ausgewertet werden.Parsec: Ausdruck zwischen Schrägstrichen analysieren

Ich habe versucht, diese

module Test where 

import Text.Parsec 
import Text.Parsec.Language (emptyDef) 
import Text.Parsec.Combinator (between) 
import Text.Parsec.String (Parser) 

import qualified Text.Parsec.Expr as Ex 
import qualified Text.Parsec.Token as Tok 

lexer :: Tok.TokenParser() 
lexer = Tok.makeTokenParser style 
    where 
    ops = ["+","*","-","/",";"] 
    names = ["def","extern"] 
    style = emptyDef { 
       Tok.commentLine = "#" 
      , Tok.reservedOpNames = ops 
      , Tok.reservedNames = names 
      } 

integer :: Parser Int 
integer = fromIntegral <$> Tok.integer lexer 

parens :: Parser a -> Parser a 
parens = Tok.parens lexer 

braces :: Parser a -> Parser a 
braces = Tok.braces lexer 

slashes :: Parser a -> Parser a 
slashes = between (reserved "/") (reserved "/") 

reserved :: String -> Parser() 
reserved = Tok.reserved lexer 

reservedOp :: String -> Parser() 
reservedOp = Tok.reservedOp lexer 

binary s f assoc = Ex.Infix (reservedOp s >> return f) assoc 
table = [[binary "*" (*) Ex.AssocLeft, 
      binary "/" div Ex.AssocLeft] 
     ,[binary "+" (+) Ex.AssocLeft, 
      binary "-" (-) Ex.AssocLeft]] 

factor :: Parser Int 
factor = try integer 
     <|> parens expr 

expr :: Parser Int 
expr = Ex.buildExpressionParser table factor 

programInSlashes :: Parser Int 
programInSlashes = slashes expr 

programInBraces :: Parser Int 
programInBraces = braces expr 

die für programInBraces in Ordnung funktioniert:

*Test> parse programInBraces "" "{ 1+2*3/4 }" 
Right 2 

jedoch programInSlashes scheitern wird:

*Test> parse programInSlashes "" "/ 1+2*3/4 /" 
Left (line 1, column 12): 
unexpected end of input 
expecting end of "/", integer or "(" 

Klar das Problem ist, dass / ist sowohl ein Operator und das Trennzeichen für das Programm selbst. Aber da die Sprache nicht zweideutig ist, sollten wir in der Lage sein, das zu analysieren, oder?

Antwort

2

Ich denke, Sie können Text.Parsec.Expr verwenden, um den inneren Ausdruck zu analysieren; dann können Sie für den / Fall zum Beispiel Rückzieher einbetten:

Infix (try $ do { reserved "/"; notFollowedBy eof; return div }) AssocLeft 

Sie können auch die äußeree Sprache und den Inneren Ausdruck in getrennten Durchgängen analysieren. Ich habe dies in einem Compiler für eine Sprache mit benutzerdefinierten Operatoren getan: zuerst das Programm analysieren, ohne Infix-Ausdrücke zu berühren, dann einen weiteren Durchlauf ausführen, um Infix-Ausdrücke gemäß den Operatoren im Bereich zu analysieren.

+0

Tut mir leid, ich muss das jetzt nur ausprobieren. Ich kann es leider nicht funktionieren, sagt noch 'parse programInSlashes" ""/1 + 2 * 3/4 ​​/ " Links (Zeile 1, Spalte 10): unerwartet '4' erwartet Ende von"/" ' –

Verwandte Themen