试图将字符串解析为抽象语法树
这是我在BNF中使用的语法
<Block> ::= <Expr>;
<Expr> ::= <Number> | <App>
<App> ::= (<Expr>, <Expr>) <Func>
<Func> ::= + | - | * | \
<Number> ::= <Digit> | <Digit><Number>
<Digit> ::= 0 | 1 | .... | 9
我必须使用它:
data Ast = Number Integer | Func String | App Ast [Ast] | Block [Ast]
我写了一个tokenize方法(可能没有完全完成,但给出了正确的想法)
tokenize :: String -> [String]
tokenize [] = []
tokenize xs @ (x : xs')
| x `elem` t = [x] : tokenize xs'
| isDigit x = [y | y <- takeWhile isDigit xs] : (tokenize (dropWhile isDigit xs))
| otherwise = tokenize xs'
where t = ['+', '-', '*', '/', '(', ')', ';']
我坚持使用parseApp函数。对我来说,如何使用模式匹配并不是很明显,我也没有看到任何其他方法(使用我非常有限的haskell经验)
parse :: String -> Ast
parse xs = parseBlock (tokenize xs)
parseBlock :: [String] -> (Ast, [String])
parseBlock xss = let (a, b) = parseExpr (init xss) in (Block [a], b)
parseExpr :: [String] -> (Ast, [String])
parseExpr xss @ (xs : xss')
| all isDigit xs = (Number (read xs :: Integer), xss')
| otherwise = parseApp xss
parseApp :: [String] -> (Ast, [String])
parseApp xss = -- ...
如果输入字符串是
"((10, 2)- , (0, 2)-)+;"
它应该标记为
["(", "(", "10", ",", "2", ")", "-", ",", "(", "0", ",", "2", ")", "-", ")", "+", ";"]
那将成为
(Block [ App (Name "+") [App (Name "-") [Number 10, Number 2], App (Name "-") [Number 0, Number 2]]], [])
这是一项任务,所以我不能改变类型等等。我应该假设给定的输入具有正确的语法。我在这里读过类似的线索,但答案似乎假设了更高层次的理解