首页 > 解决方案 > 如何使我的 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
}

标签: parsinggo

解决方案


如何使我的代码更具可读性?


为了可读性,正确、可维护的代码的先决条件,

// 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


推荐阅读