Skip to content

cabuliwallah/shanghai-from-dongbei

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

shanghai- 上海方言编程语言

老卵伐

老卵伐

本语言改编自@zhangyong-wan的dongbei语言。

扫码关注原作者微信公众号“老万故事会”

上海宁可以扫码关注我的微信公众号“一择刚度”

引言

shanghai是啥?它是一门以上海方言词汇为基本关键字的以人为本的编程语言。

这瘪三可是填补了世界方言编程地图上的一大片空档啊! 这么说吧,谁要是看了 shanghai 程序能忍住了不笑,伊最老卵!

那它有啥特点?多了去了:

  • 简单啊!小学文化程度就行。侬能看懂老娘舅伐?能?那就没问题。
  • 好读啊!看着看着包侬不由自主地念出来。
  • 开心啊!呃,做人嘛,最重要的是要开心。
  • 开源啊!不但不要钱,而且不要脸 -- 随时随地欢迎上海话高手打脸指正。

shanghai 编程语言的开发采用了业界领先的 TDD(TreeNewBee-Driven Development) 方式。 具体地说,就是每个功能都是先把文案写好,八字没一撇牛皮就吹起来了,然后根据牛皮写测试案例,最后再实现功能让牛皮不被吹破。 这样做有两大好处:第一每个功能都是有的放矢,不值得 tree new bee 的功能一概没有。 第二确保了每个功能都有文案负责吹嘘,开发者的辛劳绝对不会被埋没。

不扯犊子了。阿庆,上奶茶~~~

系统要求

shanghai 语言是基于 Python 3 二次开发的。 只要能跑 Python 3 的地方都能跑。 像 Mac OS 啦、Windows 啦、Linux 啦,等等等等,都可以!

安装

甭麻烦了!直接跑 shanghai.py 就成。

不过,要是你的系统没有python3呢,那得先毛估估是一个,免费!

比如,你要是用 Mac 的话,就按 https://docs.python-guide.org/starting/install3/osx/ 做。

测试

没事跑跑

test/shanghai_test.py

身体更健康。

你好,世界

创建一个名字叫 hello-world.shanghai 的文本文件,内容如下:

嘎讪胡:“侬脑子瓦特了!”。

用 utf-8 编码保存。 要是编辑器因为编码错误弄松侬,那就把文件内容改成

# -*- coding: utf-8 -*-

嘎讪胡:“侬脑子瓦特了!”。

再试,应该就成了。

然后在命令行窗口运行:

python shanghai.py hello-world.shanghai

你应该看到执行结果:

侬脑子瓦特了!

考试小抄

要是你以前有 shanghai 语言基础,或者不耐烦看文档,可以直扑 shanghai 语言考试小抄

语言定义

学习一门语言,先得了解它的词法(怎么从一串串的字符组成词),然后是语法(怎么把词组成句子)和语义(这些句子都啥意思啊?)。 所以,咱们先讲讲 shanghai 语言词汇的构成。

词法

字符串常量

一行代码当中,要是出现配对的中文全角双引号,比如

...“我是一个字符串”...

那么引号当中的内容(我是一个字符串)会被当成一个字符串常量。

注释

一行代码当中,如果在字符串常量外面出现 # 字符,所有从 # 开始的字符都会被当成注释被忽略掉。 比如

嘎讪胡:  # 我是一个注释。
    “组撒#?”。  # 我还是一个注释。

嘎讪胡:“组撒#?”。

是一样一样的。

分词

大部分的西方语言在书写的时候要用空白字符或者标点把单词隔开,要不就会产生歧义。 比如 therapist(理疗师)和 the rapist(强X犯)就有很大的不同!

所以,西人开发的编程语言也一样啰嗦,动不动就要加空格,忒麻烦了。

shanghai 语言以人为本,适应华人的书写习惯,加不加空格换行都无所谓。 反正加了也白加(除非加在一个字符串常量的内部)。 所以对 shanghai 来说,

嘎讪
    胡
      :
       “组撒?”
             。

嘎讪胡:“组撒?”。

是一样一样的。

名字

代码里面除了各种有特俗意义的关键词(keyword),还会有各种用户定义的名字(变量名、函数名、类型名,等等)。 在 shanghai 语言里面,除了关键词、标点符号和常数,剩下的都是名字。 比如,在“阿庆乘阿德”这个 shanghai 语言表达式里,“乘”是一个关键词,“阿庆”和“阿德”是两个不同的名字,

那么问题来了:shanghai 语言是不管空格的,名字和关键词之间没有明显的隔离。 要是名字里包含关键词怎么办? 比如,我们知道“乘”是一个关键词,那还能用“阶乘”做套路名吗? 系统会不会把它理解成名字“阶”和关键词“乘”?

不要方! shanghai 语言允许你用中文全角方括号【】把一串字符标注为名字。 比方说,“【阶乘】”就明明白白地是一个叫“阶乘”的名字,绝对不会被当成是名字“阶”加关键词“乘”。

常数

除了用阿拉伯数字表示的十进制整数(比如 2、42、250,等等),0 到 10 的常数也可以用中文表达:

零一二三四五六七八九十

也可以写成

灵耶良(尼)赛思恩咯且吧就色

比如,

五加二

的意思就是 5 + 2。

语句

一个 shanghai 程序是由一串语句组成的。 每个语句以句号(。)结束。 为了表达程序员炽热的感情,也可以用感叹号(!)结束,意思和句号是一样一样的。 请大家根据自己的心情任选使用。

变量

shanghai 语言允许使用任何字符串做变量名。只要记住两点:

  1. 变量名里所有的空白字符都会被忽略。
  2. 有歧义的时候要把变量名用【】括起来。

定义变量

shanghai 是一门以人为本的语言。 我们知道上海人都是赤佬。 所以,要定义一个叫 XX 的变量,我们要写......

XX是则赤佬。

比如:

阿庆是则赤佬。

当然,热情洋溢的

阿庆是则赤佬!

也是可以的。

给变量赋值

shanghai 语言不整“赋值”这种文绉绉的词。 阿拉叫“毛估估”。 比如:

阿庆毛估估是二。

可以理解为 C 语言的

a_qing = 2;

要把一则赤佬的值清空回到原始状态,可以用色特

色特阿庆。

过后阿庆就啥也不是了。

增减变量

赤佬除了会毛估估,加加减减也是常见的操作。 这些操作的名字叫做:扎台型混腔势扎X趟混X趟。 比如:

阿德毛估估是二。  # 现在阿德等于2
阿德扎台型。  # 现在阿德等于3
阿德扎两趟。  # 现在阿德等于5
阿德混腔势。  # 现在阿德等于4
阿德混五趟。  # 现在阿德等于-1

引用变量

变量,呃,赤佬定义以后就可以引用了。 引用的方法很简单:把赤佬的名字写出来就成。 比如:

阿德是则赤佬。
阿庆是则赤佬。
阿德毛估估是250。
阿庆毛估估是阿德加13。

定义了两个则赤佬:阿德和阿庆。 阿德值250。 阿庆值263。

输出

要输出信息,咱们得说“嘎讪胡”。假定要说的信息是 YY,就得写

嘎讪胡:YY。

比如说,赤佬阿庆的当前值是263,那么

嘎讪胡:阿庆。

的结果就是打印

263

内容也可以是中文全角双引号括起来的字符串常量,像

嘎讪胡:“侬脑子瓦特了!”。

的结果就是打印出

侬脑子瓦特了!

字符串运算

顿号(、) 操作符可以把两个值当成字符串拼接起来。 假定赤佬阿庆的当前值是字符串“NB”,那么表达式

阿庆、“A”

的值就是字符串 NBA。而

“阿庆”、665加一

的值是 阿庆666

算术运算

基本的四则运算 shanghai 都是支持的。举例说明:

表达式 含义
阿庆加阿德 阿庆 + 阿德
阿庆减阿德 阿庆 - 阿德
阿庆乘阿德 阿庆 * 阿德
阿庆除以阿德 阿庆 / 阿德
阿庆除以得毕挺阿德 阿庆 / 阿德,只保留整数部分

注意除法运算叫“除以”,不叫“除”。 问问你小学数学老师就知道,“A除B”的意思其实是“B除以A”,也就是说“B/A“。 所以,要是你说“6除2”,数学老师会以为你在说3分之1,而不是3。 你要是跟他讲“6除2得3”,信不信他给你吃毛栗子?

跟小学学过的一样,乘除的优先级比加减高。 相同优先级的情况下,运算从左到右。比如说:

3加2乘5

的结果是13,不是25。

括号也是可以的:

嘎讪胡:(五减(四减三))乘二。

8

比大小

shanghai 人讲究分寸,长幼有序。

假定阿庆毛估估是5,阿德毛估估是6。 那么

嘎讪胡:阿庆 比 阿德 老卵。
嘎讪胡:阿庆 比 阿德 推板。
嘎讪胡:阿庆 帮 阿德 一色一样。
嘎讪胡:阿庆 帮 阿德 伐大一样。

的结果就是

勿对
对额
勿对
对额

除此之外,一个刚刚创建的赤佬还没有值。 我们就说他脑子瓦特了

阿庆是则赤佬。
嘎讪胡:阿庆。
嘎讪胡:阿庆脑子瓦特了。

会打印

脑子瓦特了
对额

循环

所谓循环,就是一遍一遍搞七捻三。 所以,在 shanghai 语言里循环的写法是:

变量名 从 X 到 Y 搞七捻三:
  ...  # 需要重复做的事
搞好了。

举例说明:

阿庆从一到五搞七捻三:  # 阿庆从1走到5。
  嘎讪胡:阿庆!  # 打印阿庆的当前值。
搞好了!  # 循环结束。

运行的结果是:

1
2
3
4
5

搞七捻三是可以嵌套的。比如:

阿德从一到二搞七捻三:
  嘎讪胡:“阿德:”、阿德。
  阿庆从阿德到四搞七捻三:  # 内层搞七捻三可以引用外层搞七捻三变量
    嘎讪胡:“阿庆:”、阿庆。
  搞好了。  # 内层搞七捻三结束。
搞好了。  # 外层搞七捻三结束。

运行出来是这样的:

阿德:1
阿庆:1
阿庆:2
阿庆:3
阿庆:4
阿德:2
阿庆:2
阿庆:3
阿庆:4

讲条件

虽然 shanghai 人都是赤佬,干活的时候该讲条件还是要讲条件的。 轧苗头 是一项很有用的技能!

一般来讲,要是阿拉有件事情(不妨叫做 XXX)只想在某个条件(不妨叫 CCC)成立的时候再做,就写:

轧苗头: CCC ?
要来赛就 XXX

要是 CCC 不成立的时候阿拉有另外一件事情 YYY 要做,那就写:

轧苗头: CCC ?
要来赛就 XXX
勿来赛就 YYY

比如说吧,要是阿拉看阿庆比阿德大就想夸夸阿庆,那就这么写:

轧苗头:阿庆比阿德老卵?
要来赛就嘎讪胡:“阿庆比较老卵!”。

再复杂一点的:

轧苗头:阿庆比阿德老卵?
要来赛就嘎讪胡:“阿庆比较老卵!”。
勿来赛就轧苗头:阿德比阿庆老卵?
要来赛就嘎讪胡:“阿德比较老卵!”。
勿来赛就嘎讪胡:“阿庆阿德共同老卵。”。

看懂了?要是阿庆是3阿德是2,那么这段代码就会打印

阿庆比较老卵!

要是阿庆2阿德3,就会打印

阿德比较老卵!

要是阿庆阿德都2,打印的就是

阿庆阿德共同老卵。

组合拳

你有没有想过:要是阿拉在某个条件成立的时候想做两件事而不是一件事,哪能办? 要是写

轧苗头:CCC ?
要来赛就
   XXX。
   YYY。

行嘛?

不行。

前面阿拉说过了,shanghai 语言里面字符串常量外头的空白是不作数的。 写了也瞎忙活。 所以,按上面这种写法,XXX 倒是只有 CCC 成立的时候才会做,可 YYY 是无论如何都会做的。 毛估估是:

# 先讲条件:
轧苗头:CCC ?
要来赛就XXX。

# 这个不讲条件。
YYY。

要解决这个问题,咱得上 组合拳:把一串操作整合成一个操作。 组合拳的写法是:

一道组特:
  XXX。
  YYY。
  ...
  ZZZ。
组好了。

尽管整了一串,在 shanghai 语言看来这是一个操作。 所以,

轧苗头:CCC ?
要来赛就一道组特:
   XXX。
   YYY。
组好了。

就能达到阿拉的目的了!

套路

“套路”这名字听着吓人,其实就是给一串常用的组合拳取一个名字,然后吧需要做这些操作的时候提一下这个名字就OK了。

定义套路

要定义一个套路,用这个格式:

套路名字 哪能组:
  ...  # 要做的操作
组好了。

还是举例说明:

写九九表哪能组:  # 定义套路 写九九表。
  阿庆从1到9搞七捻三:
    阿德从阿庆到9搞七捻三:
      嘎讪胡:阿庆、“*”、阿德、“=”、阿庆乘阿德。  # 打印 X*Y=Z
    搞好了。
    嘎讪胡:“”。  # 空一行。
  搞好了。
组好了。  # 结束套路定义。

定义了一个叫“写九九表”的套路。 注意定义套路本身不会让这个套路真的跑起来。 所以上面这段程序跑的结果是啥也不做。

使用套路

要把一个套路代表的操作跑一遍,得写:

白相 套路名。

比如说,上面这个“写九九表”的套路定义好了过后,你只要写:

白相写九九表。

就可以打印出一份浓眉大眼的九九表了:

1*1=1
1*2=2
1*3=3
...

8*8=64
8*9=72

9*9=81

带参数的套路

有的时候,我们希望通过一个参数去控制一个套路的行为。 比如,我们要教会电脑算一个数的阶乘(就是123*... 一直乘到这个数)。 在定义这个“阶乘”套路的时候,我们并不知道以后会用它来算哪个数的阶乘。 所以,我们要把这个数定义成这个套路的一个参数。

那就要这样写:

套路名(参数名)哪能组:
  ...  # 爱做的事
组好了。

具体到这个“阶乘”套路,就是这样的:

【阶乘】(阿庆)哪能组:  # 定义套路 阶乘,有一个参数 阿庆
  ...  # 阶乘的操作步骤
组好了。  # 定义结束。

注意这里我们把套路名“阶乘”用方括号【】括起来,因为“乘”本身是个关键词,不括起来容易引起误会。

这个套路有一个参数,名字叫“阿庆”。 “【阶乘】(阿庆)”就是算阿庆的阶乘。

要是一个套路有多个参数,那就得把它们一个一个列出来,中间用逗号隔开:

求和(甲,乙)哪能组:
  再会 甲加乙。
组好了。

调用这种套路的时候,相应地要把参数的值一个一个列出来:

嘎讪胡:白相求和(五,七)。

会打印出 12。

从套路返回值

在“写九九表”这个例子里,套路本身是不返回任何值的。 它要做的事都通过“嘎讪胡”打印出来了。

而对于“阶乘”来说,我们并不想打印这个阶乘的结果。 我们只想把结果返回给整这个套路的人,爱哪能用咋哪能。

在 shanghai 里边,从套路里返回一个值X,得说“再会。”

这个阶乘的完整定义,可以是这样的:

【阶乘】(阿无卵)哪能组:  # 定义套路 阶乘,有一个参数 阿无卵
  阿庆是则赤佬。
  阿庆毛估估是一。
  阿德从一到阿无卵搞七捻三:
    阿庆毛估估是阿庆乘阿德。
  搞好了。
  再会阿庆!  # 返回值。
组好了。  # 定义结束。

写完这个,再来一句

嘎讪胡:白相【阶乘】(五)。

就可以看到打印结果

120

了!

自推

每个程序员在学习编程的时候都要翻一个坎儿,这就是 递归

在 shanghai 语言里面,咱不整这些虚头八脑的概念。 咱就叫“自推”。

啥意思? 就是说在做一个操作的时候调用这个操作自己。 有点循环定义的意思。

其实这就是阿拉中学老师讲过的数学归纳法:欲求 f(n),先求 f(n-1)。 然后如果从 f(n-1) 的值可以推算出 f(n) 的值,不就搞定了吗? 当然,前提是这个自推不能无穷无尽地整下去,到某一步得停下来。

举个例子。 求 n 的阶乘 f(n) 可以这么搞: 要是 n 是 0 的话,结果就是 1。 要是 n 比 0 大的话,就给就是 n * f(n-1)。

这里,在算 f(n) 的时候,我们先算 f(n-1),再从 f(n-1) 算出 f(n)。 这就是自推大法的精髓。

把上面的思路用 shanghai 语言写出来,就是:

【阶乘】(阿无卵)哪能组:  # 定义套路 阶乘,有一个参数 阿无卵。
  轧苗头:阿无卵比一推板? # 需要自推吗?
  要来赛就 再会 一。  # 不需要。
  勿来赛就 再会 阿无卵乘白相【阶乘】(阿无卵减一)。  # 需要。自推吧。
组好了。  # 定义结束。

翘边

在家啃父母,出门靠姐妹。 不管你多老卵,没人翘边也不成。 所以咱们写 shanghai 程序得借力。 比如阿庆蛇家宝贝不少,阿拉就借来翘边呗。

举例说明,

阿庆,上 re。  # 导入 python 的正则表达式 re 模块。
阿庆毛估估是“abd”。
轧苗头:整re.match(“a.*”,阿庆)?  # 调用 re.match()。
要来赛就嘎讪胡:“OK!”。
勿来赛就嘎讪胡:“完结了!”。

跑出来结果

OK!

About

上海方言编程语言

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%