怎麼用中文設計編程語言?
因為計算機科學起源於西方,現今各種編程語言都是用英文,如果用中文設計一種語言可行嗎?有大神是否想過怎麼設計呢?
開了下腦洞,覺得 @NightyNight 的文言編程有意思,關於語法規則的劃分可以考慮更加充分的利用文言虛詞,不一定要拘泥於句式。文言中的虛詞本身起到了語法的界定作用,用文言虛詞來進行語法界定可以避免那些亂七八糟的符號。
比如過程定義的文法可以寫成
definition := parameters "之" def_name "者" expression "也"
expression := (arguments "之" function) | (lhs function rhs)
也就是寫成
某之均者某之數除某之累和也
這一句就相當於
(define (均 某) (/ (sum 某) (count 某)))
不過有一點難處理的是,這樣的機制默認寫出來的 identifier 都是單個漢字,連續的單個漢字會被認為是並列的多個參數(如「甲乙之積」中認為「積」是兩個參數的函數,甲乙是兩個並列的參數),畢竟文言名詞也以單字詞居多。這種時候可能就不得不引入諸如引號(「」或「」)、逗號(,)、頓號(、)分號(;)等現代漢語的標點來進行輔助的界定,比如放在引號中的多個單字被認為是一個整體(「隔壁老王」藏於「衣櫃」)。
別的一些語義也可以用類似形式表達,比如 let...in... 寫成 「以……為……」
如
以十三為廣,十四為縱,廣縱之積
相當於
(let ((廣 13) (縱 14)) (* 廣 縱))
部分參考《九章算術》
當然可行,可以參考 vczh/tinymoe 。雖然這個是英文的,不過沒關係,只要把tokenizer改掉,每一個字元一個token(而不是按照非字母字元去切連續的字母作為token),立刻就搞定了。不過這種做法出來的不可能是自然語言,你寫出來的中文也是需要嚴格滿足一定的語法結構的。
原理其實很簡單,首先識別出來哪些行是函數聲明,每一個函數聲明其實就是聲明了一個短語,which給語言增加了新的語法結構。然後你把這些聲明收集起來,當作EBNF,跑一邊經典的LALR演算法,出來一個parser,然後再用parse一遍自己的函數體,你就成功的做完語法分析了。
我可以想像一下給出最終中文編程的例子(逃
語句:輸出(垃圾)
重定向到printf
短語:從(甲)加到(乙)的結果
令結果為0
令丙為甲
只要丙小於或等於乙就
令結果為結果加丙
語句:入口
輸出從1加到100的結果
不需要添加多餘的空格,爽!
分析一下,我們可以強行規定「短語/語句:」開頭的就是函數頭,然後用python一樣的那種縮進的辦法。於是我們就有了下面的EBNF:
(省略語言本身就預定義好的語句,譬如說「令 fuck 為 shit」和「只 要 expr 就」
stat := "輸" "出" expr
expr := "從" expr "加" "到" expr "的" "結" "果" // 你需要處理優先順序問題
剩下來就很容易了,龍書裡面都說過了。
而且跟現在的那些所謂的漢語編程不一樣,人家總是不斷地給單詞中間加入符號,看起來成了一堆屎。憑啥要在中文裡面加入空格?你說話的時候會加空格嗎?
(逃
好,放劍制。
來,我們來寫文言文。
首先下一個Parser(Python 3.6)框架。放心我不是調包黨,我是造輪子的。
這個框架真的很有趣的(吃我安利!),你要是有興趣可以問我實現原理,可以看我文章。
pip install -U EBNFParser
(剛剛花時間支持了中文parser名...不然我早就來回答了。吐槽一下,shutil包真的很玄幻。
然後,這裡有一個文件。
很騷氣的文言編程文法(對不齊是因為unicode字元的鍋。。)
複製它,找個地方,放著。
然後在這裡打開命令行。
parserGenerator ./grammar ./myparser.py
# EBNFParser已經更新,現在的命令是
# ruiko ./grammar ./myparser.py
然後就可以開始玩了。
python testLang.py 語句 "[吾身]乃劍所[天成]。" -o 吾身乃劍所天成
python testLang.py 語句 "血作為[鐵潮];心作為[琉璃]。" -o 血潮為鐵,心為琉璃
....
詳見travis測試文件
結果放點圖,現在是ast。
(這個圖比較舊,如果你認真看會發現分號被當成了變數(概念),因為token沒對。吃飯後更正
文件名叫無限劍制.sh。
其實這本質上是一個函數單參數,然後有兩種倒裝運算的Lisp。
下午有課,解釋器等下。
語法是這樣的。
lambda定義是用由開頭,後面跟一個字,或者一個方括弧括起來的詞,表示參數,再後面跟一個具象,你把它理解為表達式即可。
調用函數的形式是以以字開頭,後面跟參數,參數是一個具象(剛剛發現上面寫錯了。上面的圖其實用的是概念這個Ast,是錯的,但是生成Ast階段是不報錯的,在Ast解析時,這個位置的類型不是具象的話,會拋出異常)。再跟一個表達式,這個表達式得到的結果將調用前面這個參數。所有的函數都是單參數的,很洋氣:)
然後倒裝句有於、所、作為三種,其中於和所的優先順序是一樣的,作為比他們靠後。
[吾身](乃( 劍(所(天成)) ) ) # 劍所天成是會結合成一個表達式,然後用被乃調用
(人)作為((天)所(寵幸)) # 這裡就是優先順序的體現了。
Emmmmm
想了一晚上還是加一句... 可以的話,github上給這項目加個星吧。
thautwarm/EBNFParser
畢竟也確實能方便到有些工作。個人也覺得挺好玩的。
以下原文
這個問題突然提起了我對所謂中文編程的興趣。之前見過的都是些符號替換,實在沒有半點興趣。
然後我今天早上看到大v輪的答案,他說把token搞成單一字元拆分(這個其實很有趣),然後給了自己的語言的例子。然後我來了一點靈感。
我想理想中大概是這樣的
&>&> 以我為0,以你為1,問以我加你是為你?
=&> 是
&>&> 有年為天,干,地,支 #容器
&>&> 以吾之事為由某年言若某年是為天則1而若某年是為地則2否則3 # let一個lambda
# 以 吾之事 為 由 某年 言 若某年是為天 則1 而若某年是為地 則2 否則3
# 這個語法在我後來的實現里改了,詳見更新寫的
&>&> 以年之天行吾之事
=&> 1
上面這些都很好做(吃完飯放解釋器),問題在於這些例子:
以1加2
以人余聖
解析時,怎麼判斷1加2不是符號,以及人余妖不是符號。怎麼把他們解析成
以(1)(加)(2)
以(人)(余)(聖)
我解決思路應該非常清真,全部單子化
以具象行具象,等於
具象(具象)
那麼上面的以1加2就是
以1行以2行加
加 :: Int -&> Int -&> Int
好的,答題前其實還沒想清楚,答題後已經搞定。
可以用數學教材當中常用的中文描述,比如
定義 f(名字,次數):
取i從範圍(次數):
輸出「你好世界」,名字
f(「用戶」,2)
主要的優點:
可以省略空格(但是分詞演算法可能會很複雜)
主要的缺點:
輸入真TM累,如果有輔助的輸入法的話可能能好一點
附關鍵字:
若 否則若 否則
取(變數)從(範圍)
當(條件)
繼續
跳出
嘗試 拋出 捕捉(為) 否則 最終
定義
返回
交出(yield)
類
……
把 APL 漢化了就行了(逃
為什麼不願意搜一下尼?
蕭涵:為什麼程序都要用英文寫,中文不行嗎?
我就問一句,用英文直接敲代碼就好,用中文開著輸入法你不嫌打字慢嘛?
火了這麼多年的易語言你們都沒聽說過???
洛谷P1001 A+B Problem的一篇討論
你自己看看這群……hhhhhhhhhh
你可以用拼音的。
編程語言就是一門語言,有自己的語法,並不是英文,只是利用了ascii碼更新一下 Python 怎麼加中文token
1.90%語法,可以按下面方法加同義的中文token
以while為例
第1步. 編譯pgen
cd到python的源代碼目錄下,
./configure
make Parser/pgen
第2步. 修改 ./Grammar/Grammar,添加同義詞並生成語法代碼。
原文:
while_stmt: "while" test ":" suite ["else" ":" suite]
改為:
while_stmt: ("while"|當) test ":" suite [("else"|另) ":" suite]
執行
./Parser/pgen ./Grammar/Grammar ./Include/graminit.h ./Python/graminit.c
之後 make 編譯python即可。
中文的py文件也需要保存為UTF-8格式。
2.還有一較複雜語法在/Python/ast.c 里有輔助解析
例如
comp_op: ... |"in"|"not" "in"|"is"|"is" "not"
改為 comp_op: ... |("in"|在)|("not" "in"|不在)|("is"|為)|("is" "not"|不為)
在ast.c里的 ast_for_comp_op 中
if (NCH(n) == 1)
switch (TYPE(n))
case NAME
/******添加如下代碼*******/
if (strcmp(STR(n), "在") == 0)
return In;
if (strcmp(STR(n), "不在") == 0)
return NotIn;
if (strcmp(STR(n), "為") == 0)
return Is;
if (strcmp(STR(n), "不為") == 0)
return IsNot;
其實從源代碼我們可以看出來,comp_op原來的判斷是token有兩個單詞的話,第二個單詞為in返回NotIn,第一個單詞為is返回IsNot。
3.內置函數 中文化
在/Python/bltinmodule.c中的builtin_methods[]中添加
以print為例,將含"print"的一行複製粘貼,替換第二行的"print"為"列印"即可
其他的還有一些宏,展開看一下,就明白了。
/*********************************/
我用clang做了一個與C++、C兼容的純中文的編譯器
swizl/cnlang
其實就是加token
在/include/clang/Basic/TokenKinds.def 中用ALIAS添加中文關鍵字
在 /lib/Basic/IdentifierTable.cpp 中 加個頭文件 #include "llvm/ADT/StringSwitch.h"
例如
KEYWORD(char, KEYALL)
ALIAS("字", char, KEYALL)
在 tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const 里用llvm::StringSwitch添加 中文宏
例如
//default: return tok::pp_not_keyword;
default: return llvm::StringSwitch&
.Case("如", tok::pp_if)
.Case("定義", tok::pp_define)
.Default(tok::pp_not_keyword);
至於llvm/clang的編譯方法,網上一堆。
還用tinycc做了個中文自舉編譯器,也是加token。
再把源代碼里的關鍵字都替換掉。
swizl/tinycc_cn 添加了中文token的tinycc
swizl/tinycc_zh 關鍵字全換了的tinycc,用tinycc_cn編了之後,可以自舉
#include&
#define shiyong using
#define minmingkongjian namespace
#define changliang const
#define zhengxing int
#define changzheng long long
#define wufuhao unsigned
#define buer bool
#define ruguo if
#define xunhuan for
#define mo %
#define jiashang +
#define jianqu -
#define chengyi *
#define chuyi /
#define zuiyi haiyaoshuchu
#define youyi dayu dayu
#define haiyou ,
#define canshukaishi (
#define canshujieshu )
#define jieshubencixunhuan continue
#define tiaochuxunhuan break
#define zhuhanshu main
#define fanhui return
#define fuzhi =
#define dengyu =
#define wancheng ;
#define kaishi {
#define jieshu }
#define biaozhunku std
#define jiegouti struct
#define lei class
#define duilie queue
#define shuangduanduilie deque
#define zhan stack
#define youxianduilie priority_queue
#define zhuhanshu main
#define zifuchuan string
#define shuru cin
#define shuchu cout
#define yaoshurude &>&>
#define yaoshuchude &<&<
#define haiyaoshuchude &<&<
#define haiyaoshurude &>&>
#define xiaoyu &<
#define dayu &>
#define de .
#define bufanhui void
#define kongde bufanhui
#define neilian inline
#define youhua __attribute__((__optimize__("-O4")))
#define zijia ++
#define zairuguo else ruguo
#define bumanzu else
#define quandengyu ==
#define jiaguoqu +=
#define jianguoqu -=
#define chengguoqu *=
#define chuguoqu /=
#define moguoqu %=
#define xiaoyudengyu &<=
#define dayudengyu &>=
#define huozhe ||
#define bingqie
#define budengyu !=
#define hangjieshule endl
#define manzutiaojianjiuxunhuan while
#define qudizhi
#define paixu sort
#define fanhui return
#define zhuhanshu main
shiyong minmingkongjian biaozhunku ;
zhengxing a , b;
zhengxing zhuhanshu canshukaishi canshujieshu
kaishi
shuru yaoshurude a; shuru yaoshurude b;
shuchu yaoshuchude canshukaishi a jiashang b canshujieshu ;
fanhui 0;
jieshu
一份putong的a + b
(別打我哈哈哈哈哈哈哈哈哈)
當然是用lisp的宏呀
給我一個Chinese.h就行
在程序員眼中,int,if,true等這些並不是英語,而是計算機語。
你們煩不煩啊,這種提問都是月經題了吧。先去了解易語言再談別的好不好?
中文編程語言之Z語言初嘗試: ZLOGO 4
已經商用的日語編程語言, 語法還是有點接近自然語言的: 日語編程語言"撫子" - 第三版特色初探
還遠未實現的中文彙編編譯器原型. 基於現有開源彙編器漢化關鍵詞開始應該會省力的多. 當時是想從頭做一個編譯器, 順便在Java中實踐中文命名. 對x64體系和intel指令的認識有限, 生成二進位碼時遇到瓶頸. 項目已擱置.
設想的效果圖(中英對比):
為什麼ruby一個日本人發明的卻用英文,為什麼python是荷蘭人發明卻用英文,為什麼易語言沒有走向世界。
對不起偏題了但是就想表達一下。
用中文變成意義不大,弊大於利。設計一門中文變成語言不難,以前就有e語言啊,但是一門編程語言用什麼文字書寫區別不大 因為就那麼幾個關鍵字。重要的事學習資料是中文還是英文,社區是中文還是英文
中文編程已經有了很久了,丙正正這門語言就是中文版的C++,只是因為沒人使用,所以沒發展起來
推薦閱讀:
※瀏覽器是如何識別惡意站點並提示的?
※怎麼看待鬥魚TV這段時間負面不斷?是鬥魚出現了問題,還是行業出現了瓶頸?
※2016~20 年矽谷需求量最大的是什麼方向的技術人才?
※為什麼工資高的程序員會難找到女朋友?
※IT上班族怎樣才能有情調、有意義地過生活?