每日五分钟:学习编写编程语言

最近心血来潮,就来学学写语言。

大家可能觉得写一个语言很难,但是其实,怎么说呢,其实理解理解一下会发现没有想象中的难懂。我这里就用javascript 示范写一个lisp语言。

为什么是lisp呢?因为它语法简单,整个语言语言就是围绕()。

(* 3 (+ 1 2))

今天就先看看语言的编译过程。

一个语言从文字到被电脑运行的过程,分为:

1. 扫描 (scanning):就是把文字读入内存,这个很简单,相信大家都会。用linux bash就是

file=$(<code.lisp)
node index.js $file

2. 解析 (parsing):把内存的文字逐一拆解分析,比如

const parser = line => {
  return line
    .replace(/\(/g, ' ( ')
    .replace(/\)/g, ' ) ')
    .split(/\s+/g)
    .filter(x => x)
}

这样以来就能把

(* 3 (+ 1 2))

分解成

['(', '*', '3', '(', '+', '1', '2',')',')']

当然还不止那么简单,我们这里就要定义我们的语言原件是什么

我们这个简单lisp的话就是

1. 左括弧是开始

2. 右括弧是结束

3. 数字就是号码

4. 不是数字的都是符号

就这。

所以我们写一写这个的处理函数就是这样的

const isNumeric = str => {
  if (typeof str != 'string') return false
  return !isNaN(str) &&
    !isNaN(parseFloat(str))
}

const atomize = (token) => {
  if (isNumeric(token)) {
    return +token
  } else {
    return Symbol.for(token)
  }
}

这里用了Javascript里es6的Symbol是为了方便,它就是符号的意思,拿来代表别的东西。

然后接下来就是括弧的处理

const LEFT_BRACE = '('
const RIGHT_BRACE = ')'

const reader = tokens => {
  if (tokens.length === 0) {
    throw new SyntaxError('Unexpected EOF')
  }
  let token = tokens.shift()
  if (token === LEFT_BRACE) {
    let context = []
    while (tokens[0] !== RIGHT_BRACE && tokens.length > 0) {
      context.push(reader(tokens))
    }
    tokens.shift()
    return context
  } else if (token === RIGHT_BRACE) {
    throw new SyntaxError('Unexpected )')
  } else {
    return atomize(token)
  }
}

就是那么简单,这样的话还能处理嵌套。

结果就是一个

[ Symbol(*), 3, [ Symbol(+), 1, 2 ] ]

就是在代码内有了一个语言的真实模型。

先这里停一停休息一下。

 

如果点赞超过50个我就继续下一章吧!

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值