[英]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.