- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一项作业,但我不知道如何定义答案。
编写函数exp::[String] -> (AST, [String])
AST
:
x
是数字,则应显示 Number x
。Atom x
。 [AST]
。这样输出将是:
exp (token "(hi (4) 32)")
> (List [Atom "hi", List [Number 4], Number 32], [])
exp (token "(+ 3 42 654 2)")
> (List [Atom "+", Number 3, Number 42, Number 654, Number 2], [])
exp (token "(+ 21 444) junk")
> (List [Atom "+", Number 21, Number 444], ["junk"])
我已经有了 token 函数,token::String -> [String]
,它可以创建一个列表。
`token "( + 2 ( + 2 3 ) )"
> ["(","+","2","(","+","2","3",")",")"]`
exp
函数如下所示:
exp :: [String] -> (AST, [String])
exp [] = error "Empty list"
exp (x:xs) | x == ")" = error ""
| x == "(" = let (e, ss') = exp xs in (List [getAst xs], ss')
| x == "+" = let (e, ss') = exp xs in (Atom (read x), ss')
| x == "-" = let (e, ss') = exp xs in (Atom (read x), ss')
| otherwise = exp xs`
其中 getAst
函数:
getAst :: [String] -> AST
getAst [] = error ""
getAst (x:xs)
| x == ")" = error ""
| x == "(" = (List [getAst xs])
| isAtom x = (Atom x)
| isNum x = (Number (read x))
| otherwise = getAst xs`
(是的,我是 Haskell 的初学者..)
最佳答案
我想我可以尽力帮助你。
问题的表现方式你应该能够通过查看下一个来做到这一点输入/ token 并从那里决定去哪里。
数据表示为[String] -> (Ast, [String])
的方式我假设它是一个常见的解析器,其中解析器尝试读取输入的某些部分,并返回解析/转换后的输出以及未转换的输入的其余部分(因此只有元组的两个部分 - Ast
和其余的输入)。
因为您没有包含它,所以我认为它是:
data Ast
= Number Int
| Atom String
| List [Ast]
deriving Show
我需要一些东西:
import Prelude hiding (exp)
import Control.Applicative ((<$>))
import Data.Maybe (fromJust, isJust)
我必须隐藏 exp
因为我们想将其用作函数名称。
然后我想通过 Maybe
进行 fmap
,因此我包含了 Control.Applicative
中的运算符。这实际上就是这样,以防您之前没有看到它:
f <$> Nothing = Nothing
f <$> Just a = Just (f a)
我想要一些帮助也许
:
isJust
检查是否为 Just _
fromJust
从 Just a
获取 a
最后,我需要这个辅助函数来读取
更安全一点:
tryRead :: (Read a) => String -> Maybe a
tryRead input =
case readsPrec 0 input of
(a,_):_ -> Just a
_ -> Nothing
这将尝试在此处读取一个数字 - 如果 n 是数字,则返回 Just n
,否则返回 Nothing
。
这是一个未完成首先解决您的问题:
exp :: [String] -> (Ast, [String])
exp (lookat:rest)
| isJust number = (fromJust number, rest)
| lookat == "(" = parseList rest []
where number = Number <$> tryRead lookat
parseList :: [String] -> [Ast] -> (Ast, [String])
parseList inp@(lookat:rest) acc
| lookat == ")" = (List (reverse acc), rest)
| otherwise = let (el, rest') = exp inp
in parseList rest' (el:acc)
正如你所看到的,我只是基于 lookat
进行分支,但略有不同:
如果我看到一个数字,我会返回该数字和剩余 token 列表。如果我看到 (
,我会启动另一个解析器 parseList
。
parseList
也会做同样的事情: - 它查看第一个 token - 如果 token 是 )
它完成当前列表(它使用累加器技术)并返回。 - 如果不是,它使用现有的 exp
解析器递归地获取列表的元素。
这是一个运行示例:
λ> let input = ["(", "2", "(", "3", "4", ")", "5", ")"]
λ> exp input
(List [Number 2,List [Number 3,Number 4],Number 5],[])
还有一些边界情况需要您决定(如果没有输入标记怎么办?)。
当然,您必须添加 Atom 的情况 - 才能完成此练习。
好的 - 3 小时后,OP 没有再次 checkin ,所以我想我可以发布完整的解决方案。我希望我没有忘记任何边缘情况,并且这肯定不是最有效的实现(想到了 token ) - 但OP给出的示例全部匹配:
module Ast where
import Prelude hiding (exp)
import Control.Applicative ((<$>))
import Data.Char (isSpace, isControl)
import Data.Maybe (fromJust, isJust)
data Ast
= Number Int
| Atom String
| List [Ast]
| Empty
deriving Show
type Token = String
main :: IO ()
main = do
print $ parse "(hi (4) 32)"
print $ parse "(+ 3 42 654 2)"
print $ parseAst . tokens $ "(+ 21 444) junk"
parse :: String -> Ast
parse = fst . parseAst . tokens
parseAst :: [Token] -> (Ast, [Token])
parseAst [] = (Empty, [])
parseAst (lookat:rest)
| isJust number = (fromJust number, rest)
| lookat == "(" = parseList rest []
| otherwise = (Atom lookat, rest)
where number = Number <$> tryRead lookat
parseList :: [Token] -> [Ast] -> (Ast, [Token])
parseList [] _ = error "Syntax error: `)` not found"
parseList inp@(lookat:rest) acc
| lookat == ")" = (List (reverse acc), rest)
| otherwise = let (el, rest') = parseAst inp
in parseList rest' (el:acc)
tokens :: String -> [Token]
tokens = split ""
where split tok "" = add tok []
split tok (c:cs)
| c == '(' || c == ')' = add tok $ [c] : split "" cs
| isSpace c || isControl c = add tok $ split "" cs
| otherwise = split (tok ++ [c]) cs
add "" tks = tks
add t tks = t : tks
tryRead :: (Read a) => Token -> Maybe a
tryRead input =
case readsPrec 0 input of
(a,_):_ -> Just a
_ -> Nothing
λ> :main
List [Atom "hi",List [Number 4],Number 32]
List [Atom "+",Number 3,Number 42,Number 654,Number 2]
(List [Atom "+",Number 21,Number 444],["junk"])
关于parsing - Haskell 中的 AST 和解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26230759/
我正在尝试检查 Go 源代码以制作一个工具。为此,我使用 ast.Inspect 函数。 我需要知道函数/方法内部如何使用 channel 。 我将此作为要检查的示例代码: package main
我正在为我自己的语言制作一个解释器作为一个业余爱好项目。目前我的解释器只是执行它看到的代码。我听说你应该让解析器从源代码生成 AST。所以我想知道,正如解析器所见,AST 实际上如何使事情比仅仅线性执
我正在为 JavaScript 实现一个突变测试工具。修改 AST 并针对修改后的代码执行测试用例。运行测试用例后,我想将修改后的 AST 恢复为原始 AST,以便我可以重复变异过程。但是,我不知道如
AST 文档:https://www.dartdocs.org/documentation/analyzer_experimental/0.8.0/analyzer/parseCompilationU
更新2:再次感谢@deepak-azad,我设法解决了我的问题:这里是主代码的链接:https://gist.github.com/1714641 更新:感谢@deepak-azad,我补充了代码,但
我正在编写一些 Go AST 代码,而编译器在这一行上令人窒息: var call ast.Expr = ast.CallExpr{Fun: ast.NewIdent("foo"), Args: []
我正在对 c 程序进行静态分析。我搜索了 antlr 网站,似乎没有合适的语法文件为 c 程序生成 ast。这是否意味着我必须从一开始就自己做。或者是有一个更快的方法。我还需要一个可以遍历解析器创建的
是否可以像这样采用带引号的 Elixir 表达式(AST 树): quote do: 1 + 1 => {:+, [context: Elixir, import: Kernel], [1, 1]}
我遇到了这个异常: unexpected AST node: query 我的查询是: SELECT u.user_id, u.username,u.email,u.phone,u.status,r
我是 Java 编程语言的初学者。我想从 java 源代码中提取 AST 并将 AST 打印到文件或标准输出。 我按照本教程学习了如何使用 AST。 http://www.programcreek.c
NodeVisitor 以深度优先的方式遍历 AST,并且在进入时仅访问每个节点一次。因此,用它做一些严肃的事情是有问题的。是否可以更改其默认行为? 最佳答案 也许有人会对一些草拟的例子感兴趣,如何做
目前,我正在努力用 Java 表示我用 SML 编写的 AST 树,这样我就可以随时用 Java 遍历它。 我想知道是否应该在 Java 中创建一个 Node 类,其中包含我想要表示的数据,以及一个数
我正在尝试修改/重构输入的 C 源代码。我试图在输入代码的每一行之后添加一个 printf 语句。 例如如果我的输入是 - void foo(){ // Sample input code
我目前正在使用 eclipse AST 来生成源代码。除了在大多数示例中,我是在独立应用程序中从头开始生成源代码,而不是在 eclipse 插件中。 当从 ASTParser 读取时,您可以通过调用
我有一个 HQL 查询: query = select item.itemNumber from items item where item.stock>0 and item.price it = q
根据 Om Next's documentation : query->ast (om.next/query->ast '[(:foo {:bar 1})]) Given a query expres
如果能学到一些有用的东西,我会非常感激,至于现在,我一直在盲目地行动。所以问题出在python的ast.NodeTransformer上。我想知道是否可以使用这种方式向现有类添加一个函数,而不是生气。
我们希望为 Elixir 开发一个静态代码分析器,以检测并发问题(主要是死锁和竞争条件)。我们对分析器的结构有了一些基本的了解,但我们的问题是哪种 AST 更适合这项任务。正如我们所了解的,Elixi
我在以下代码段中遇到错误 using (var session = Database.OpenSession()) { var q = from x in session.Query()
我正在使用以下 C# 代码: public IList GetAllByExpression(Expression> expression, int startIndex, int count, Fu
我是一名优秀的程序员,十分优秀!