# SchemeInterpreterJava **Repository Path**: RAYPALMER/SchemeInterpreterJava ## Basic Information - **Project Name**: SchemeInterpreterJava - **Description**: 情怀驱使 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2017-10-20 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SchemeInterpreterJava 整个项目使用Java语言编写,用于解释执行Scheme语言,本项目不会过多做很多人性化的功能,比如输入一个文件,分析一个scheme文件等等, 不存在的。项目clone下来以后使用IntelliJ运行, 直接在console里面输入scheme语句就可以进行解释执行 # 基本配置 `IntelliJ IDEA` `Java 8` # 疑难点记录 ## 语法分析阶段和运行时阶段 对于这两个阶段,在编程的时候,经常会进行混淆,就是到底该什么时候检查类型 错误,比如如下语句 ```aidl (define a 1) ``` 不用怀疑,是正确的。 但是如果出现了下面的语句 ```aidl (define a (define b 1)) ``` 明显是不正确的,这里就需要考虑在哪里检查这个错误,针对这个问题,有一个 很好的知道方针,装逼点说就是“上下文无关语法”,通俗点说就是语法分析阶段 要进行检查的仅仅只有这条语句满不满足正则表达式即可。 上面的 ```aidl (define a (define b 1)) ``` 是符合正则表达式的,所以语法阶段是允许通过的,但是会出现运行时错误。 **编程时要时刻注意,时刻用这个方针指导自己** ## (define)和(set!)的返回值问题 ### 2017.10.25记录 这个问题本身我纠结了很久,就是define和set!究竟有没有返回值,以及 如果有,该如何定义,这里目前没有想到什么好的方法,我觉得只能进行 特殊处理。 存在以下代码 ``` (define a (define a 1)) ``` 运行是会出错的,因为define没有返回值,但是如果出现了这种代码 ```concept (define a (void)) a ``` 即执行define操作,然后在输入a,那么command-line中会什么都没有 ,直接等待下面的执行,然后使用 ```concept (void? a) ``` 成功执行,返回#t,所以void类型确实是真实存在的。 ### 2017.10.27记录 今天我对这两个语句进行了如下处理,还包括之后的let和let* 让这四种语句返回值是BLOCKING,意思是阻断,此语句的返回值不能被 use。 ## 对于SchemeQuoted的处理 自我感觉'()这种运算需要好好思考一下,如果定义如下语句 ```concept (define a 1) (apply + '(1 2 3 a)) ``` 代码会报错,因为这里加上了点号,不会对列表里面的a进行解释了。 # 编程技巧 ## Predicate函数式接口的使用 在Parser部分的代码中,需要适当地检查一下参数的合法性,比如 ```aidl (define a 1) ``` 其中第二个参数就不能是除Atom之外的其他的Token的子类,又比如 ```aidl (if (< x 1) (display 0) (display 1)) ``` 其中第二个参数就只能是Atom,或者是一个Call,或者就仅仅是一个Boolean 类型的字面量,其他的Token子类不允许出现。 所以我们可以这样设计代码 ```aidl static Predicate IsDefineOrSet = e -> e instanceof SchemeDefine || e instanceof SchemeSet; static Predicate IsProceOrRef = e -> e instanceof SchemeProcedure || e instanceof SchemeAtom; static Predicate IsCallOrRef = e -> e instanceof SchemeCall || e instanceof SchemeAtom; static Predicate IsNumber = IsCallOrRef.or(e -> e instanceof SchemeNumber); static Predicate IsString = IsCallOrRef.or(e -> e instanceof SchemeString); static Predicate IsBoolean = IsCallOrRef.or(e -> e instanceof SchemeBoolean); static Predicate IsList = IsCallOrRef.and(e -> { SchemeQuoted Quoted = e instanceof SchemeQuoted ? (SchemeQuoted) e : null; if (Quoted == null) { return false; } else { return Quoted.getContent() instanceof SchemeList; } }); ``` 通过设计基本的条件,以及对条件进行组合,我们可以得到逻辑清晰的 Predicate函数式接口,便于之后的编程。