1. 为什么写本文
笔者在自己的原创文章 [关于中文编程的一些思考]中,有一段关于go的中文代码,并且还能正常执行。
可能有些小伙伴看到之后,在自己的电脑上也执行了同样的代码却报错,原因就是:还需要对部分源码进行修改。这里,笔者就整理了一下操作的步骤。
2. 源码修改步骤
拉取Go源代码
1
| git clone https://github.com/golang/go.git
|
从GitHub拉取Go源代码的好处是:拉取的源码中包含了多个版本分支,可以切换到自己想要的版本。
切换到编译的版本
1 2 3
| cd go git branch -a git checkout -b go1.14 origin/dev.boringcrypto.go1.14
|
笔者这里是在go1.14的基础上进行的关键字汉化,你可以选择自己想要的版本。
添加中文关键字
文件:go\src\go\token\token.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
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()
c := s.getr() for isLetter(c) || isDecimal(c) { c = s.getr() }
if c >= utf8.RuneSelf { for s.isIdentRune(c, false) { c = s.getr() } } s.ungetr()
lit := s.stopLit()
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 { 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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}, {"println", OPRINTN}, {"real", OREAL}, {"recover", ORECOVER}, }
|
笔者这里只汉化了一个内置函数print。
编译源码
到这里,go源码的修改已经可以支持笔者示例中的中文代码。这里只是抛砖引玉,其他操作有待你的发掘。
这一步有2件事情需要注意:
- 执行
./all.bash
时,必须进到go源码下的src目录执行
- 如果没有安装其他版本的go程序,会有报错信息提示安装go1.4
3. 汉化验证
示例代码 demo.go
1 2 3 4 5 6 7 8 9
| package main func main(){ 如果 (1==1) { 输出("这里是如果"); } 否则 { 输出("这里是否则"); } } go run demo.go
|
结果具体是什么?是否跟笔者的一致?聪明的你试试便知。
4. 总结
常见的汉化一般有:国外软件汉化、操作系统汉化、APP汉化等,而对编程语言的汉化则不常见。
本文的一系列操作,只想让你明白:编程语言在编译过程中有词法分析、语法分析
的步骤 (笔者的另一篇文章:[关于中文编程的一些思考]中有写)。了解其工作原理,能够对编程语言有更深层次的理解提升。
5.参考
[1] https://zhuanlan.zhihu.com/p/106104002 给go语言添加中文关键字