在java中编写自定义语法解释器?

use*_*100 4 java parsing runtime anonymous-class

我即将开始编写一个演示程序来编写我即将给出的演讲.我想让班上的每个学生都下载这个应用程序,然后能够通过命令行以交互方式创建对象实例(及其图形表示).我决定用Java写的,而不是因为它是我最熟悉的语言,而是因为它有简单的图形类,我可以很肯定的罐子会在他们的计算机上运行.

简介.现在的问题是:

为此程序实现某些自定义命令行语法的好方法是什么?我想使用一个简单,随意的语法,如:

CREATE Monster Bob;    
Bob.jump();   
LS Bob //to list Bob's methods or something.   
LS CREATE //to list all the classes    
Run Code Online (Sandbox Code Playgroud)

首先,当我想到这个问题时,我会首先想到的是什么.

我可以想象我可以在树型链接中拥有一组地图.我可以解析每个关键词作为下一个地图的关键.因此,"CREATE Monster Bob"可以被评估为

1)搜索关键字"CREATE"的关键字映射.返回值,这是对类映射的引用.2)搜索类映射关键"怪物".返回值,这是一个实现一些接口Leaf的工厂类,它让我知道它是一个叶子值(我将使用instanceof进行检查).
3)也许Leaf接口将包含一个名为execute()的方法,它可以做任何想做的事情.在这种情况下,它将创建一个Monster对象,将此对象添加到名为Objects的名为Bob的地图中.(这个Leaf业务听起来很丑,但可以清理.)

凉.但这句话对我来说有点困难:Bob.jump();

1)搜索"Bob"的一些对象图.返回一些对象实现一个接口与等的方法"评价(字符串或多个)",并将它传递字符串"跳()"
2)鲍勃搜索的用于"跳()"方法的一些内部地图,然后...?在c ++中,我将使用键作为指向要执行的成员函数Monster.jump()的指针.但是我不相信java中没有函数指针这样的东西.我已经读过你可以使用匿名类来完成这个,虽然我没有尝试过.看起来它会起作用.

所以,这将有效,但有更优雅的方式去做吗?我以前从未写过任何类型的翻译.如果有人提供一些提示,我想以一种很好的方式做一些事情并在这个过程中学到一些东西.如果我不是很结构化的话,这似乎是一种可能容易出错的方法,特别是当Bob和其他所有对象开始解析他们自己的指令并使用匿名函数时.此外,看起来除了普通代码之外,每个类都需要一个运行时就绪的接口.

我也不知道Java的那么好,所以如果有一些景点在那里我可能会撞到南墙,然后我想太了解.

我在这里先向您的帮助表示感谢.

小智 11

我实际上建议使用Python - 除非有一个非常好的理由不这样做.

这是因为:

  1. Python有一个非常好的 IDE/REPL,叫做IDLE.我不能说使用一个好的Read-Eval-Print-Loop:反馈周期非常适合学习/播放.喜欢冒险的学生甚至可以跳进去!
  2. 图形支持是跨平台的,并且通过TkInter得到良好支持.
  3. 对于初学者和/或非程序员而言,我发现它比Java更好.(Python实际上不是我最喜欢的语言,但它非常适合初学者,并且有一个非常好的IDE/REPL.)
  4. 这对你来说要少得多 ;-)

这就是演示的Python代码的外观:

Bob = BigMonster()
Bob.jump()
dir(Bob)
dir(Monters)
Run Code Online (Sandbox Code Playgroud)

因为所有这些只是常规的Python语法,所以没有解析 - 只需创建几个类,也许实现__dir__协议,一切都准备好了.如果Java集成是一个要求也有Jython的,虽然我从来没有尝试过,与IDLE(或者知道它是否支持这样).

快乐的编码.

一种基于图像的Smalltalk的Sqeak远远比Python更互动的代码持久运行环境的一部分.但是,找到一个好的图像需要一些时间 - 吱吱声不是最好的实现,但它是免费的 - 并且学习特定的SmallTalk环境.因此,虽然集成最终可以获得很大的支出,但它确实需要更多的适应性:)


但是,唉,要在Java中使用一个简单的解析器,这些将是有趣的:

  1. 一个词法分析器,它将输入文本转换为令牌的蒸汽,并且;
  2. 还有一个递归下降解析器(这是一种非常简单的解析方法)
    1. 构建一个AST(抽象语法树),可以在以后行走(读取:"运行"),或者;
    2. 或者"现在做东西"(立即评估)

简单的递归下降解析器是上面概念的Java崩溃课程简介.下面是一些用于"中微子语法"的递归下降解析器的代码,无论是什么 - 查看注释以及递归下降解析器 EBNF语法的匹配程度.

现在,它只是"定义"这种伪/迷你语言的语义规则并实现它的问题;-)


更多地探索语义/ Java方法(部分只是原始帖子的简化/重新声明):

CREATE Monster Bob
Run Code Online (Sandbox Code Playgroud)

会创建一个新的MonsterObject.一些方法可能是:

  1. 用反射创建对象,或;
  2. 如上所述的Factory类(来自String - > FactoryObject)的映射,或;
  3. 一个简单的静态if-else-branch.

结果将存储在映射Name - > MonsterObject的"变量散列"中.

Bob.jump()
Run Code Online (Sandbox Code Playgroud)

将其解析为[object Bob] [method jump] [p1], [p2], ..., [pn],在"变量哈希"中查找对象,然后:

  1. 使用反射来调用方法,或;
  2. 有名称的地图(通过MonsterObject的方法检索) - > MethodEvaluatorObject(例如具有eval(Object ... params)法),或;
  3. 调用表单的方法eval(String action, String[] ... parameters)并让它使用if-else-branch来"do stuff"(注意参数,如果有的话,在解析过程中已经分离出来).

LS Bob并且LS Monster很好地依赖前两个如何实现.

虽然Java没有"函数指针",但可以通过使用具有给定接口的对象来模拟它们(即,对象本身充当指针).Functional JavaF/F2 /.../ F8类试图用泛型统一处理它.但是,在Java中,通常会创建一个单独的一次性接口(或类),如Runnable,它具有单个"action"方法,该方法被修改为接受适当的参数并返回适当的结果(例如MethodEvaluatorObjects或FactoryObjects).

如果有任何具体的有关议题之一问题(反射,递归下降,匿名类型,[模拟]封闭等等),然后随便问另一个 SO问题与特定的焦点.(并且,一如既往,研究中的尽职调查得到回报;-)