【发布时间】:2011-05-06 08:24:42
【问题描述】:
情况:
我已经为一种很少使用的编程语言(我的一个爱好项目)制作了一个扫描器、解析器和各种 AST 类。解析器在扫描仪的帮助下构建了一个异构 AST,我对其进行了一些操作。在过去,我为一些 IDE 创建了一个插件/加载项,用于语法高亮和一些其他元素。
问题在于错误:解析器生成一些并可以访问构成语句的标记。然而,一些错误只会在以后出现,例如无法解析标识符。我想在此类标识符或其他错误标记下显示曲线。不仅如此,我喜欢在不丢失原始文档中所有 cmets、间距等的情况下操纵 AST 节点的能力。
在我的 AST 中创建新语句时,我可以轻松地将构成该语句的标记添加为子项。但是……
问题:
如果合理可行,我希望包括对显示曲线的支持。这需要一个语句知道组成语句的标记的位置。不幸的是,一个语句有变体,有时包含更多的标记,有时包含更少的标记。如果我正在制作只读 AST,这将不是问题。但是,我希望我的 AST 可以读写以进行重构!这意味着更改 AST 中的语句本质上意味着添加标记(语句的子级),因此 Statement 类应该能够自我解析。
这会污染 AST 解析代码并且不再保持关注点分离!
技术细节:
另一种方法是将 AssignmentStatement 变成一个工厂,获取一组标记,生成语句的一个实例,并不断让它知道自己的标记。
在我的情况下,用于分配的 AST 节点目前基本上是这样的:
分层样本 AST 可以是:
AssemblyDeclaration
.. Statement ..
.. Statement ..
ClassDeclaration
.. Token .. // one or more that make up the entire class statement
.. Token .. // one or more that make up the entire class statement
Statement(s)
.. Token .. // Which have their own tokens that make up the statement .. and possibly have sub-nodes of their own such as Expressions which have -their- own Tokens that comprise it.
基本 ast 节点的概念性想法,语法树中所有内容的父节点,无论它是类声明、语句还是标记。
public abstract class BaseAstNode : IList<BaseAstNode>
{
... implementation of IList<BaseAstNode>
... implementation of Visitor Pattern
... implementation of Clonable
}
public sealed class AssignmentStatement : BaseAstNode
{
public Expression Expression { get; set; }; // Setting this will alter the Tokens (children!) of this node, possibly even ADD Tokens!
public TypeReference Target { get; set; }
}
public sealed class PrimitiveNumberExpression : Expression // is a BaseAstNode
{
public int Value { get; set; } // Setting this will alter the Tokens (children!) of this node!
}
public abstract class Token : BaseAstNode
{
public Layers Layer { get; set; }
public TokenType TokenType { get; set; }
public int Column { get; set; }
public int Line { get; set; }
public int Position { get; set; }
public abstract int Length { get; set; }
public virtual string Value { get; set; }
public override string ToString(){}
}
其他人如何解决这个问题?这是正确的方法吗?
【问题讨论】:
-
你当前的代码是如何构造AssignmentStatement对象的?
-
var stmt = new AssignmentStatement { Expression = Expression.Null, Target = TypeReference.Null }; .. 只有解析器产生的表达式和引用。
-
我想我的问题是如何为成员填充数据,为什么类也不能填充起始和长度值?
-
语句是语法树的一部分,由解析器填充。每个语句都可以轻松获得开始和结束标记。但是我仍然不能在我的标识符下面加上波浪线,除非我开始跟踪语句组成的所有标记和 -their- 的位置。
标签: c# .net parsing abstract-syntax-tree