其他分享
首页 > 其他分享> > lambda解释器_Lambda Interpreter

lambda解释器_Lambda Interpreter

作者:互联网

代码参考:

200行JS代码实现lambda解释器

PP大佬代码

解释器构造

一个lambda interpreter主要由一下几个方面构成:

其他工具类:

TokenType

LPAREN: '('
RPAREN: ')'
LAMBDA: '\' // 为了方便使用 “\”
DOT: '.'
LCID: /[a-z][a-zA-Z]*/ 
EOF:输入流终止

Lexer

处理 token 的辅助方法:(可以自行定义)

注:调用next和match是如果为true就向控制台输出Token类型+换行

Parser

语法规则

BNF范式(巴科斯范式)简介

1.Term ::= Application| LAMBDA LCID DOT Term

2.Application ::= Application Atom| Atom
//这里需要做一个特殊处理,本条规则为左递归,会导致无限递归,因此将其处理为右递归
application ::= atom application'
application' ::= atom application'| ε

3.Atom ::= LPAREN Term RPAREN| LCID
抽象语法树 AST构造

lambda 演算的 AST 非常简单,因为我们只有 3 种节点:

Abstraction 
    Identifier param;//变量
    AST body;//表达式
toString显示为: \.body.toString()
Application
    AST lhs;左树
    AST rhs;右树
toString显示为: (lhs.toString()空格rhs.toString())
Indentifier
	String name;//变量名
    String value;//De Bruijn index
toString显示为: value
De Bruijn index

使用德布鲁因值来避免变量重名导致的规约结果不同

(\x.\y.x \f.\g.g)
首先转化为:(变量保持不变,数字从0开始代码同层变量,1代表上一层次变量。)
(\x.\y.1 \f.\g.0)
toString显示为:(为了防止alpha变换造成的不一致,去掉变量)
(\.\.1 \.\.0)

Interpreter

求值evalAST(递归思路)

evalAST规则:

substitute

这里需要做一个处理,因为代换以后最外层会消掉一个lambda,所以所有变量要shift位移-1,而value中的叶节点代入是就需要补位移一个1;

subst变量代换
shift德布鲁因值位移

Main方法

public static void main(String[] args) {

        String source = "(\\x.\\y.x)(\\x.x)(\\y.y)";

        Lexer lexer = new Lexer(source);

        Parser parser = new Parser(lexer);

        Interpreter interpreter = new Interpreter(parser);

        AST result = interpreter.eval();

        System.out.println(result.toString());
}

Test


    @Test
    public void testLexer() {
        Lexer lexer = new Lexer(sources[1]);
        Parser parser = new Parser(lexer);
        AST ast = parser.parse();

        assertEquals("LPAREN" + lineBreak+
                "LPAREN" + lineBreak+
                "LAMBDA" + lineBreak+
                "LCID" + lineBreak+
                "DOT" + lineBreak+
                "LAMBDA" + lineBreak+
                "LCID" + lineBreak+
                "DOT" + lineBreak+
                "LAMBDA" + lineBreak+
                "LCID" + lineBreak+
                "DOT" + lineBreak+
                "LCID" + lineBreak+
                "LPAREN" + lineBreak+
                "LCID" + lineBreak+
                "LCID" + lineBreak+
                "LCID" + lineBreak+
                "RPAREN" + lineBreak+
                "RPAREN" + lineBreak+
                "LPAREN" + lineBreak+
                "LAMBDA" + lineBreak+
                "LCID" + lineBreak+
                "DOT" + lineBreak+
                "LAMBDA" + lineBreak+
                "LCID" + lineBreak+
                "DOT" + lineBreak+
                "LCID" + lineBreak+
                "RPAREN" + lineBreak+
                "RPAREN"+lineBreak+
                "EOF"+lineBreak,bytes.toString());

    }

    @Test
    public void testParser() {
        Lexer lexer = new Lexer(sources[1]);
        Parser parser = new Parser(lexer);
        AST ast = parser.parse();
        assertEquals("(\\.\\.\\.(1 ((2 1) 0)) \\.\\.0)",ast.toString());


    }

    @Test
    public void testInterpreter() {
        Lexer lexer = new Lexer(sources[1]);
        Parser parser = new Parser(lexer);
        interpreter = new Interpreter(parser);

        AST ast = parser.parse();

        AST result = interpreter.eval(ast);

        assertEquals("\\.\\.(1 0)",result.toString());


    }

标签:lineBreak,toString,AST,Lexer,LCID,new,Interpreter,Lambda,lambda
来源: https://blog.csdn.net/newlw/article/details/122522117