下面我们尝试自定义一些BNF规则。
一般示例:全名的语法
现在我们尝试定义一个人的全名的语法,一个人的全名包含3部分:
first name
, middle name
, family name
。
每个部分之间应该用空格分隔,middle name
是可选的。
<full_name> ::= <first_name> " " (<middle_name> " ")? <family_name>
规则的左侧部分是一个非终止符变量,用于标识人员的全名。::=
符号表示 <full_name>
将替换为规则的右侧部分。
规则的右侧部分有几个组成部分。首先是first name,使用<first_name>
非终止符定义。
接下来是一个空格。为了定义空格,要使用一个终止符,即" "
。
接下来,我们有一个可选的middle_name,使用(<middle_name> " ")?
定义。
最后,我们有一个家庭名,使用<family_name>
定义。
我们还需要定义<first_name>
, <middle_name>
, <family_name>
的规则。
- 只接受字母
- 首字母大写,其余小写
我们又引入了大写字母和小写字母两个非终止符,需要进一步定义:
<uppercase_letter> ::= [A-Z]
<lowercase_letter> ::= [a-z]
接着,我们可以定义<first_name>
, <middle_name>
, <family_name>
的规则:
<first_name> ::= <uppercase_letter> <lowercase_letter>*
您可以按照相同的模式来构建 <middle_name>
和 <family_name>
规则。
我们构建完了一个full name的BNF规则。
下面我们在BNF Playground
网站中测试这个规则。
与编程相关的示例:标识符
在学习编程语言时,我们很早就会接触到标识符(Identifiers)的概念。
标识符是用来标识变量、函数、类等的名称。
在Python中,标识符的命名规则如下:
- 第一个字符是字母、下划线。
- 其余字符可以是字母、下划线或数字。
可以写出相应的BNF规则:
<identifier> ::= <char> (<char> | <digit>)*
其中<char>
和<digit>
进一步定义:
<char> ::= [A-Z] | [a-z] | "_"
<digit> ::= [0-9]
我们可以在
BNF Playground
网站中测试这个规则。
Python的BNF变体
Python 使用 BNF 表示法的自定义变体来定义语言的语法。
Python 的 BNF 变体使用以下样式:
符号 | 含义 |
---|---|
name | 规则或非终止符的名称 |
::= | 意味着 |
` | ` |
* | 零个或多个 |
+ | 一个或多个 |
[] | 零个或一个,即可选项 |
() | 分组 |
space | 仅对分隔令牌有意义 |
这些符号定义了 Python 的 BNF 变体。与常规 BNF 规则的一个显着区别是Python不使用尖括号( <>
)来括起非终端符号。它仅使用非终端标识符或名称。这使得规则更简洁易读。
另外,[]
的含义不再是字符集,而是可选项。要定义类似于BNF的[a-z]
,需要使用"a"..."z"
。
在Python文档经常会遇到BNF代码片段,有必要学习如何阅读它们。
从 Python 的文档中读取 BNF 规则:示例
pass 和 return 语句
这是Python的pass
语句
pass_stmt ::= "pass"
这里,pass_stmt
是一个规则的名称,使用::=
指示规则扩展为"pass"
。"pass"
是一个终止符,意味着语句本身由单词pass
组成。
因此,pass
语句只是一个单词
pass
另一个常见的语句是return
语句:
return_stmt ::= "return" [expression_list]
return
语句由"return"
和[expression_list]
组成。expression_list
是一个非终止符,[]
表示它是可选的。
因此你可以这样使用return语句
def func():
return
如果你进入expression_list的定义,你会看到
expression_list ::= expression ("," expression)* [","]
又出现了一个非终止符expression,你可以继续查看expression的定义。
通过该定义,你可以了解到return
语句可以返回一个或多个(用,隔开)表达式。
def func():
return "Hello!", "Pythonista!"
赋值表达式
Python 3.8 引入了赋值表达式:=
(称为walrus运算符/象牙运算符)。作用是给变量赋值并返回表达式的值。
assignment_expression ::= [identifier ":="] expression
规则的右侧先是一个可选的组件,由一个标识符和一个终止符:=
组成。然后是一个表达式。
我们可以在python中使用赋值表达式:
identifier := expression
例如
>>> (length := len([1, 2, 3]))
3
>>> length
3
条件语句
我们现在进阶到复合语句了。
if语句的BNF规则如下:
if_stmt ::= "if" assignment_expression ":" suite
("elif" assignment_expression ":" suite)*
["else" ":" suite]
首先是终止符if
,然后是assignment_expression(上一节已经讨论过)。然后是终止符:
, 非终止符suite
。
安装刚刚读的定义,我们可以写出下面的if语句:
if assignment_expression:
suite
继续看定义,我们有了可选的elif:
if assignment_expression:
suite
elif assignment_expression:
suite
最后是可选的else:
最后
🍅 硬核资料:关注即可领取PPT模板、简历模板、行业经典书籍PDF。
🍅 技术互助:技术群大佬指点迷津,你的问题可能不是问题,求资源在群里喊一声。
🍅 面试题库:由技术群里的小伙伴们共同投稿,热乎的大厂面试真题,持续更新中。
🍅 知识体系:含编程语言、算法、大数据生态圈组件(Mysql、Hive、Spark、Flink)、数据仓库、Python、前端等等。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!