当前位置: 首页 > 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

在这里插入图片描述

执行结果

在这里插入图片描述

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

http://www.lryc.cn/news/35747.html

相关文章:

  • DSF深度搜索时到底是如何回溯的(小tip)
  • Rust Web入门(八):打包发布
  • synchronize优化偏向锁
  • 算法习题之动态规划
  • 顺序表【数据结构】
  • SNAP中根据入射角和干涉图使用波段计算器计算垂直形变--以门源地震为例
  • Ubuntu20.04中Docker安装与配置
  • pytorch权值初始化和损失函数
  • maven将jar文件上传至本地仓库及私服
  • 前端学习第三阶段-第1、2章 JavaScript 基础语法
  • hibernate学习(二)
  • 平安银行LAMBDA实验室负责人崔孝林:提早拿到下一个计算时代入场券
  • linux下进不去adb
  • 【SPSS】多因素方差分析详细操作教程(附案例实战)
  • 我的投稿之旅
  • 51单片机DS18B20的使用
  • Vue组件原理知识(1)
  • Linux:IO库函数
  • Go爬虫学习笔记
  • 数据结构课程设计:高铁信息管理系统(C++实现)
  • Python 模块之 datetime
  • linux安装编译ffmpeg
  • 嵌入式Linux驱动开发(二)LED驱动
  • C++学习
  • JavaEE简单示例——依赖注入
  • 大数据框架之Hive: 第7章 综合案例练习(初级)
  • kafka:linux 安装 kafka集群
  • springboot实现Hessian协议的RPC服务
  • 2-6 SpringCloud快速开发入门: Eureka 服务注册中心发现与消费服务
  • Java-Web之s2-001与CommonsCollections