Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Python Interpreter

a toy python interpreter

具体要求

程序结构

从上到下逐行执行。

文法规则

ASCII 编码,区分大小写。中文字符是未定义的。

关键字

NoneTrueFalsedefreturnbreakcontinueifelifelsewhileorandnot

关键字不可作为变量名或函数名。

空白字符的处理

空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。

换行符表示新的语句的开始。

注释

# 开始到本行结束的内容都会被作为注释。

标识符

标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。

标识符区分大小写。长度超过 $64$ 个字符的标识符是未定义的。

常量

逻辑常量

True 为真,False 为假。

整数常量

整数常量以十进制表示。整数常量不设负数,负数可以由正数取负号得到。

整数的范围是没有限制的,这意味着你必须实现高精度整数。

首位为 $0$ 的整数常量是未定义的。

字符串常量

字符串常量是由双引号或单引号括起来的字符串。

可以由两个字符串拼接而形成新的字符串常量。如 "123""456" 相当于 "123456"

字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种。

空值常量

None 用来表示变量没有指向任何值。

运算符

算术运算符

+-*///%

在字符串意义下 + 表示拼接,* a 表示拼接 $a$ 次。

/ 是浮点除,// 是整除,% 是模运算。

运算的隐式类型转换参考 c++ 语法。当整除与模涉及到浮点数,此行为是未定义的行为。

整除(无论正负)可以看成浮点除之后向下取整(当然这不是正确写法,因为这样会造成有效数字丢失)

模运算无论正负定义为: a%b=a-(a//b)*b

关系运算符

<><=>===!=

连续比较:若出现 1<2>3 这样连续的关系运算符,将它拆成相邻的比较并用 and 连接,但每个值只计算一遍。如 a()<b()<c(),相当于判断 a()<b() and b()<c() 但是 a(),b(),c() 只调用一遍。

逻辑运算符

andornot

与标准 python 语法不同,这里只返回布尔类型

请注意逻辑运算的短路。

赋值运算符

=

给一个变量赋值的意义是将这个变量指向右值,右值不管类型。

对于一个之前未定义的变量,赋值运算会先定义变量。

与标准 python 不同,全局变量的生效范围是全部范围 (不用 global 关键字即可访问)。

局部变量的生效范围是在当前语句块(被缩进和取消缩进包起来的部分),具体局部变量和全局变量划分规则和 c++ 一样。

a=1,a=”123”,a=1.1 这三条语句依次执行,再输出 a,结果是 1.1

可以连等,如 a=b="123" 意思是 b="123",a=b 这两条语句依次执行。

可以给多变量赋值,如 a,b=1,2 意思是 a=1,b=2 依次执行。

增量赋值

+=-=*=/=//=%=

对字符串而言 += 就是往后加字符,*= 就是把字符串复制多遍加起来,剩下两个符号对字符串无定义。

圆括号

圆括号除了用在表达式里,可以用来调用函数,定义函数。

优先级

从低到高依次为

=orandnot<><=>===!=+-*///%
()

数据类型

bool:只有 TrueFalse

int:高精度整数。

float: 与 c++ 中的 double 一致。

str: 字符串,immutable

语句

变量定义/赋值语句

var_1 = (var_2 = ...) = value

语法规则参见赋值运算符。

表达式语句

var += value 或其他增量赋值

运算时如果两个运算数类型不一致,按照 c++ 规则执行自动类型转换。

条件语句

ifexpression_1:
# code blockelifexpression_2:
# code blockelseexpression_3:
# code block

elif 相当于 else ifelse 可以没有。

循环语句

whileexpression:
# code block

跳转语句

breakreturncontinue

函数

函数定义

deffunc(parameters):
# code block

参数列表如 a,b,c,变量名之间用逗号分隔,可以为空。

有些变量可以有默认值,但是都必须出现在无默认值的变量后面。

函数调用

func(parameters)

函数调用必须出现在该函数定义后。

参数有两种形式:keyword 和 positional。

Keyword argument 比如 foo(a=1,b=2) 表示传入参数 a 的值为 1b 的值 2

Positional argument 是指 foo(1,2) 这样按照出现顺序指代参数。

若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如 foo(1,b=2)

内建函数

print:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出 float 保留 $6$ 位小数。输出字符串不要输出前后面的引号。如 print("123",1.0) 请输出 123 1.000000

int:将 floatboolstr 转成 int

float: 将 intboolstr 转成 float

str: 将 intfloatbool 转成 str

bool: 将 intfloatstr 转成 bool。对于 str,如果是 "" 则为 False,否则为 True

转型类函数都只有一个参数。

函数递归

数据保证递归层数不超过 $2000$ 层。

Q&A

  • Q:需不需要实现函数内定义函数的功能?

    A:不需要。定义函数只能在全局最外层,在其它语句块内部均为未定义行为,不作要求。

评分相关

本次作业要求用 OOP 实现,若不按照要求会在 code review 扣除一定分数。

作业按数据总的通过比例给分。助教会下发部分数据在作业仓库中,还有另一部分数据不会提供。

这意味着你需要自己手写测试数据给自己测试,如果你对自己造的数据是否满足要求有疑问,请及时向助教询问。

如果有实现要求之外的功能或者语法(如报错、容器、自定义类等),可酌情加分,最多不超过本作业的总分。

提示

建议使用 antlr4 框架完成。助教组已经提供了现成的语法文件。

如果你想挑战自己,可以自己写 parser 或者自己重写语法文件。

其他

如果有不懂的文法规则,参考 python3.g4,以上面的规则为准。

如果有其他问题可以及时联系助教。

About

SJTU-ACM Programming 2021 assignment 2 (A-Class) , a toy Python3 Interpreter.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages