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