Skip to content

Lite 1.0 到 Lite 1.1 的语法变化

duangsuse edited this page May 7, 2018 · 7 revisions

Lite 1.0 -> 1.1 版本升级 See Also

新版本使用了手写的 Lexer 和 Deflator(为使用缩进的语义添加 end

使用 PEG.js 作为解析器生成器, 目标是生成序列化 JSON,需要使用的时候让解释器反序列化得到 AST

使用 JavaScript 解析器生成器,使用 Json 在 Java 和 Js 之前交换 AST 数据结构

使用松耦合解析器(Reflect 调用解析器),允许将 Lite 代码文本「编译(解析)」成 AST JSON, 执行时加载

分别为 Android 和 JavaSE 平台实现 JS 解析器接口

内部方法调度支持 Lite fallback block

lay << @text # 这是 Lite 1.1 的语法, AST 解释器的内部隐式方法调用支持内部实现 def LinearLayout$add ..... 内部特殊方法调用支持 Lite fallback

Why?

提供了 Lite 的部分运算符重载特性,允许 Lite 拥有更优雅的语法

def System.getEnv # Java 这里比较 emmmmm.... 没有用标准的方法名风格
  return System.getenv() # Just an alias of System#getenv

System.env::HOME #=> "/home/dse"
# instead of
System.getEnv::HOME

import android.widget
import android.view
def LinearLayout.add(view)
  self.addView view

def Button.new
  return Button(ctx) # or Button(lite[:ctx])

layout << Button.new
# instead of
layout.addView(Button(ctx))

Fallback 方法允许向类继承树上查找到 java.lang.Object

def Object.eq? other
  return self.equals other

基于对象 hash 的 singleton Fallback 方法

def System.out.cprintln

基于 range 的 for 和 range 支持

for i in 1..4

添加了一个创建 LiteRange 的二元操作符 .. 1..2 2..a 0..(1 + 1)

这个不解释,没啥好解释的

支持 case 语句

case input.text
"OC<"
puts ""
contains "foo" exit
nil exit if false
length(0) puts "${input.text}"

支持字符串内联表达式语法糖(由 Lexer 处理脱糖)

"$variable" "${expression}"

高级的块参数填充(*varargs/name=default)

puts "Hello" "Word\n"

参考 BeanShell 为解释器实现 Java 接口 (java.io.Serializable, 从 Object 类实现部分应该重载的方法)

  • Interpreter 类需要实现 Serializable

参考 BeanShell 默认加载一些 Java 包

  • java.lang 你们肯定没意见
  • LuaJava 和 BeanShell 的部分导入

裁剪合适的语法

  • trace 1 trace 有何德能作为关键字
  • import 后面是不用加 '' 的 string

支持 or/and 操作符

when a
  is 1 or 2 or 3

二元操作中支持数值类型自动提升 (参考 BeanShell)

Math.random + 1l

BeanShell 的实现位置: https://github.com/beanshell/beanshell/blob/master/src/main/java/bsh/Primitive.java#L592

Lite 目前支持手动提供要 cast 到的类型,也是复制粘贴了很多代码

修复 as 表达式

(1L as Integer) (Math.random as Float) 是预期的用途, 不是默认 Class#cast (当然也有这个功能,但应该优先处理数值(Number)类型)

支持 paren expression

以上

其他

  • 内建 AST Formatter 支持缩进格式化

  • 提高内部代码重用数量

  • 写好 JavaDoc

  • 使用 Class#cast 解决编译器的 unchecked 问题

  • 为实现过程写尽可能多的注释

  • 完全测试(但不测试驱动开发)

  • 包装好,使用 CI(后事)

  • 为代码文本处理部分添加 Deflator 和 JsonAst 类

部分 1.1 版本代码

foo = String()
foo = 1 if Math.random > 0.5

when foo
  class String # getClass() == String
    puts foo
  class Double
    puts "${foo}D"
  is 1
    exit()
  is 0 or 2 or 3
    puts()

a = { self: nil }
def a.new(obj)
  a->self { obj: obj }
  a->print { print self.obj }
aa = a.new 1 + 1
aa.print()
# 如果是 @a 就直接用
# @a->new do |obj| 吧

# file a
import android.widget

scope android
  def @LinearLayout.add(v)
    self.addView(v)

# file b
scope android
  lay << Button(ctx)

def 语法变更

def 的特殊标识符(就是使用 '.' 语法的标识符)(对于一个 identifier 来说没有什么特殊的,但 Lite 目前不能解析带 '.' 的 identifier(和那个 '.' 操作符冲突了) Lite def 目前可以使用带 '.' 的特殊 全局 标识符语法来创建特殊的方法(在 Lite 内部表示为 全局上下文 的普通变量 java_lang_System!println xor@java_lang_Number $ xor Missing_java_lang_Object (Lite 那时不支持内部类, 这次应该会支持, 内部类的 $ 会被看作 .))

def 到 Map<String, ?> (同时也是 Lite 的 Table) 中
a = { self: nil }
def a.new(obj)
  a->self { obj: obj }
  a->print { print self.obj }
aa = a.new 1 + 1
aa.print()
如果是 @a 就直接用
@a->new do |obj| 吧
Java FFI 的用途

为类创建静态方法 fallback java_lang_System!getEnv
为类创建方法 fallback join@java_lang_String
为类创建 methodMissing Missing!java_lang_Object
为对象创建单例方法 Singleton_(hashcode)

字面值表示修改

https://github.com/duangsuse/Lite/issues/1#issuecomment-386947676 写道:

追加一个语法特性:

String 字面量支持更多 escape

参考 https://github.com/lice-lang/lice/blob/master/src/main/kotlin/org/lice/parse/Lexer.kt#L189

参考 http://ice1000.org/2018/02/18/SyntaxDesign/ 里的尴尬情况, 当然 Lite 的词法很简单,不存在此问题(String 字面就是 String 字面,当前版本也没有太多转义 而且转义是后来处理的,字符串在解析过程中也没有什么特殊处理,就是 '"' string data '"')

如果转义不对,Lite 的 Lexer 要失败报错(同时现在 Lexer 的错误检查也太弱了,得增强一下)

对于 0x 0b 0o 这种数字字面量变换语法,也要支持(不是在分词器里,因为那里只认为数字是 [0-9] 到 一个空白字符结束)

但 012345 这种令人费解的 8 进制语法不可以支持,不得不说这么设计的确很纸张....

如果可能的话,Lexer 和 Parser 这种机械化的东西我会使用 JFlex/PEG.js|OHM.js 自动生成