我需要使用 Roslyn 转换某个类的所有属性。
在不使引用无效的情况下对语法树应用多个转换的推荐方法是什么?
这是我尝试过的以及我陷入困境的地方:
在第一遍中, 的后代CSharpSyntaxWalker访问所有PropertyDeclarationSyntax节点,并将它们存储在列表中。
在第二遍中,aCSharpSyntaxRewriter正在转换节点,同时在转换之前检查每个访问的节点是否等于列表中的 1。
我的尝试的问题是:当我转换属性时,我向类添加新字段,这会导致类发生变化。列表中对其他属性的所有引用在该类的新树中变得无效。
重新访问整个类似乎效率很低,而且无论哪种方式,由于引用差异,我都无法检测到已经处理的属性节点。
抽象语法树中存在哪些类型信息?如何使用 AST 进行类型推断?我不明白当没有节点指示具体类型时,如何在给定 AST 的情况下导出类型输入和输出。类型是仅从树结构推断出来的吗?例如有一堆IfStatement(Statement),所以它可能会返回一个 bool ?例如,javalang python 模块使用以下 AST 节点:
CompilationUnit(Node)
Import(Node)
Documented(Node)
Declaration(Node)
Type(Node)
TypeArgument(Node)
TypeParameter(Node)
Annotation(Node)
ElementValuePair(Node)
ElementArrayValue(Node)
ArrayInitializer(Node)
VariableDeclarator(Node)
InferredFormalParameter(Node)
Statement(Node)
SwitchStatementCase(Node)
ForControl(Node)
EnhancedForControl(Node)
Expression(Node)
EnumBody(Node)
VariableDeclaration(Declaration)
FormalParameter(Declaration)
TryResource(Declaration)
CatchClauseParameter(Declaration)
AnnotationMethod(Declaration)
BasicType(Type)
ReferenceType(Type)
TypeDeclaration(Declaration, Documented)
PackageDeclaration(Declaration, Documented)
ConstructorDeclaration(Declaration, Documented)
EnumConstantDeclaration(Declaration, Documented)
ClassDeclaration(TypeDeclaration)
EnumDeclaration(TypeDeclaration)
InterfaceDeclaration(TypeDeclaration)
AnnotationDeclaration(TypeDeclaration)
Member(Documented)
MethodDeclaration(Member, Declaration)
FieldDeclaration(Member, Declaration)
ConstantDeclaration(FieldDeclaration)
LocalVariableDeclaration(VariableDeclaration)
IfStatement(Statement)
WhileStatement(Statement)
DoStatement(Statement)
ForStatement(Statement)
AssertStatement(Statement)
BreakStatement(Statement)
ContinueStatement(Statement)
ReturnStatement(Statement)
ThrowStatement(Statement)
SynchronizedStatement(Statement)
TryStatement(Statement)
SwitchStatement(Statement)
BlockStatement(Statement)
StatementExpression(Statement)
CatchClause(Statement)
Assignment(Expression)
TernaryExpression(Expression)
BinaryOperation(Expression)
Cast(Expression)
MethodReference(Expression)
LambdaExpression(Expression)
Primary(Expression) …Run Code Online (Sandbox Code Playgroud) 所以我正在为我正在制作的类似于 Python 的语言制作一个解释器。现在我明白这不是一个小任务,我不希望它工作得很好或做很多事情,但我希望它有一些基本功能(变量、函数、循环、if 语句等......)。
所以目前我正处于解释器获取文件并将其拆分为令牌列表的阶段,现在我准备将这些令牌转换为 AST。我打算用递归下降解析器来做到这一点,我相信我理解,但这就是问题。假设我有以下输入
1 + 2 * 3
Run Code Online (Sandbox Code Playgroud)
这将输出 7,因为使用 BIDMAS 首先完成乘法,所以
2 * 3 = 6
Run Code Online (Sandbox Code Playgroud)
然后添加完成后
1 + 6 = 7
Run Code Online (Sandbox Code Playgroud)
我知道如何获得这个订单,因为我有一个简单的语法,但我不知道如何将其存储为 AST。为了简化答案,我们假设这是您将收到的唯一输入,并且语法可以是
program = add
add = mul {"+" mul}
mul = NUM {"*" NUM}
Run Code Online (Sandbox Code Playgroud)
那么基本上,如何创建一个数据结构来存储 AST?
PS我是用C做的。
c compiler-construction grammar interpreter abstract-syntax-tree
我想找到此脚本中没有任何父级的调用表达式:
1 + 1
function parent() {
2 + 2
}
3 + 3
Run Code Online (Sandbox Code Playgroud)
这里我想获取1 + 1和3 + 3节点,但不是2 + 2。
我想要实现的目标是:
j(file.source).find(j.ExpressionStatement, {
parent: null
});
Run Code Online (Sandbox Code Playgroud)
那么是否有一个过滤器可以查找表达式是否有父级?
是否有一种工具能够迭代 Python 文件中的所有变量和函数参数并根据样式规则替换它们?例如,给定一个函数myModule.py
def myFunc(Variable):
Tmp = sin(Variable)
return Tmp * 2
Run Code Online (Sandbox Code Playgroud)
是否有一个工具可以通过如下方式调用
> tool myModule.py --variable-begin-with-lowercase
产生下面的结果?
def myFunc(variable):
tmp = sin(variable)
return tmp * 2
Run Code Online (Sandbox Code Playgroud)
我想,该工具应该警告干扰现有变量的重命名。
由于 TSLint 已被弃用,我正在将项目转换为使用 ESLint。
我想设置我的缩进规则以允许这样做:
type HtmlColor = 'attrib' | 'background' | 'bg_whitespace' | 'comment' | 'entity' | 'error' | 'foreground' |
'invalid' | 'markup' | 'tag' | 'value' | 'warning' | 'whitespace';
Run Code Online (Sandbox Code Playgroud)
我目前收到关于第二行缩进的错误,它应该是 0 个空格而不是 17 个。我可能预计该错误会抱怨它不是 2 个空格,但肯定不是 0。
无论如何,如果我无法获得我想要识别的特定缩进,我至少希望在这种情况下忽略缩进。
我尝试使用ignoredNodesESLintindent规则的选项来修复此问题,如下所示:
"@typescript-eslint/indent": [
"error",
2,
{
"ArrayExpression": "first",
"FunctionDeclaration": { parameters: "first" },
"ignoredNodes": [
"ArrowFunction > Block",
"NoSubstitutionTemplateLiteral",
"TemplateLiteral",
"TypeAliasDeclaration *"
],
"ObjectExpression": "first",
"VariableDeclarator": "first",
"SwitchCase": 1
}
],
Run Code Online (Sandbox Code Playgroud)
我可以看到列表的一部分ignoredNodes …
背景
我正在处理的项目的一部分要求我分析 Q# 源代码并在遇到某些语法元素时执行特定操作。例如,假设我想计算整个程序中使用了多少种不同的门类型。现在,这可以通过遍历程序的抽象语法树并根据当前语法节点执行操作来实现。
我试过的
我首先分析了qsharp-compiler存储库,但是,编译器的内部工作方式缺乏在线文档,浏览所有 C# 和 F# 源代码非常乏味。
当然,我可以为该语言编写自己的解析器,但这对于手头的任务来说可能是一种矫枉过正。有有一个方法可以从编译器的内部提取AST。
问题
有没有办法以编程方式使用 Q# 编译器(从 C# 或 F#)编译 Q# 源代码,并提取内部 AST?
如果我运行以下 common lisp 代码:
(print "A")
(print "B")
(print "C - No closing bracket"
Run Code Online (Sandbox Code Playgroud)
sbcl --script ./test.lisp
打印A和B。之后错误就像预期的那样出现。
SBCL是否解析第一行(或者换句话说“括号内的代码”)并在进入下一部分之前立即执行它?或者它是否解析整个文件并“标记”AST 中的特定点存在解析器错误?
我想从以JSON格式给出的AST构建控制流图(CFG).所以这个AST是在TouchDevelop中针对每个脚本自动创建的.而且由于TouchDevelop不是面向对象的编程,我还可以使用访问者模式吗?任何有用的指针将不胜感激.
Update1:我的问题是我不明白从哪里开始.从互联网上,我应该使用访问者模式来浏览AST以访问每个节点并收集信息.从那里,我可以构建一个CFG,然后进行数据流分析.但有两个问题:
1)据我所知,我需要面向对象的编程模型,使用访问者模式,(我可能是错的),这TouchDevelop不是.
2)如下所示,AST不是AST格式,正如我在互联网上找到的那样.它是JSON格式.我想我可以解析JSON将其转换为所需的AST结构,但我不太确定.
示例脚本的源代码
meta version "v2.2,nothing";
meta name "DivideByZero";
//
meta platform "current";
action main() {
(5 / 0)?post_to_wall;
}
Run Code Online (Sandbox Code Playgroud)
产生的AST(JSON格式)如下:
{
"type":"app",
"version":"v2.2,nothing",
"name":"DivideByZero",
"icon":null,
"color":null,
"comment":"",
"things":[
{
"type":"action",
"name":"main",
"isEvent":false,
"outParameters":[
],
"inParameters":[
],
"body":[
{
"type":"exprStmt",
"tokens":[
{
"type":"operator",
"data":"("
},
{
"type":"operator",
"data":"5"
},
{
"type":"operator",
"data":"/"
},
{
"type":"operator",
"data":"0"
},
{
"type":"operator",
"data":")"
},
{
"type":"propertyRef",
"data":"post to wall"
}
]
}
],
"isPrivate":false
}
]
}
Run Code Online (Sandbox Code Playgroud) procedural-programming static-analysis abstract-syntax-tree touchdevelop control-flow-graph
我想在Python中使用一个函数将字符串命令转换为AST(抽象语法树).
该命令的语法如下:
commandName(3, "hello", 5.0, x::int)
Run Code Online (Sandbox Code Playgroud)
命令可以接受任意数量的逗号分隔值
假设函数被调用convert_to_ast,那么
convert_to_ast('commandName(3, "hello", 5.0, x::int)')
Run Code Online (Sandbox Code Playgroud)
应该产生以下AST:
{
'type': 'command',
'name': 'commandName',
'args': [{
'type': 'int',
'value': 3
}, {
'type': 'str',
'value': 'Hello'
}, {
'type': 'float',
'value': 5.0
}, {
'type': 'var',
'kind': 'int',
'name': 'x
}]
Run Code Online (Sandbox Code Playgroud) parsing ×3
c# ×2
javascript ×2
python ×2
c ×1
common-lisp ×1
eslint ×1
grammar ×1
interpreter ×1
jscodeshift ×1
pyparsing ×1
q# ×1
roslyn ×1
sbcl ×1
touchdevelop ×1
types ×1
typescript ×1