自制操作系统Antz(14)——实现内置编程语言(词法解析器)

AntzScript

?? The language executed in the Antz system.

基于以实现的内置vim,接下来需要实现Antz系统中内置语言AntzScript。

Antz系统更新地址

Antz项目地址

AntzScript项目地址

vim

一、概述

1. 解释器与编译器

1.1 解释器

解释器根据程序中的算法执行运算。简单地说,它是一种用于执行程序的软件。

1.2 编译器

编译器能将某种语言写成的程序转换为另一种语言的程序。通常它会将源程序转换为机器语言程序。编译器转换程序的行为称为编译,转换前的程序称为源程序。

  • Java虚拟机为了提高性能,会在执行过程中通过编译器将一部分Java二进制代码直接转换为机器语言使用。

过去的编译器编译过程非常费时,不过由于编译后实际执行的是机器语言,因此执行速度很快。而解释器,会在程序输入的同时立即执行,执行速度较慢。这就是两者的基本区别。

在为Antz制作内置脚本语言时,因为是直接执行,处理器属于解释器,不过,为了提高性能,该解释器内部将采用编译器。

基本流程如下

2. Token

语言处理器的第一个组成部分是词法分析器(lexer)。程序的源代码最初只是一长串字符串,这样的字符串很难处理,语言处理器通常会首先将字符串中的字符以解析单元分组,切割成多个Token,这就是词法分析。

解析结果

Token类中需要对源代码分割成最小单元,并解析出变量类型数值量符号标识符

Token
Token中k代表单元含义,lexeme代表其在代码中的内容。kindMap是一个提前预置关系转换符表。在需要添加其他关键字时可以直接在KindMap中添加。

词法解析器的实现方法有手工构造法和正则表达式的方法。

手工构造法-状态图

这种方法较为复杂,需要大量的代码,而正则表达式的方法较为便捷。

二、实现词法解析

借助正则表达式库能简单地实现词法分析器。下表列出的记号在大多数情况下都能使用。例如,.*\.java指的是以.java结束的任意长度的字符串模式。.*\.由两部分组成,.*表示由任意字符组成的任意长度的字符串模式,\.表示与句点字符相匹配的字符串模式。(java|javax)\..*则表示由java.javax.起始的任意长度的字符串模式。

元字符 含义
. 与任意字符匹配
[0-9] 与0至9中的某个数字匹配
[^0-9] 与0至9这些数字之外的的某个字符匹配
pattern* 模式pattern至少重复出现0次
pattern+ 模式pattern至少重复出现1次
pattern? 模式pattern出现0次或1次
pattern1 pattern2
() 将括号内视为一个完整的模式
\c 与单个字符c(元字符*或.等)匹配

整型字面量的匹配

[0-9]+

标识符的匹配

[A-Z_a-z][A-Z_a-z0-9]*
  • 以字母、下划线开头,之后仅包含有字母、数字、下划线的就是标识符的定义规则。
[A-Z_a-z][A-Z_a-z0-9]*|==|<=|>=|&&|\|\||\p{Punct}

最后的\p{Punct}表示与任意一个符号字符匹配。模式\|\|将会匹配||。由于|是正则表达式的元字符,因此在使用时必须添加反斜线转义。

最后需要定义的是字符串字面量。由于不得不处理各种转义字符,字符串字面量的定义略微复杂。

"(\\"|\\\\|\\n|[^"])*"

首先,从整体上看,这是一个"(pattern)*"形式的模式,即双引号内是一个与pattern重复出现至少0次的结果匹配的字符串。其中,模式pattern与\"\\\n匹配,同时也与除"之外任意一个字符匹配。

所以我们可以得到一个下图的匹配规则regexPat。

ArrayList<Token> tokens是词法解析器Lexer中已解析的Token

源码source作为参数传入Lexeradd方法中。

在创建Token时,单元作为构造函数的参数。同时变量,数字值等单元我们无法通过KindMap类来判断k值,所以需要在这里判断。

判断是否是变量类型
判断是否是数值类型
判断是否是字符串类型

三、效果

测试代码
Token解析

将源代码转换为了相应的Token单元,这就是词法解析的主要工作了。

接下来按照源代码获得转换后的直译代码。

效果图

原文地址:https://www.cnblogs.com/LexMoon/p/antz14.html

时间: 2024-11-07 08:33:46

自制操作系统Antz(14)——实现内置编程语言(词法解析器)的相关文章

Android通过意图使用内置的音频播放器

如果实现一个音频文件的播放,那么在应用程序中提供播放音频文件功能的最简单的方式是利用内置的"Music(音乐)"应用程序的功能--即使用系统自带的或已安装好的音乐播放器来播放指定的音频文件. 本例比较简单,下面直接给出源代码: 布局文件activity_main: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http:/

Mysql研究之MySQL常用内置函数完全解析

说明: 1)可以用在SELECT/UPDATE/DELETE中,及where,orderby,having中 2)在函数里将字段名作为参数,变量的值就是字段所对应的每一行的值. 3)在程序设计语言如C++中提供的函数,MySQL大部分也提供了,关于MySQL函数的完整信息,请参阅<MySQL参考手册> 一.字符串函数[比较常用,需要掌握] 1. concat(s1,s2,…,sn) #把传入的参数连接成一个字符串 selectconcat(‘abc’,’def’); selectconcat(

14、内置函数、递归函数、匿名函数

一.内置函数 # print(abs(-1))# print(all([1,2,3]))# print(all([0,2,3])) # print(all('')) # print(any([0,None,'',1]))# print(any([0,None,'']))# print(any([])) # print(bin(3))# print(hex(17))# print(oct(9)) #0 None 空===>bool值为False,其余都为True # def func():# pa

14,内置函数,和匿名函数

作用域相关: locals :函数会以字典的类型返回当前位置的全部局部变量. globals:函数以字典的类型返回全部全局变量 a = 1 b = 2 print(locals()) print(globals()) # 这两个一样,因为是在全局执行的. #########################################华丽分割线 def func(argv): c = 2 print(locals()) print(globals()) func(3) #这两个不一样,loca

python基础篇【第四篇】内置函数、装饰器:

一.内置函数: 对于一些python中常用的函数,python自身就已经定义了一些函数用于调用,我们就叫它内置函数!如以下都是python中内置的函数! 一些常用的内置函数具体用法: 一些常用的内置函数具体用法: 1.abs():取绝对值 1 n=abs(-2) 2 print(n) 3 4 结果: 5 2 2.all();传入可迭代的对象中,都为真才为真; Fasle: 0,None,"",[],{} ,()都为假True: 1,-1,True,有值返回真. n=all([1,2,3

python学习之路-4 内置函数和装饰器

本篇涉及内容 内置函数 装饰器 内置函数 callable()   判断对象是否可以被调用,返回一个布尔值 1 2 3 4 5 6 7 8 9 10 11 num = 10 print(callable(num))   # num不能够被调用,返回False    def f1():     print("name")    print(callable(f1))     # f1可以被调用,返回True    # 输出 False True ?chr()   将十进制整数转换为asc

python之路 内置函数,装饰器

一.内置函数 #绝对值 abs() #所有值都为真才为真 all() #只要有一个值为真就为真 any() #10进制转成二进制 bin() #10进制转成八进制 oct() #10进制转成十六进制 hex() #布尔值 bool() #字符转换成字节 bytes() #字节转换成字符 str() #对文件的操作 open() #基本流程 #打开文件 op_file=open("file name","rwb+") #操作文件 op_file.operation()

Python学习之旅 —— 基础篇(四)内置函数、装饰器

本篇要点: 内置函数 装饰器 一.内置函数 # abs() :取绝对值 >>> res = abs(-10) >>> print(res) 10 # 0,None,"",{},[],() 布尔值都为空 # all(),any() 判断值的真假 # all() 所有为真才为真 p = all([0,1,2,3]) # 0为False,所有p 是False print(p) # any() 任意一个为真即为真 p = any((0,""

2017年05月10日记一次微项目投产 | 安卓版微信内置浏览器不能解析gzip压缩过的mp4视频的问题

前言 今天投产了一个小项目,一个很简单的H5,有播放视频功能,使用了videojs插件. 之前也做过数个视频播放,视频的转压都按照既定流程进行,文件放到FTP后,iphone和安卓机测试下来都没有问题. 于是给链接,业务组直接在微信公众号里投放了.那个企业号有不少关注的人,推送发出去1分钟就有近千阅读量. 但是我在点击链接后,发现项目打不开了,而且该企业官网的主站也挂了,在经过pc端和手机4G下测试发现问题依然存在后,赶紧报bug给其他同事. 通过询问FTP管理员得知,那个"大"企业的