首页技术代码解释器?代码编辑器下载

代码解释器?代码编辑器下载

编程之家2026-06-29998次浏览

大家好,如果您还对代码解释器不太了解,没有关系,今天就由本站为大家分享代码解释器的知识,包括代码编辑器下载的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

代码解释器?代码编辑器下载

shell命令解释器源代码

要求实现一个简单的命令解释器,也就是linux中的shell程序,在本程序中我们将其起名为ysh,要求:

1、能够执行外部程序命令,命令可以带参数;

2、能够执行fg、bg、cd、history、exit等内部命令;

3、使用管道和输入输出重定向;

4、支持前后台作业,提供作业控制功能,包括打印作业的清单,改变当前运行作业的前/后台状态,以及控制作业的挂起、中止与继续运行;

5、使用Make工具建立工程;

代码解释器?代码编辑器下载

6、使用调试器gdb来调试程序;

二、实验现象:

本程序的ysh程序设计不包括对配置文件和命令行参数的支持。要求ysh提供一个命令提示符,如ysh>,表示接受用户输入,每次执行完成后,再打印下一个命令提示符ysh>,当用户没有输入时,ysh需要一直处于等待输入状态,同时在屏幕上显示一些必要的信息。

三、 Ysh解释程序的具体要求:

1、外部命令和内部命令:

在大多数情况下,用户输入的命令是执行存储在文件系统下中的可执行程序,我们称之为外部命令或外部程序。Ysh应当支持在执行这些程序时可以将输入/输出重新定向到一个文件,并允许若干个程序使用管道串联起来。我们把由管道连接起来的符合命令以及单独使用的命令成为作业。

外部命令的形式是一系列分隔的字符串。第一个字符串可以是可执行程序的名字,其它的是传递给这个外部程序的参数。如果第一个字符串所声名的可执行文件并不存在或者不可执行,则认为这个命令是错误的。

解释器还必须支持一些内部命令,这些命令在ysh内部实现了特定的动作,下面是一些内部命令,如果用户提交了一个内部命令,ysh应按照下面的描述执行相应动作。

�8�5 exit:退出ysh。

�8�5 jobs:打印当前正在后台执行的作业和挂起的作业信息。输出信息应采用便于用户理解的格式。

�8�5 fg%<int>:把<int>所标识的作业放到前台运行,如果这个作业原来已经停止,那么他继续运行。Shell应当在打印新的命令提示行之前等待前台运行的子进程结束。

�8�5 Bg%<int>:在后台执行<int>标识的已挂起的进程。

2、命令行:

当用户在提示符后面输入命令时,输入的整行内容叫做“命令行字符串”,ysh应当保存每一条命令行字符串,直到它表示的作业执行结束,其中包括后台作业和被挂起的作业。

3、前台和后台作业

ysh应当能够执行前台和后台作业。Shell在前台执行结束之前要一直等待。而在开始执行后台作业时要立刻打印出提示符ysh>,让用户输入下一条命令。

前台作业的执行总是优先于一个后台作业,ysh不需要在打印下一个提示符前等待后台作业的完成,无论是否有后台作业的执行,只要完成一个前台作业,便立即输出提示符ysh>;一个后台作业结束时,ysh应当在作业结束后立刻打印出一条提示信息。

4、特殊键:

又称组合键。通过终端驱动程序,特殊的组合键可以产生信号给ysh,程序应当对这些信号做出适当的响应。

�8�5 Ctrl+ Z:产生SIGTSTP信号,这个信号不是挂起ysh,而是让shell挂起在前台运行的作业,如果没有任何前台作业,则该特殊键无效。

�8�5 Ctrl+C:产生SIGINT信号,这个信号不是中止ysh,而是通过ysh发出信号杀死前台作业中的进程。如果没有任何前台作业,则该特殊键无效。

5、分析用户输入:

a)分隔符和特殊字符

分析用户输入的语法分析器应具有下面介绍的功能,它能够检查用户的输入错误。如果用户输入的某些地方出错了,ysh应当给出合理的出错信息。

ysh每次接受用户输入的一行命令,在用户按下回车键(Enter)后开始执行分析动作。空名令不产生任何操作,而只是打印一个新的提示符。

定义空格符为分隔符,ysh应能处理命令行中间和前后出现的重复空格符。

某些字符被称做“元字符”,它们在用户输入的上下文中具有特殊的定义。这些字符包括”&、|、<、>”。Shell假设这些字符不会出现在程序名、参数名、文件名中,他们是ysh的保留字符。

b)内部命令:

如果命令行字符串符合前面介绍的内部命令的格式,它就当作一个内部命令被解释。如果不是,就要考虑可能是外部程序的执行,或者是错误的。

c) I/O重定向:

一个程序命令后面可能还跟有元字符“<”或“>”,他们是重定向符号,而在重定向符号后面还跟着一个文件名,在”<”的情况下,程序的输入被重定向到一个指定的文件中去。在”>”的情况下,程序的输出被重定向到一个指定的文件中。如果输出文件不存在,需要创建一个输出文件。如果输入文件不存在,则认为出现了错误。

d)管道和协同程序

在一条命令行中当若干个命令被元字符“|”分开时,这个元字符代表管道符号。在这种情况下,ysh为每一个子命令都创建一个进程,并把它们的输入、输出用管道连接起来。

例如下面这条命令行:

progA argA1 argA2< infine| progB1> outfile

应生成progA和progB两个进程,ProgA的输入来自文件infile,porgA的输出是progB的输入,并且progB的输出文件是outfile。这种命令行可以通过进程间通信中的管道来实现。

含有一个和多个管道的命令会在如下几种情况下产生错误:

�8�5当其任何一个子程序执行出错时。

�8�5除了第一个子程序以外其它子程序的输入被重定向。

�8�5除了最后一个子程序以外的其它子程序的输出被重定向。

由管道连接的多个进程所组成的作业只有当其所有子进程都执行完毕后才算结束。

e)后台作业

当用户需要在后台执行一个作业时,可以在作业命令的后面加上元字符“&”。用户以该种方式输入的作业命令都必须放在后台执行,同时并不影响用户与终端的交互

Python解释器有哪些

python解释器很多种,最广泛运用的有:

1、CPython

当我们从Python官方网站下载并安装好Python 2.7后,我们就直接获得了一个官方版本的解释器:CPython。这个解释器是用C语言开发的,所以叫CPython。在命令行下运行python就是启动CPython解释器。

CPython是使用最广的Python解释器。教程的所有代码也都在CPython下执行。

2、IPython

IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互方式上有所增强,但是执行Python代码的功能和CPython是完全一样的。好比很多国产浏览器虽然外观不同,但内核其实都是调用了IE。

CPython用>>>作为提示符,而IPython用In [序号]:作为提示符。

3、PyPy

PyPy是另一个Python解释器,它的目标是执行速度。PyPy采用JIT技术,对Python代码进行动态编译(注意不是解释),所以可以显著提高Python代码的执行速度。

绝大部分Python代码都可以在PyPy下运行,但是PyPy和CPython有一些是不同的,这就导致相同的Python代码在两种解释器下执行可能会有不同的结果。如果你的代码要放到PyPy下执行,就需要了解PyPy和CPython的不同点。

4、Jython

Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。

5、IronPython

IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。

6、qpython用于在手机上编程。

Python怎样使用解释器

大学里计算机科学最吸引我的地方就是编译器。最神奇的是,编译器是如何读出我写的那些烂代码,并且还能生成那么复杂的程序。当我终于选了一门编译方面的课程时,我发现这个过程比我想的要简单得多。

在本系列的文章中,我会试着通过为一种基本命令语言IMP写一个解释器,来展示这种简易性。因为IMP是一个简单广为人知的语言,所以打算用 Python写这个解释器。Python代码看起来很像伪代码,所以即使你不认识 Python,你也能理解它。解析可以通过一套从头开始实现的解析器组合完成(在本系列的下一篇文章中会有解释)。除了sys(用于I/O)、re(用于解析正则表达式)以及unittest(用于确保一切工作正常)库,没有使用其他额外的库。

IMP语言

在开始写之前,我们先来讨论一下将要解释的语言。IMP是拥有下面结构的最小命令语言:

赋值语句(所有变量都是全局的,而且只能存储整数):

Python

1

x:= 1

条件语句:

Python

1

2

3

4

5

if x= 1 then

y:= 2

else

y:= 3

end

while循环:

Python

1

2

3

while x< 10 do

x:= x+ 1

end

复合语句(分号分隔):

Python

1

2

x:= 1;

y:= 2

OK,所以它只是一门工具语言,但你可以很容易就把它扩展成比Lua或python更有用的语言。我希望能把这份教程能保持尽量简单。

下面这个例子是计算阶乘的程序:

Python

1

2

3

4

5

6

n:= 5;

p:= 1;

while n> 0 do

p:= p* n;

n:= n- 1

end

IMP没有读取输入的方式,所以初始状态必须是在程序最开始写一系列的赋值语句。也没有打印结果的方式,所以解释器必须在程序的结尾打印所有变量的值。

解释器的结构

解释器的核心是「中间表示」(Intermediate representation,IR)。这就是如何在内存中表示IMP程序。因为IMP是一个很简单的语言,中间表示将直接对应于语言的语法;每一种表达和语句都有对应的类。在一种更复杂的语言中,你不仅需要一个「语法表示」,还需要一个更容易分析或运行的「语义表示」。

解释器将会执行三个阶段:

将源码中的字符分割成标记符(token)

将标记符组织成一棵抽象语法树(AST)。抽象语法树就是中间表示。

评估这棵抽象语法树,并在最后打印这棵树的状态

将字符串分割成标记符的过程叫做「词法分析」,通过一个词法分析器完成。关键字是很短,易于理解的字符串,包含程序中最基本的部分,如数字、标识符、关键字和操作符。词法分析器会除去空格和注释,因为它们都会被解释器忽略。

将标记符组织成抽象语法树(AST)的过程称为「解析过程」。解析器将程序的结构提取成一张我们可以评估的表格。

实际执行这个解析过的抽象语法树的过程称为评估。这实际上是这个解析器中最简单的部分了。

本文会把重点放在词法分析器上。我们将编写一个通用的词汇库,然后用它来为IMP创建一个词法分析器。下一篇文章将会重点打造一个语法分析器和评估计算器。

词汇库

词法分析器的操作相当简单。它是基于正则表达式的,所以如果你不熟悉它们,你可能需要读一些资料。简单来说,正则表达式就是一种能描述其他字符串的特殊的格式化的字符串。你可以使用它们去匹配电话号码或是邮箱地址,或者是像我们遇到在这种情况,不同类型的标记符。

词法分析器的输入可能只是一个字符串。简单起见,我们将整个输入文件都读到内存中。输出是一个标记符列表。每个标记符包括一个值(它代表的字符串)和一个标记(表示它是一个什么类型的标记符)。语法分析器会使用这两个数据来决定如何构建一棵抽象语法树。

由于不论何种语言的词法分析器,其操作都大同小异,我们将创建一个通用的词法分析器,包括一个正则表达式列表和对应的标签(tag)。对每一个表达式,它都会检查是否和当前位置的输入文本匹配。如果匹配,匹配文本就会作为一个标记符被提取出来,并且被加上该正则表达式的标签。如果该正则表达式没有标签,那么这段文本将会被丢弃。这样免得我们被诸如注释和空格之类的垃圾字符干扰。如果没有匹配的正则表达式,程序就要报错并终止。这个过程会不断循环直到没有字符可匹配。

下面是一段来自词汇库的代码:

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

import sys

import re

def lex(characters, token_exprs):

pos= 0

tokens= []

while pos< len(characters):

match= None

for token_expr in token_exprs:

pattern, tag= token_expr

regex= re.compile(pattern)

match= regex.match(characters, pos)

if match:

text= match.group(0)

if tag:

token=(text, tag)

tokens.append(token)

break

if not match:

sys.stderr.write('Illegal character:%sn'% characters[pos])

sys.exit(1)

else:

pos= match.end(0)

return tokens

注意,我们遍历正则表达式的顺序很重要。lex会遍历所有的表达式,然后接受第一个匹配成功的表达式。这也就意味着,当使用词法分析器时,我们应当首先考虑最具体的表达式(像那些匹配算子(matching operator)和关键词),其次才是比较一般的表达式(像标识符和数字)。

词法分析器

给定上面的lex函数,为IMP定义一个词法分析器就非常简单了。首先我们要做的就是为标记符定义一系列的标签。IMP只需要三个标签。RESERVED表示一个保留字或操作符。INT表示一个文字整数。ID代表标识符。

Python

1

2

3

4

5

import lexer

RESERVED='RESERVED'

INT='INT'

ID='ID'

接下来定义词法分析器将会用到的标记符表达式。前两个表达式匹配空格和注释。它们没有标签,所以 lex会丢弃它们匹配到的所有字符。

Python

1

2

3

token_exprs= [

(r'[ nt]+',None),

(r'#[^n]*', None),

然后,只剩下所有的操作符和保留字了。记住,每个正则表达式前面的“r”表示这个字符串是“raw”;Python不会处理任何转义字符。这使我们可以在字符串中包含进反斜线,正则表达式正是利用这一点来转义操作符比如“+”和“*”。

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

(r':=', RESERVED),

(r'(',RESERVED),

(r')',RESERVED),

(r';', RESERVED),

(r'+',RESERVED),

(r'-', RESERVED),

(r'*',RESERVED),

(r'/', RESERVED),

(r'<=',RESERVED),

(r'<', RESERVED),

(r'>=',RESERVED),

(r'>', RESERVED),

(r'=', RESERVED),

(r'!=',RESERVED),

(r'and', RESERVED),

(r'or',RESERVED),

(r'not', RESERVED),

(r'if',RESERVED),

(r'then',RESERVED),

(r'else',RESERVED),

(r'while', RESERVED),

(r'do',RESERVED),

(r'end', RESERVED),

最后,轮到整数和标识符的表达式。要注意的是,标识符的正则表达式会匹配上面的所有的保留字,所以它一定要留到最后。

Python

1

2

3

(r'[0-9]+',INT),

(r'[A-Za-z][A-Za-z0-9_]*', ID),

]

既然正则表达式已经定义好了,我们还需要创建一个实际的lexer函数。

Python

1

2

def imp_lex(characters):

return lexer.lex(characters, token_exprs)

如果你对这部分感兴趣,这里有一些驱动代码可以测试输出:

Python

1

2

3

4

5

6

7

8

9

10

11

import sys

from imp_lexer import*

if __name__=='__main__':

filename= sys.argv[1]

file= open(filename)

characters= file.read()

file.close()

tokens= imp_lex(characters)

for token in tokens:

print token

继续……

在本系列的下一篇文章中,我会讨论解析器组合,然后描述如何使用他们从lexer中生成的标记符列表建立抽象语法树。

如果你对于实现IMP解释器很感兴趣,你可以从这里下载全部的源码。

在源码包含的示例文件中运行解释器:

Python

1

python imp.py hello.imp

运行单元测试:

Python

1

python test.py

关于代码解释器,代码编辑器下载的介绍到此结束,希望对大家有所帮助。

css通用选择器,css三种基本选择器的用法正则表达式大全?正则表达式入门