我说"实时代码"因为我的意思不是来自文本源文件或源字符串,而是来自partialFunctions/lambdas.(我知道Ruby1.8的parseTree和C#linq可以做到)
考虑一个partialFunction f:
val f = (i: Int, j: Int) => (i + j) * 2
Run Code Online (Sandbox Code Playgroud)
我希望有一些工具像这样:
getBodyAstFrom(f) //=> (Infix('*'), (Infix('+'), Id('i'), Id('j')), Val('2'))
Run Code Online (Sandbox Code Playgroud)
我不关心语义事物(上下文解析和implicits太复杂,对我来说是不必要的),我只需要实时代码的语法树,是否可能?
检查其他人的代码可能存在问题,但我自己的代码呢?以下事情可能吗?
val f = AstFunction(i: Int, j: Int){(i + j) * 2}
f(5, 6) //=> 22
f.ast //=> (Infix('*'), (Infix('+'), Id('i'), Id('j')), Val('2'))
Run Code Online (Sandbox Code Playgroud)
它似乎需要一些黑客入侵编译器,嗯......
在Python 2.7中的新功能文档中,它表示对集合文字的支持是从Python 3.1反向移植的.但是,似乎这种支持没有扩展到ast模块的literal_eval()功能,如下所示.
这是故意的,疏忽的还是其他的 - 从字符串表示创建文字集的最简洁的解决方法是什么?(我假设以下工作在Python 3.1+中,对吧?)
import ast
a_set = {1,2,3,4,5}
print a_set
print ast.literal_eval('{1,2,3,4,5}')
Run Code Online (Sandbox Code Playgroud)
输出显示错误消息:
set([1, 2, 3, 4, 5])
Traceback (most recent call last):
File "...\setliterals.py", line 4, in <module>
print ast.literal_eval('{1,2,3,4,5}')
File "...\Python\lib\ast.py", line 80, in literal_eval
return _convert(node_or_string)
File "...\Python\lib\ast.py", line 79, in _convert
raise ValueError('malformed string')
ValueError: malformed string
Run Code Online (Sandbox Code Playgroud)
PS我能想到的唯一解决方法就是使用eval().
我想获得一个用于C++的AST,然后我可以使用外部程序进行解析.哪些程序适合为C++生成AST?我不关心它实现的语言或输出格式(只要它易于解析).
我的总体目标是将C++单元测试台转换为相应的C#包装器测试台.
我可以使用recursivevisitor类遍历clang AST的特定子树,但我想要做的是按节点遍历clang AST节点.
如果有人能帮助我,我真的很感激.
提前致谢.
我正在使用Python 3中的抽象语法树.该ast库提供了许多方法来获取节点的子节点(您可以使用iter_child_nodes()或walk())但没有办法获得一个父节点.此外,每个节点都有指向其子节点的链接,但它没有指向其父节点的链接.
如果我不想给ast库写一些插件,我怎么能得到AST节点的父节点?
这样做最正确的方法是什么?
以下是使用ast和symtable 包的Python代码段.我试图解析代码并检查类型.但我不明白如何遍历对象以获取被引用的实际变量.
下面的代码实现了一个NodeVisitor,并且一个函数被呈现给编译器并由编译器和ast走了.正在分析的函数(eval_types)传递了几个对象.
下面是构成示例的代码块.我为每个块添加了一些注释.要运行代码,需要重新组装"块".
导入和用于解压缩代码块的函数.
import inspect
import ast
import symtable
from tokenize import generate_tokens, untokenize, INDENT
from cStringIO import StringIO
# _dedent borrowed from the myhdl package (www.myhdl.org)
def _dedent(s):
"""Dedent python code string."""
result = [t[:2] for t in generate_tokens(StringIO(s).readline)]
# set initial indent to 0 if any
if result[0][0] == INDENT:
result[0] = (INDENT, '')
return untokenize(result)
Run Code Online (Sandbox Code Playgroud)
以下是节点访问者,它具有通用的未处理和名称访问者重载.
class NodeVisitor(ast.NodeVisitor):
def __init__(self, SymbolTable):
self.symtable = SymbolTable
for child in SymbolTable.get_children():
self.symtable = …Run Code Online (Sandbox Code Playgroud) 我正在使用scala编写玩具编译器.目标语言本身看起来像scala,但它是一个开放的实验领域.
在几次大型重构之后,我找不到一种模拟抽象语法树的好方法.我想使用scala模式匹配的设施,问题是树在编译过程中携带移动信息(如类型,符号).
我可以看到几个解决方案,我都不喜欢它们:
具有可变字段的case类(我相信scala编译器会这样做):问题是这些字段不存在于编译的每个阶段,因此必须被置为空(或者选项)并且调试/它变得非常繁重写代码.此外,如果例如,我在键入阶段后找到一个空类型的节点我很难找到错误的原因.
巨大的特质/案例类层次结构:像Node,NodeWithSymbol,NodeWithType,......似乎很难写和使用
完全用提取器手工制作的东西
我也不确定使用完全不可变的AST是否是一个好习惯,特别是在scala中没有隐式共享(因为编译器不知道不变性)并且它可能会损害性能以便始终复制树.
你能想到使用scala强大的类型系统来模拟我的树的优雅模式吗?
具体来说,我们有一个像这样的C++源文件:
template <int n>
struct N {};
struct B {
template <typename M>
using A = typename std::conditional<std::is_same<M, N<4>>::value,
int*, void*>::type;
};
template <typename T, T value>
struct F : B {};
template <>
struct F<decltype(&fopen), &fopen> : B {
template <typename M>
using A = double*;
};
template <>
struct F<decltype(&fclose), &fclose> : B {
template <typename M>
using A = typename std::conditional<std::is_same<M, N<16>>::value,
void*, char**>::type;
};
// More specialization of 'F' follows.
Run Code Online (Sandbox Code Playgroud)
这是很容易找到ClassTemplateDecl第N和F …
我正在用clang进行程序间数据流分析.目前我正在使用libtooling来解析源文件并调用AST访问者.问题是如何为几个.c文件创建单个AST?
我曾尝试使用ASTImport类,但它不支持导入某些AST节点.而且,当我创建和操作CompilerIstance并且它在析构函数中崩溃时,我做错了什么.
一个非常相似的选项是ASTImportAction,但在这种情况下我不太清楚哪些命令行参数应传递给ClangTool.
第三种选择是为每个.c文件创建ASTUnits并在每个文件中查找定义,不清楚如何找到用户定义类型之间的对应关系,例如记录.在ASTImport中,它们使用IsStructurallyEquivalent()函数,但它在匿名命名空间中声明,因此我只能将所有这些代码复制到我的程序中.并且它再次支持不是所有AST节点.
从互联网上链接http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-August/023865.html似乎是最合适的,但对我来说,解决方案的技术细节并不清楚.
欢迎任何建议.非常感谢.
我试图根据我在网上阅读的一些有用的文献,使用Free monad构建AST.
我有一些关于在实践中使用这些AST的问题,我已经归结为以下示例.
假设我的语言允许以下命令:
{-# LANGUAGE DeriveFunctor #-}
data Command next
= DisplayChar Char next
| DisplayString String next
| Repeat Int (Free Command ()) next
| Done
deriving (Eq, Show, Functor)
Run Code Online (Sandbox Code Playgroud)
我手动定义了Free monad样板:
displayChar :: Char -> Free Command ()
displayChar ch = liftF (DisplayChar ch ())
displayString :: String -> Free Command ()
displayString str = liftF (DisplayString str ())
repeat :: Int -> Free Command () -> Free Command ()
repeat times block = liftF (Repeat times …Run Code Online (Sandbox Code Playgroud)