簡體   English   中英

解析此BNF時如何刪除某些術語?

[英]How can I remove some terms when parsing this BNF?

我正在嘗試使用Happy庫解析布爾表達式。 問題在於,引入括號后的結果不如我想要的那樣好。 我做了以下語法。

Query       : Expr              { $1 }

Expr        : Expr "OR" Term            { ActOp Or $1 $3 }
            | Expr "AND" Term           { ActOp And $1 $3 }
            | Term                      { Term $1 }


Term        : '"' string '"'            { QuotedWord $2 }
            | string                    { Word $1 }
            | '(' Expr ')'              { Brack $2}

以下是要分析的字符串和結果。

"(computer AND science) OR cs" -> ActOp Or (Term (Brack (ActOp And (Term (Word "computer")) (Word "science")))) (Word "cs")

我希望它像下面這樣,因為它更容易解釋:

ActOp Or (ActOp And (Word "computer") (Word "science")) (Word "cs")

編輯-完整代碼

{
module BoolAst where
import Data.Char
import Data.List
}

%name translate
%tokentype { Token }

%token 
      string            { TokenString $$ }
      '"'               { TokenQuote}
      "AND"             { TokenAnd }
      "OR"              { TokenOr }
      '('               { TokenOb }
      ')'               { TokenCb }

%%

Query       : Expr                      { $1 }

Expr        : Expr "OR" Term            { ActOp Or $1 $3 }
            | Expr "AND" Term           { ActOp And $1 $3 }
            | Term                      { Term $1 }


Term        : '"' string '"'            { QuotedWord $2 }
            | string                    { Word $1 }
            | '(' Expr ')'              { Brack $2}


{
happyError :: [Token] -> a
happyError _ = error ("Parse error\n")

type Query 
        = Expr

data Expr 
        = ActOp Op Expr Term
        | Term Term
        deriving Show

data Op
        = Or
        | And
        deriving Show

data Term
        = QuotedWord String
        | Word String
        | Brack Expr
        deriving Show

data Token
      = TokenQuote
      | TokenAnd
      | TokenOr
      | TokenString String
      | TokenOb
      | TokenCb
 deriving Show


lexer :: String -> [Token]
lexer [] = []
lexer cs
      | isPrefixOf "AND" cs = TokenAnd : (lexer $ drop 3 cs)
      | isPrefixOf "OR" cs = TokenOr : (lexer $ drop 2 cs)
lexer (c:cs) 
      | isSpace c = lexer cs
      | isAlpha c = lexVar (c:cs)
lexer ('"':cs) = TokenQuote : lexer cs
lexer ('(':cs) = TokenOb : lexer cs
lexer (')':cs) = TokenCb : lexer cs

lexVar cs =
   case span isAlphaNum cs of
    (var,rest)   -> TokenString var : lexer rest

main = print $ translate . lexer $ "computer AND science OR cs"

您的數據類型不必直接對應於語法規則。 讓Term nonterminal產生Expr值是完全有效的。 例如

data Expr 
    = ActOp Op Expr Expr
    | QuotedWord String
    | Word String
    deriving Show

...

Expr        : Expr "OR" Term            { ActOp Or $1 $3 }
            | Expr "AND" Term           { ActOp And $1 $3 }
            | Term                      { $1 } -- no need to wrap in a constructor

Term        : '"' string '"'            { QuotedWord $2 }
            | string                    { Word $1 }
            | '(' Expr ')'              { $2 } -- no need to wrap in a constructor

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM