当前位置: 首页 > news >正文

手把手开发一门程序语言JimLang (2)

根据爱因斯坦的相对论,物体的质量越大,时间过得越快,所以托更对于我的煎熬,远远比你们想象的还要痛苦…今天给大家来盘硬菜,也是前些时日预告过的JimLang的开发过程… Let’s go !!!

语法及解析

JimLang.g4

这里我们还是借用ANTLR来做解析器,构建基础的函数语法

grammar JimLang;prog:  statementList? EOF;statementList : ( variableDecl | functionDecl | functionCall | expressionStatement  )* ;assignment: '=' singleExpression ;returnStatement: RETURN  expressionStatement;variableDecl : VAR identifier typeAnnotation? ( assignment )* ';';
typeAnnotation : ':' typeName;functionDecl: FUNCTION identifier '(' parameterList? ')' functionBody ';'? ;
functionBody: '{' statementList?  returnStatement? '}';
functionCall: (sysfunction |  identifier) '(' parameterList? ')';expressionStatement: singleExpression | singleExpression ';';
singleExpression: primary (binOP primary)* ;
primary: ID |  NUMBER_LITERAL| STRING_LITERAL | BOOLEAN_LITERAL |  functionCall | '(' singleExpression ')' ;
binOP : '+'| '-'| '*'| '/'| '='| '<='| '>=';parameterList: singleExpression (',' singleExpression)*;
identifier: ID;sysfunction : 'print'| 'println'
;typeName :  'string'|  'number'|  'boolean';VAR: 'var';
FUNCTION: 'function';
RETURN: 'return';BOOLEAN_LITERAL: 'true' | 'false' ;STRING_LITERAL: '"'[a-zA-Z0-9!@#$% "]*'"';
NUMBER_LITERAL: [0-9]+(.)?[0-9]?;ID  :   [a-zA-Z_][a-zA-Z0-9_]*;
//WS  :   [ \t\r\n]+ -> skip ;WS:                 [ \t\r\n\u000C]+ -> channel(HIDDEN);
COMMENT:            '/*' .*? '*/'    -> channel(HIDDEN);
LINE_COMMENT:       '//' ~[\r\n]*    -> channel(HIDDEN);

JimLangVistor.java

构建vistor

package com.dafei1288.jimlang;import com.dafei1288.jimlang.metadata.StackFrane;
import com.dafei1288.jimlang.metadata.Symbol;
import com.dafei1288.jimlang.metadata.SymbolFunction;
import com.dafei1288.jimlang.metadata.SymbolType;
import com.dafei1288.jimlang.metadata.SymbolVar;import com.dafei1288.jimlang.parser.JimLangBaseVisitor;
import com.dafei1288.jimlang.parser.JimLangParser.AssignmentContext;
import com.dafei1288.jimlang.parser.JimLangParser.FunctionCallContext;
import com.dafei1288.jimlang.parser.JimLangParser.FunctionDeclContext;
import com.dafei1288.jimlang.parser.JimLangParser.PrimaryContext;
import com.dafei1288.jimlang.parser.JimLangParser.ReturnStatementContext;
import com.dafei1288.jimlang.parser.JimLangParser.SingleExpressionContext;
import com.dafei1288.jimlang.parser.JimLangParser.SysfunctionContext;
import com.dafei1288.jimlang.parser.JimLangParser.VariableDeclContext;
import com.dafei1288.jimlang.sys.Funcall;
import java.util.List;
import java.util.stream.Collectors;import java.util.Hashtable;
import org.antlr.v4.runtime.TokenStream;public class JimLangVistor extends JimLangBaseVisitor {Hashtable<String, Symbol> _sympoltable = new Hashtable<>();@Overridepublic Object visitVariableDecl(VariableDeclContext ctx) {String varName = ctx.identifier().getText();if(_sympoltable.get(varName) == null){SymbolVar symbol = new SymbolVar();symbol.setName(varName);symbol.setParseTree(ctx);if(ctx.typeAnnotation()!=null && ctx.typeAnnotation().typeName()!=null){symbol.setTypeName(ctx.typeAnnotation().typeName().getText());}for(AssignmentContext assignmentContext : ctx.assignment()){if(assignmentContext.singleExpression() != null &&  assignmentContext.singleExpression().primary() != null && assignmentContext.singleExpression().primary().size() > 0){SingleExpressionContext singleExpressionContext = assignmentContext.singleExpression();PrimaryContext primaryContext = singleExpressionContext.primary(0);if(primaryContext.NUMBER_LITERAL() != null){symbol.setValue(Integer.parseInt(primaryContext.NUMBER_LITERAL().getText().trim()));}else if(primaryContext.STRING_LITERAL() != null){symbol.setValue(primaryContext.STRING_LITERAL().getText());}else{}}}_sympoltable.put(varName,symbol);}return super.visitVariableDecl(ctx);}@Overridepublic Object visitSingleExpression(SingleExpressionContext ctx) {PrimaryContext primaryContext = ctx.primary(0);if(_sympoltable.get(primaryContext.getText())!=null){return _sympoltable.get(primaryContext.getText().trim()).getValue();}if(primaryContext.NUMBER_LITERAL() != null){return Integer.parseInt(primaryContext.NUMBER_LITERAL().getText().trim());}else if(primaryContext.STRING_LITERAL() != null){String text = primaryContext.STRING_LITERAL().getText();if(text.startsWith("\"")){text = text.substring(1,text.length()-1);}return text;}else if(primaryContext.BOOLEAN_LITERAL() != null){return Boolean.valueOf(primaryContext.BOOLEAN_LITERAL().getText());
//            return this.visitBooleanType(primaryContext.booleanType());}return super.visitSingleExpression(ctx);}@Overridepublic Object visitFunctionDecl(FunctionDeclContext ctx) {String functionName = ctx.identifier().getText();if(_sympoltable.get(functionName) == null){
//            System.out.println("define function ==> "+functionName);//            sympoltable.put(ctx.identifier().getText(),ctx);SymbolFunction symbol = new SymbolFunction();symbol.setName(functionName);symbol.setParseTree(ctx);if(Funcall.isSysFunction(functionName)){symbol.setType(SymbolType.SYSFUNCTION);}else{symbol.setType(SymbolType.FUNCTION);}if(ctx.parameterList()!=null && ctx.parameterList().singleExpression()!=null){List<String> pl = ctx.parameterList().singleExpression().stream().map(it->it.getText().trim()).collect(Collectors.toList());symbol.setParameterList(pl);}if(ctx.functionBody() != null){symbol.setFunctionBody(ctx.functionBody().getText());if(ctx.functionBody().returnStatement() != null){Object o = this.visitReturnStatement(ctx.functionBody().returnStatement());symbol.setValue(o);}}//            if(ctx.functionBody().)_sympoltable.put(functionName,symbol);
//            return null;}//return null;return super.visitFunctionDecl(ctx);}@Overridepublic Object visitReturnStatement(ReturnStatementContext ctx) {if(ctx.expressionStatement().singleExpression()!=null){return this.visitSingleExpression(ctx.expressionStatement().singleExpression());}return super.visitReturnStatement(ctx);}@Overridepublic Object visitFunctionCall(FunctionCallContext ctx) {String functionName = null;if(ctx.parameterList() != null){this.visitParameterList(ctx.parameterList());}if(ctx.sysfunction() != null){functionName = ctx.sysfunction().getText();
//            System.out.println(functionName);List<Object> all = ctx.parameterList().singleExpression().stream().map(it->{return this.visitSingleExpression(it);}).collect(Collectors.toList());return Funcall.exec(functionName,all);}if(ctx.identifier() != null){functionName = ctx.identifier().getText();}SymbolFunction currentSymbol = (SymbolFunction) _sympoltable.get(functionName);if(currentSymbol != null){
//            System.out.println("call function ==> "+currentSymbol.getName());StackFrane stackFrane = new StackFrane(currentSymbol,functionName);return currentSymbol.getValue();}return super.visitFunctionCall(ctx);}@Overridepublic Object visitSysfunction(SysfunctionContext ctx) {String functionName = ctx.getText();return super.visitSysfunction(ctx);}
}

Funcall.java

系统函数执行器

package com.dafei1288.jimlang.sys;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;public class Funcall {public static Set<String> SYS_FUNCTION_NAMES = new HashSet<>();static{SYS_FUNCTION_NAMES.add("PRINTLN");SYS_FUNCTION_NAMES.add("PRINT");}public static boolean isSysFunction(String functionName){boolean tag = false;if(SYS_FUNCTION_NAMES.contains(functionName.toUpperCase(Locale.ROOT))){tag = true;}return tag;}public static Object exec(String functionName, List<Object> params){Funcall f = new Funcall();Method method = Arrays.stream(f.getClass().getMethods()).filter(it->it.getName().equals(functionName)).findFirst().get();try {return  method.invoke(f,params.toArray());} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}}public void println(Object obj){System.out.println(obj);}public void print(Object obj){System.out.print(obj);}
}

符号表

构建符号表系统

Symbol.java

package com.dafei1288.jimlang.metadata;import org.antlr.v4.runtime.tree.ParseTree;public interface Symbol {String getName();void setName(String name);SymbolType getType();void setType(SymbolType type);ParseTree getParseTree();void setParseTree(ParseTree parseTree);String getTypeName() ;void setTypeName(String typeName) ;Object getValue() ;void setValue(Object value);Scope getScope();void setScope(Scope scope);}

AbstractSymbol.java

package com.dafei1288.jimlang.metadata;import org.antlr.v4.runtime.tree.ParseTree;public class AbstractSymbol implements Symbol {private String name ;private SymbolType type;private ParseTree parseTree;private String typeName;private Object value;private Scope scope;public String getName() {return name;}public void setName(String name) {this.name = name;}public SymbolType getType() {return type;}public void setType(SymbolType type) {this.type = type;}public ParseTree getParseTree() {return parseTree;}public void setParseTree(ParseTree parseTree) {this.parseTree = parseTree;}public String getTypeName() {return typeName;}public void setTypeName(String typeName) {this.typeName = typeName;}public Object getValue() {return value;}public void setValue(Object value) {this.value = value;}public Scope getScope() {return scope;}public void setScope(Scope scope) {this.scope = scope;}@Overridepublic String toString() {return "AbstractSymbol{" +"name='" + name + '\'' +", type=" + type +", parseTree=" + parseTree +", dataType='" + typeName + '\'' +", value=" + value +'}';}
}

SymbolFunction.java

package com.dafei1288.jimlang.metadata;import java.util.List;public class SymbolFunction extends AbstractSymbol {private List<String> parameterList;private String functionBody;public List<String> getParameterList() {return parameterList;}public void setParameterList(List<String> parameterList) {this.parameterList = parameterList;}public String getFunctionBody() {return functionBody;}public void setFunctionBody(String functionBody) {this.functionBody = functionBody;}
}

SymbolVar.java

package com.dafei1288.jimlang.metadata;public class SymbolVar extends AbstractSymbol {}

测试

Test01.java

import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.Test;
import wang.datahub.mylang.MLVistor;
import wang.datahub.mylang.parser.MyLangLexer;
import wang.datahub.mylang.parser.MyLangParser;import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;public class Test01 {@Testpublic void T2() throws IOException {String script = """var i = 11 ;function aa(i){return i;}print(aa(i))""";System.out.println(script);System.out.println("--------------------");CharStream stream= CharStreams.fromString(script);JimLangLexer lexer=new JimLangLexer(stream);JimLangParser parser = new JimLangParser(new CommonTokenStream(lexer));ParseTree parseTree = parser.prog();JimLangVistor mlvistor = new JimLangVistor();Object o = mlvistor.visit(parseTree);
//        System.out.println(o);}
}

测试结果:

AST

在这里插入图片描述

执行结果

在这里插入图片描述

好了,今天的分享就倒这里。

相关文章:

手把手开发一门程序语言JimLang (2)

根据爱因斯坦的相对论&#xff0c;物体的质量越大&#xff0c;时间过得越快&#xff0c;所以托更对于我的煎熬&#xff0c;远远比你们想象的还要痛苦…今天给大家来盘硬菜&#xff0c;也是前些时日预告过的JimLang的开发过程… Let’s go !!! 语法及解析 JimLang.g4 这里我们…...

DSF深度搜索时到底是如何回溯的(小tip)

这一段让我迷了两次&#xff0c;为什么回溯的时候&#xff0c;恢复了最后一位&#xff0c;往上递归一层之后&#xff0c;把最后一位填在它前一位&#xff0c;但是原本的前一位没有恢复&#xff0c;最后一位要怎么办&#xff1f;其实这还是递归没明白 也就是这一步是如何实现的 …...

Rust Web入门(八):打包发布

本教程笔记来自 杨旭老师的 rust web 全栈教程&#xff0c;链接如下&#xff1a; https://www.bilibili.com/video/BV1RP4y1G7KF?p1&vd_source8595fbbf160cc11a0cc07cadacf22951 学习 Rust Web 需要学习 rust 的前置知识可以学习杨旭老师的另一门教程 https://www.bili…...

synchronize优化偏向锁

偏向锁 轻量级锁在没有竞争时&#xff08;只有自己一个线程&#xff09;&#xff0c;仍然会尝试CAS替换mark word&#xff1b; 会造成一定的性能的损耗&#xff1b; JDK6之中引入了偏向锁进行优化&#xff0c;第一次使用时线程ID注入到Mark word中&#xff0c;之后重入不再进…...

算法习题之动态规划

动态规划习题1 打印n层汉诺塔从最左边移动到最右边的全部过程习题2 给你一个栈&#xff0c;请你逆序这个栈&#xff0c;不能申请额外的数据结构&#xff0c;只能使用递归函数。 如何实现?习题3 打印一个字符串的全部子序列&#xff0c;打印一个字符串的全部子序列&#xff0c;…...

顺序表【数据结构】

文章目录:star2:1. 顺序表概念:star2:2. 框架3. 基本功能3.1 头文件:star:3.2 初始化:star:3.3 扩容:star:3.4 打印:star:3.5 尾插:star:3.6 头插:star:3.7 尾删:star:3.8 头删:star:3.9 指定插入:star:3.10 指定删除:star:3.11 查找:star2:3.12 注意事项4. 顺序表的缺点&#…...

SNAP中根据入射角和干涉图使用波段计算器计算垂直形变--以门源地震为例

SNAP中根据入射角和相干图使用波段计算器计算垂直形变--以门源地震为例0 写在前面1 具体步骤1.1 准备数据1.2 在SNAP中打开波段运算Band Maths1.3 之前计算的水平位移displacement如下图数据的其他处理请参考博文在SNAP中用sentinel-1数据做InSAR测量&#xff0c;以门源地震为例…...

Ubuntu20.04中Docker安装与配置

一、安装 1、卸载可能存在的旧版本 sudo apt-get remove docker docker-engine docker-ce docker.io2、更新apt包索引 sudo apt-get update显示“正在读取软件包列表… 完成” 3、安装以下包以使apt可以通过HTTPS使用存储库(repository) sudo apt-get install -y apt-tran…...

pytorch权值初始化和损失函数

pytorch权值初始化和损失函数 权值初始化 梯度消失与爆炸 针对上面这个两个隐藏层的神经网络&#xff0c;我们求w2的梯度 可以发现&#xff0c;w2的梯度与H1&#xff08;上一层网络的输出&#xff09;有很大的关系&#xff0c;当h1趋近于0时&#xff0c;w2的梯度也趋近于0&am…...

maven将jar文件上传至本地仓库及私服

maven官方仓库有些依赖并不存在&#xff0c;现在项目都是maven直接获取jar&#xff0c;当maven获取不到时&#xff0c;需要我们把jar上传至maven仓库。已 ImpalaJDBC41.jar 文件为例&#xff0c;如&#xff1a;希望上传后&#xff0c;设置的依赖为&#xff1a;<dependency&g…...

前端学习第三阶段-第1、2章 JavaScript 基础语法

01第一章 JavaScript网页编程课前导学 1-1 JavaScript网页编程课前导学 02第二章 JavaScript 基础语法 2-1 计算机基础和Javascript介绍 01-计算机基础导读 02-编程语言 03-计算机基础 04-JavaScript初识导读 05-初始JavaScript 06-浏览器执行JS过程 07-JS三部分组成 08-JS三种…...

hibernate学习(二)

hibernate学习&#xff08;二&#xff09; 一、hibernate常见配置&#xff1a; 1.XML提示问题配置&#xff1a; 二、hibernate映射的配置&#xff1a; &#xff08;1&#xff09;class标签的配置&#xff1a; 标签用来建立类与表之间的映射关系属性&#xff1a; 1.name&…...

平安银行LAMBDA实验室负责人崔孝林:提早拿到下一个计算时代入场券

量子前哨重磅推出独家专题《“量子”百人科学家》&#xff0c;我们将遍访全球探索赋能“量子”场景应用的百位优秀科学专家&#xff0c;从商业视角了解当下各行业领域的“量子”最新研究成果&#xff0c;多角度、多维度、多层面讲述该领域的探索历程&#xff0c;为读者解析商业…...

linux下进不去adb

linux 进不去adb cat /sys/kernel/debug/usb/devices 查看是否有adb口 首先查看adb是否被识别成串口 option 如果被识别成串口 方法1&#xff1a; https://patchwork.kernel.org/project/linux-usb/patch/20180723140220.7166-1-romain.izard.progmail.com/ diff --git a/dri…...

【SPSS】多因素方差分析详细操作教程(附案例实战)

🤵‍♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 目录 方差分析概述 多因素方差分析原理...

我的投稿之旅

一、铁道科学与工程学报选择这个期刊的原因是&#xff1a;感觉影响因子较低&#xff0c;而且实验室有师兄师姐中过这个期刊&#xff0c;所以抱着试一试的心态投了。投稿之前需要去官网注册账号由于方向不一致&#xff0c;被退稿了“您的稿件内容不属于本刊刊载范畴&#xff0c;…...

51单片机DS18B20的使用

文章目录前言一、DS18B20介绍二、单总线协议三、DS18B20引脚说明四、DS18B20程序编写1.DS18B20复位函数2.DS18B20存在检测3.DS18B20读取一个bit和一个byte函数4.DS18B20写一个字节函数5.开始温度转换函数6.DS18B20初始化函数7.DS18B20读取温度函数五、代码测试总结前言 本篇文…...

Vue组件原理知识(1)

Vue 组件知识整理&#xff08;1&#xff09;文章目录Vue 组件知识整理&#xff08;1&#xff09;一、组件介绍1.1 传统方式与组件方式编写应用对比二、组件使用2.1 非单文件组件的使用**1. 组件的创建****2. 组件的注册****3. 组件的使用****4. Vue中使用组件的三大步骤总结***…...

Linux:IO库函数

目录标准库IO函数一、fopen二、fwrite三、fread四、fseek五、fclose在编写程序时&#xff0c;离不开IO操作&#xff0c;最常见的IO操作就是用printf函数进行打印&#xff0c;本文主要介绍的是封装后的IO库函数。 标准库IO函数 常使用的IO库函数如下&#xff1a; 函数作用fop…...

Go爬虫学习笔记

N002.02 Go分布式爬虫实战 开篇 学习三阶段 入门&#xff0c;照猫画虎底层&#xff0c;了解方方面面&#xff0c;深入阅读源码和书籍借助开源组件来进行复杂设计&#xff0c;窥探各个组件赋能业务 分布式系统&#xff1a; 扩展性一致性可用性高并发微服务 爬虫&#xff1…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...