Skip to content

Commit eeed0cf

Browse files
author
wangjingf
committed
增加pratt方式解析expression表达式
1 parent bdd6dc2 commit eeed0cf

File tree

10 files changed

+262
-23
lines changed

10 files changed

+262
-23
lines changed

src/main/java/compiler/expr/ExprParser.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
* statement -> assignOp | var declaration | expr |empty | compoundStatement| procedureCall
1919
* assignOp -> variable = expr
2020
* variable -> id;
21-
*
22-
* produreCall -> id(expr(,expr)*|empty)
21+
* ifStatement
22+
* procedureCall -> id(expr(,expr)*|empty)
2323
* var declation -> var (paramList:variable)*; | procedureDeclaration
2424
* procedureDeclaration -> produce id(produceParamList);vardeclaration begin statement end;
2525
* produceParams -> produceParam(,procureParam)*|empty
@@ -108,10 +108,7 @@ Procedure procedureDeclaration(){
108108
}
109109
eatToken(TokenType.RIGHT_PARA);
110110
eatToken(TokenType.SEMI);
111-
List<VarDeclaration> vars = new LinkedList<>();
112-
if(currentToken.getTokenType() == TokenType.VAR){
113-
vars.addAll(varDeclarations());
114-
}
111+
List<ASTNode> vars = declarations();;
115112
CompoundNode body = compoundStatement();
116113
eatToken(TokenType.SEMI);
117114
Procedure procedure = new Procedure(varDeclarations, identifier, body);

src/main/java/compiler/expr/Interpreter.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,22 @@ public Object visitProgram(Program program){
8080
callStack.pop();
8181
return ret;
8282
}
83+
void defineVarSymbol(VarDeclaration declaration){
84+
BuiltinTypeSymbol typeSymbol = (BuiltinTypeSymbol) requireSymbol((String) declaration.getType().getValue());
85+
currentSymbolTable.define(new VarSymbol(declaration.getId().getId(),typeSymbol ));
86+
}
8387
public Object visitProcedureCall(ProcedureCall procedureCall){
8488
Symbol symbol = currentSymbolTable.lookup(procedureCall.getProcedureName());
8589
if(!(symbol instanceof ProcedureSymbol)){
8690
throw error("expected produceSymbol but is "+symbol);
8791
}
88-
for (VarDeclaration declaration : ((ProcedureSymbol) symbol).getAllVars()) {
89-
BuiltinTypeSymbol typeSymbol = (BuiltinTypeSymbol) requireSymbol((String) declaration.getType().getValue());
90-
currentSymbolTable.define(new VarSymbol(declaration.getId().getId(),typeSymbol ));
92+
for (ASTNode declaration : ((ProcedureSymbol) symbol).getAllVars()) {
93+
if(declaration instanceof VarDeclaration){//定义内部变量
94+
defineVarSymbol((VarDeclaration) declaration);
95+
}else if(declaration instanceof Procedure){
96+
defineProcedureSymbol((Procedure) declaration);
97+
}
98+
9199
}
92100
int size = callStack.size();
93101
ActivatedRecord activatedRecord = new ActivatedRecord(size+1,procedureCall.getProcedureName(),TokenType.PROCEDURE);
@@ -106,16 +114,19 @@ public Object visitProcedureCall(ProcedureCall procedureCall){
106114
callStack.pop();
107115
return null;
108116
}
109-
public Object visitProcedure(Procedure procedure){
110-
111-
SymbolTable scopedSymbolTable = new SymbolTable();
112-
scopedSymbolTable.setParent(currentSymbolTable);
113-
currentSymbolTable = scopedSymbolTable;
117+
void defineProcedureSymbol(Procedure procedure){
114118
ProcedureSymbol procedureSymbol = new ProcedureSymbol(procedure.getId().getId());
115119
procedureSymbol.setBody(procedure.getBody());
116120
procedureSymbol.setParams(procedure.getParams());
117121
procedureSymbol.setVars(procedure.getVars());
118122
currentSymbolTable.define(procedureSymbol);
123+
}
124+
public Object visitProcedure(Procedure procedure){
125+
126+
SymbolTable scopedSymbolTable = new SymbolTable();
127+
scopedSymbolTable.setParent(currentSymbolTable);
128+
currentSymbolTable = scopedSymbolTable;
129+
defineProcedureSymbol(procedure);
119130
return null;
120131
}
121132
public Object visitRealNode(RealNode num){

src/main/java/compiler/expr/ast/Procedure.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55

66
public class Procedure extends ASTNode{
77
List<VarDeclaration> params = new LinkedList<>();
8-
List<VarDeclaration> vars = new LinkedList<>();
8+
/**
9+
* 包含声明的procedure及变量信息
10+
*/
11+
List<ASTNode> vars = new LinkedList<>();
912
Identifier id;
1013
CompoundNode body;
1114

@@ -39,11 +42,11 @@ public void setBody(CompoundNode body) {
3942
this.body = body;
4043
}
4144

42-
public List<VarDeclaration> getVars() {
45+
public List<ASTNode> getVars() {
4346
return vars;
4447
}
4548

46-
public void setVars(List<VarDeclaration> vars) {
49+
public void setVars(List<ASTNode> vars) {
4750
this.vars = vars;
4851
}
4952
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package compiler.expr.ast;
2+
3+
import compiler.expr.Token;
4+
5+
public class UnaryNode extends ASTNode {
6+
ASTNode astNode;
7+
public UnaryNode(ASTNode node){
8+
this.astNode = node;
9+
}
10+
11+
@Override
12+
public String toString() {
13+
return "-("+astNode.toString()+")";
14+
}
15+
}

src/main/java/compiler/expr/stack/CallStack.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class CallStack {
1212
List<ActivatedRecord> list = new ArrayList<>();
1313
public void pop(){
1414
ActivatedRecord activatedRecord = list.get(list.size() - 1);
15-
logger.info("currentVar:"+activatedRecord.getMembers().toString());
15+
logger.info("nestLever is "+ list.size()+" currentVar:"+activatedRecord.getMembers().toString());
1616
list.remove(list.size()-1);
1717
}
1818
public ActivatedRecord peek(){

src/main/java/compiler/expr/symbol/ProcedureSymbol.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class ProcedureSymbol extends Symbol {
1313
/**
1414
* 程序内部声明的变量
1515
*/
16-
List<VarDeclaration> vars = new LinkedList<>();
16+
List<ASTNode> vars = new LinkedList<>();
1717
public ProcedureSymbol(String name) {
1818
super(name);
1919
}
@@ -34,15 +34,15 @@ public void setParams(List<VarDeclaration> params) {
3434
this.params = params;
3535
}
3636

37-
public List<VarDeclaration> getVars() {
37+
public List<ASTNode> getVars() {
3838
return vars;
3939
}
4040

41-
public void setVars(List<VarDeclaration> vars) {
41+
public void setVars(List<ASTNode> vars) {
4242
this.vars = vars;
4343
}
44-
public List<VarDeclaration> getAllVars(){
45-
List<VarDeclaration> ret = new LinkedList<>();
44+
public List<ASTNode> getAllVars(){
45+
List<ASTNode> ret = new LinkedList<>();
4646
ret.addAll(vars);
4747
ret.addAll(params);
4848
return ret;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package compiler.infix;
2+
3+
import java.util.concurrent.Callable;
4+
import java.util.function.Function;
5+
6+
public class ParseRule {
7+
Function prefix;
8+
Function infix;
9+
Precedence precedence;
10+
11+
public ParseRule(Function prefix, Function infix, Precedence precedence) {
12+
this.prefix = prefix;
13+
this.infix = infix;
14+
this.precedence = precedence;
15+
}
16+
17+
public Function getPrefix() {
18+
return prefix;
19+
}
20+
21+
public void setPrefix(Function prefix) {
22+
this.prefix = prefix;
23+
}
24+
25+
public Function getInfix() {
26+
return infix;
27+
}
28+
29+
public void setInfix(Function infix) {
30+
this.infix = infix;
31+
}
32+
33+
public Precedence getPrecedence() {
34+
return precedence;
35+
}
36+
37+
public void setPrecedence(Precedence precedence) {
38+
this.precedence = precedence;
39+
}
40+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package compiler.infix;
2+
3+
public enum Precedence {
4+
NONE,ASSIGNMENT,OR,AND,EQ,
5+
TERM,//+-
6+
FACTOR,//*/
7+
UNARY,//!-
8+
CALL,//.[]运算
9+
PRIMARY
10+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package compiler.infix;
2+
3+
import compiler.expr.*;
4+
import compiler.expr.ast.ASTNode;
5+
import compiler.expr.ast.BinOp;
6+
import compiler.expr.ast.IntNode;
7+
import compiler.expr.ast.UnaryNode;
8+
import io.study.exception.StdException;
9+
10+
import java.util.LinkedHashMap;
11+
import java.util.Map;
12+
import java.util.concurrent.Callable;
13+
import java.util.function.Function;
14+
15+
/**
16+
* pratt parser
17+
* http://www.craftinginterpreters.com/compiling-expressions.html#parsing-infix-expressions
18+
*/
19+
public class Program {
20+
Map<TokenType,ParseRule> parseRuleMap = new LinkedHashMap<>();
21+
Lexer lexer = null;
22+
Token currentToken;
23+
Token prevToken;
24+
25+
public void advance(){
26+
prevToken = currentToken;
27+
currentToken = lexer.getNextToken();
28+
}
29+
public void consume(TokenType tokenType){
30+
if(tokenType != currentToken.getTokenType()){
31+
throw new SyntaxException("invalid token:"+currentToken.getTokenType()+",expect is :"+tokenType);
32+
}
33+
advance();
34+
}
35+
public Program(Lexer lexer){
36+
this.lexer = lexer;
37+
advance();
38+
}
39+
40+
public Object parsePrecedence(Precedence precedence){
41+
advance();
42+
Function prefixRule = parseRuleMap.get(prevToken.getTokenType()).getPrefix();
43+
if(prefixRule == null){
44+
throw new StdException("expect expression");
45+
}
46+
Object left = prefixRule.apply(null);
47+
while(precedence.ordinal() < parseRuleMap.get(currentToken.getTokenType()).precedence.ordinal()){
48+
advance();
49+
Function infix = parseRuleMap.get(prevToken.getTokenType()).infix;
50+
left = infix.apply(left);
51+
}
52+
return left;
53+
}
54+
public Object grouping(Object param){
55+
expression();
56+
consume(TokenType.RIGHT_PARA);
57+
return null;
58+
}
59+
public Object unary(Object param){
60+
return new UnaryNode((ASTNode) parsePrecedence(Precedence.UNARY));
61+
}
62+
public Object expression(){
63+
return parsePrecedence(Precedence.ASSIGNMENT);
64+
}
65+
66+
public Object binary(Object left){
67+
TokenType prevTokenType = prevToken.getTokenType();
68+
ParseRule parseRule = parseRuleMap.get(prevTokenType);
69+
Object right = parsePrecedence(Precedence.values()[parseRule.precedence.ordinal()+1]);
70+
return new BinOp((ASTNode) left,new Token(prevTokenType), (ASTNode) right);
71+
}
72+
public Object number(){
73+
return new IntNode(new Token(TokenType.INTEGER,prevToken.getValue()));
74+
}
75+
public Object number(Object object){
76+
return number();
77+
}
78+
public void init(){
79+
parseRuleMap.put(TokenType.LEFT_PARA,new ParseRule(this::grouping,null,Precedence.NONE));
80+
parseRuleMap.put(TokenType.PLUS,new ParseRule(null,this::binary,Precedence.TERM));
81+
parseRuleMap.put(TokenType.SUB,new ParseRule(this::unary,this::binary,Precedence.TERM));
82+
parseRuleMap.put(TokenType.INTEGER,new ParseRule(this::number,null,Precedence.NONE));
83+
parseRuleMap.put(TokenType.EOF,new ParseRule(null,null,Precedence.NONE));
84+
}
85+
public static void main(String[] args){
86+
Program program = new Program(new Lexer("-1+2+3"));
87+
program.init();
88+
Object ret = program.expression();
89+
System.out.println(ret);
90+
}
91+
92+
93+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
function getRule(type){
2+
3+
}
4+
5+
6+
var Factor = [
7+
"none","assignment",
8+
"or",//
9+
"and",//and
10+
"eq",//==,!=
11+
"term",//+-
12+
"factor",//*/
13+
"unary",//!-
14+
"call",//.运算
15+
"primary"
16+
]
17+
var Procedence = [];
18+
Factor.forEach((item,index)=>{
19+
Procedence[item] = index
20+
});
21+
var prefix,infix,procedure;
22+
var ParseRules = [
23+
[grouping,null,Procedence.none],//left
24+
[grouping,null,Procedence.none],// (
25+
[unary,binary,Procedence.term],//-
26+
[null,binary,Procedence.term],//+
27+
[number,null,procedence.none]
28+
]
29+
function number(){
30+
return number;
31+
}
32+
function grouping(){
33+
expression();
34+
consume(")")
35+
}
36+
function unary(){
37+
var token = parser.previous.type;
38+
expression();
39+
switch (operatorType) {
40+
case TOKEN_MINUS: emitByte(OP_NEGATE); break;
41+
default:
42+
return; // Unreachable.
43+
}
44+
}
45+
function expression(){
46+
parseProcedence(Procedence.assignment);
47+
}
48+
function binary(){
49+
var operatorType = parser.previous.type;
50+
var rule = getRule(operatorType);
51+
parseProcedence(rule.procedence+1);
52+
switch (operatorType){
53+
54+
}
55+
}
56+
57+
58+
function parseProcedence(procedence){
59+
var prefixRule = getRule(parser.previous.type).prefix;
60+
if(prefixRule == null){
61+
throw new Error("expect expression.")
62+
return;
63+
}
64+
prefixRule();
65+
while(procedure < getRule(parser.current.type).procedure){
66+
advance();
67+
var infixRule = getRule(parser.previous.type).infix
68+
infixRule();
69+
}
70+
}

0 commit comments

Comments
 (0)