parsing - 如何使我的 Go 解析器代码更具可读性
问题描述
我正在用 Go 为一种简单的组合语言编写递归下降解析器,因此我正在设计语法。我的解析器可以工作,但我想问是否有任何最佳实践来说明我应该如何布置我的代码,或者我什么时候应该将代码放在它自己的函数中等等......以使其更具可读性。
我一直在按照我迄今为止学到的简单规则来构建解析器,即。每个非终端都是它自己的功能,即使我的代码有效,我认为看起来真的很混乱且不可读。
我在函数上方包含了赋值非终结符的代码和语法。
我已经去掉了大部分错误处理以保持函数更小。
以下是该代码可以解析的一些示例:
a = 10
a,b,c = 1,2,3
a int = 100
a,b string = "hello", "world"
谁能给我一些关于如何使我的代码更具可读性的建议?
// assignment : variable_list '=' expr_list
// | variable_list type
// | variable_list type '=' expr_list
func (p *Parser) assignment() ast.Noder {
assignment := &ast.AssignmentNode{}
assignment.Left = p.variable_list()
// This if-statement deals with rule 2 or 3
if p.currentToken.Type != token.ASSIGN {
// Static variable declaration
// Could be a declaration or an assignment
// Only static variables can be declared without providing a value
assignment.IsStatic = true
assignment.Type = p.var_type().Value
assignment.Right = nil
p.nextToken()
// Rule 2 is finished at this point in the code
// This if-statement is for rule 3
if p.currentToken.Type == token.ASSIGN {
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
} else {
// This deals with rule 1
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
if assignment.Right == nil {
for i := 0; i < len(assignment.Left); i++ {
assignment.Right = append(assignment.Right, nil)
}
}
if len(assignment.Left) != len(assignment.Right) {
p.FoundError(p.syntaxError("variable mismatch, " + strconv.Itoa(len(assignment.Left)) + " on left but " + strconv.Itoa(len(assignment.Right)) + " on right,"))
}
return assignment
}
解决方案
如何使我的代码更具可读性?
为了可读性,正确、可维护的代码的先决条件,
// assignment : variable_list '=' expr_list
// | variable_list type
// | variable_list type '=' expr_list
func (p *Parser) assignment() ast.Noder {
assignment := &ast.AssignmentNode{}
// variable_list
assignment.Left = p.variable_list()
// type
if p.currentToken.Type != token.ASSIGN {
// Static variable declaration
// Could be a declaration or an assignment
// Only static variables can be declared without providing a value
assignment.IsStatic = true
assignment.Type = p.var_type().Value
p.nextToken()
}
// '=' expr_list
if p.currentToken.Type == token.ASSIGN {
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
// variable_list [expr_list]
if assignment.Right == nil {
for i := 0; i < len(assignment.Left); i++ {
assignment.Right = append(assignment.Right, nil)
}
}
if len(assignment.Left) != len(assignment.Right) {
p.FoundError(p.syntaxError(fmt.Sprintf(
"variable mismatch, %d on left but %d on right,",
len(assignment.Left), len(assignment.Right),
)))
}
return assignment
}
注意:这可能效率低下且过于复杂:
for i := 0; i < len(assignment.Left); i++ {
assignment.Right = append(assignment.Right, nil)
}
是什么类型的assignment.Right
?
推荐阅读
- ios - 在谷歌地图iOS SDK中获取两点之间的方向
- php - PHP 检查编号字符串是否遵循模式
- r - 如何仅删除 R 中所有 NA 的行?
- python - 如何在python中的字符串中使用\
- tensorflow - 预编译的 Tensorflow - 以编程方式获取它所针对的 CUDA 和 CUDNN 版本
- python-3.x - 拆分列表中的字符串
- javascript - 如何在 C# webbrowser 中获取 contentWindow?
- javascript - 使用 d3.js 在某个 div 上的力有向图的绑定节点
- python - 如何从偶数行值中减去奇数行值?
- json - 按日期对 JQ 中的多个对象进行排序/过滤