Go关键字的一次汉化过程

ivansli 2021/11/16 880℃ 0

1. 为什么写本文

笔者在自己的原创文章 [关于中文编程的一些思考]中,有一段关于go的中文代码,并且还能正常执行。

可能有些小伙伴看到之后,在自己的电脑上也执行了同样的代码却报错,原因就是:还需要对部分源码进行修改。这里,笔者就整理了一下操作的步骤。

2. 源码修改步骤

拉取Go源代码

git clone https://github.com/golang/go.git

从GitHub拉取Go源代码的好处是:拉取的源码中包含了多个版本分支,可以切换到自己想要的版本。

切换到编译的版本

cd go
git branch -a
git checkout -b go1.14 origin/dev.boringcrypto.go1.14

笔者这里是在go1.14的基础上进行的关键字汉化,你可以选择自己想要的版本。

添加中文关键字

文件:go\src\go\token\token.go

// 添加中文关键字数组
// 这里笔者仅汉化了IF ELSE
var tokens_cn = [...]string{
    BREAK:    "break",
    CASE:     "case",
    CHAN:     "chan",
    CONST:    "const",
    CONTINUE: "continue",

    DEFAULT:     "default",
    DEFER:       "defer",
    ELSE:        "否则",
    FALLTHROUGH: "fallthrough",
    FOR:         "for",

    FUNC:   "func",
    GO:     "go",
    GOTO:   "goto",
    IF:     "如果",
    IMPORT: "import",

    INTERFACE: "interface",
    MAP:       "map",
    PACKAGE:   "package",
    RANGE:     "range",
    RETURN:    "return",

    SELECT: "select",
    STRUCT: "struct",
    SWITCH: "switch",
    TYPE:   "type",
    VAR:    "var",
}

func init() {
    keywords = make(map[string]Token)
    for i := keyword_beg + 1; i < keyword_end; i++ {
        keywords[tokens[i]] = i
        keywords[tokens_cn[i]] = i  // 关键!把自定义的中文关键字添加进来
    }
}

笔者这里仅汉化了IF/ELSE,如果想汉化其他的关键字可以在tokens_cn数组进行修改即可。

文件:go\src\cmd\compile\internal\syntax\scanner.go

// 添加token识别函数
// 笔者这里仅修改了 if else
func getCnToken(lit []byte) token {
    switchstring(lit) {
    case"break": return _Break
    case"case": return _Case
    case"chan": return _Chan
    case"const": return _Const
    case"continue": return _Continue
    case"default": return _Default
    case"defer": return _Defer
    case"否则": return _Else
    case"fallthrough": return _Fallthrough
    case"for": return _For
    case"func": return _Func
    case"go": return _Go
    case"goto": return _Goto
    case"如果": return _If
    case"import": return _Import
    case"interface": return _Interface
    case"map": return _Map
    case"package": return _Package
    case"range": return _Range
    case"return": return _Return
    case"select": return _Select
    case"struct": return _Struct
    case"switch": return _Switch
    case"type": return _Type
    case"var": return _Var
    default: return0
    }
}

func (s *scanner) ident() {
    s.startLit()

    // accelerate common case (7bit ASCII)
    c := s.getr()
    for isLetter(c) || isDecimal(c) {
        c = s.getr()
    }

    // general case
    if c >= utf8.RuneSelf {
        for s.isIdentRune(c, false) {
            c = s.getr()
        }
    }
    s.ungetr()

    lit := s.stopLit()

    // possibly a keyword
    iflen(lit) >= 2 {
        if tok := keywordMap[hash(lit)]; tok != 0 && tokStrFast(tok) == string(lit) {
            s.nlsemi = contains(1<<_Break|1<<_Continue|1<<_Fallthrough|1<<_Return, tok)
            s.tok = tok
            return
        } elseif tok := getCnToken(lit); tok != 0 { // 添加else if,识别出正确的中文token。共5行代码
            s.nlsemi = contains(1<<_Break|1<<_Continue|1<<_Fallthrough|1<<_Return, tok)
            s.tok = tok
            return
        }
    }

    s.nlsemi = true
    s.lit = string(lit)
    s.tok = _Name
}

添加中文函数关键字

文件 go\src\cmd\compile\internal\gc\universe.go

var builtinFuncs = [...]struct {
   name string
   op   Op
}{
   {"append", OAPPEND},
   {"cap", OCAP},
   {"close", OCLOSE},
   {"complex", OCOMPLEX},
   {"copy", OCOPY},
   {"delete", ODELETE},
   {"imag", OIMAG},
   {"len", OLEN},
   {"make", OMAKE},
   {"new", ONEW},
   {"panic", OPANIC},
   {"print", OPRINT},
   {"输出", OPRINT}, // 对函数print进行汉化
   {"println", OPRINTN},
   {"real", OREAL},
   {"recover", ORECOVER},
}

笔者这里只汉化了一个内置函数print。

编译源码

./all.bash

到这里,go源码的修改已经可以支持笔者示例中的中文代码。这里只是抛砖引玉,其他操作有待你的发掘。

这一步有2件事情需要注意:

  • 执行 ./all.bash时,必须进到go源码下的src目录执行
  • 如果没有安装其他版本的go程序,会有报错信息提示安装go1.4

3. 汉化验证

示例代码 demo.go

package main
func main(){
    如果 (1==1) {
        输出("这里是如果");
    } 否则 {
        输出("这里是否则");
    }
}
go run demo.go

结果具体是什么?是否跟笔者的一致?聪明的你试试便知。

4. 总结

常见的汉化一般有:国外软件汉化、操作系统汉化、APP汉化等,而对编程语言的汉化则不常见。

本文的一系列操作,只想让你明白:编程语言在编译过程中有词法分析、语法分析的步骤 (笔者的另一篇文章:[关于中文编程的一些思考]中有写)。了解其工作原理,能够对编程语言有更深层次的理解提升。

5.参考

[1] https://zhuanlan.zhihu.com/p/106104002 给go语言添加中文关键字

评论啦~