手把手开发一门程序语言JimLang
Posted 麒思妙想
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手开发一门程序语言JimLang相关的知识,希望对你有一定的参考价值。
根据爱因斯坦的相对论,物体的质量越大,时间过得越快,所以托更对于我的煎熬,远远比你们想象的还要痛苦…今天给大家来盘硬菜,也是前些时日预告过的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<>();
@Override
public 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);
@Override
public 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);
@Override
public 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);
@Override
public Object visitReturnStatement(ReturnStatementContext ctx)
if(ctx.expressionStatement().singleExpression()!=null)
return this.visitSingleExpression(ctx.expressionStatement().singleExpression());
return super.visitReturnStatement(ctx);
@Override
public 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);
@Override
public 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肝了4.5万字,手把手带你玩转JavaScript(建议收藏)
肝了4.5万字,手把手带你玩转JavaScript(建议收藏)
Java开发四年的程序员想再学习一门语言,该选着C还是Python呢?