我也能写编程语言
Posted 麒思妙想
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我也能写编程语言相关的知识,希望对你有一定的参考价值。
在写函数的实现时候,一直很迷茫,感觉不够优雅,直到听了南大的《操作系统》,程序就是状态机,方法调研就是引用计数++,函数返回就是弹栈,才豁然开朗,也让我鉴定了开一个系列坑,这里我打算实现一门开发语言。
今天我们先来实现函数一个简单的函数调用
MyLang.g4
这里我们还是借用ANTLR来做解析器,构建基础的函数语法
grammar MyLang;
prog: statementList? EOF;
statementList : ( variableDecl | functionDecl | expressionStatement )* ;
variableDecl : VAR identifier typeAnnotation? ( '=' singleExpression)? ';';
typeAnnotation : ':' typeName;
functionDecl: FUNCTION identifier '(' parameterList ')' functionBody;
functionBody: '' statementList? '';
functionCall: identifier '(' parameterList? ')';
expressionStatement: singleExpression ';';
singleExpression: primary (binOP primary)* ;
primary: ID | NUMBER_LITERAL | functionCall | '(' singleExpression ')' ;
binOP : '+'
| '-'
| '*'
| '/'
| '='
| '<='
| '>='
;
parameterList: singleExpression(',' singleExpression)*;
identifier: ID;
typeName : 'String'
| 'Number'
| 'Boolean'
;
VAR: 'var';
FUNCTION: 'function';
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 ;
MLVistor.java
构建vistor
package wang.datahub.mylang;
import wang.datahub.mylang.parser.MyLangBaseVisitor;
import wang.datahub.mylang.parser.MyLangParser;
import java.util.Hashtable;
public class MLVistor extends MyLangBaseVisitor
// Hashtable<String, MyLangParser.FunctionDeclContext> sympoltable = new Hashtable<>();
Hashtable<String,Symbol> _sympoltable = new Hashtable<>();
@Override
public Object visitFunctionDecl(MyLangParser.FunctionDeclContext ctx)
String functionName = ctx.identifier().getText();
if(_sympoltable.get(functionName) == null)
System.out.println("define function ==> "+functionName);
// sympoltable.put(ctx.identifier().getText(),ctx);
Symbol symbol = new Symbol();
symbol.setName(functionName);
symbol.setParseTree(ctx);
symbol.setType(Symbol.SymbolType.FUNCTION);
_sympoltable.put(functionName,symbol);
return null;
//return null;
return super.visitFunctionDecl(ctx);
@Override
public Object visitFunctionCall(MyLangParser.FunctionCallContext ctx)
String functionName = ctx.identifier().getText();
if("print".equals(functionName))
String parStr = ctx.parameterList().getText();
if(parStr.startsWith("\\""))
parStr = parStr.substring(1,parStr.length()-1);
System.out.println(parStr);
return null;
else
System.out.println("run function ==>"+functionName);
MyLangParser.FunctionDeclContext fdc = (MyLangParser.FunctionDeclContext) _sympoltable.get(functionName).getParseTree();
//sympoltable.get(functionName);
if(fdc==null)
throw new RuntimeException("undefine function ...." + functionName);
super.visitFunctionDecl(fdc);
return super.visitFunctionCall(ctx);
Symbol.java
做一个简单的栈帧实现
package wang.datahub.mylang;
import org.antlr.v4.runtime.tree.ParseTree;
public class Symbol
public static enum SymbolType
FUNCTION,VAR,
private String name ;
private SymbolType type;
private ParseTree parseTree;
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;
@Override
public String toString()
return "Symbol" +
"name='" + name + '\\'' +
", type=" + type +
", parseTree=" + parseTree +
'';
测试
Test01.mylang
function foo()
print("in foo")
bar()
function bar()
print("in bar")
foo()
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
@Test
public void T1() throws IOException
List<String> lines = Files.readAllLines(Paths.get("src/test/java/Test01.mylang"));
String expr = lines.stream().collect(Collectors.joining("\\n"));
System.out.println(expr);
System.out.println("--------------------");
CharStream stream= CharStreams.fromString(expr);
MyLangLexer lexer=new MyLangLexer(stream);
MyLangParser parser = new MyLangParser(new CommonTokenStream(lexer));
ParseTree parseTree = parser.prog();
MLVistor mlvistor = new MLVistor();
mlvistor.visit(parseTree);
测试结果
好了,今天的分享就倒这里。
以上是关于我也能写编程语言的主要内容,如果未能解决你的问题,请参考以下文章