-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.js
124 lines (117 loc) · 5.09 KB
/
parser.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const fs = require("fs");
const ohm = require("ohm-js");
const parserContents = fs.readFileSync("JCaml.ohm");
const JCamlGrammar = ohm.grammar(parserContents);
const Type = require("./ast/type");
const Program = require("./ast/program");
const Block = require("./ast/block");
const StatementIfElse = require("./ast/statementIfElse");
const Decl = require("./ast/decl");
const Print = require("./ast/print");
const Return = require("./ast/return");
const Addop = require("./ast/addop");
const Relop = require("./ast/relop");
const Mullop = require("./ast/mullop");
const Expop = require("./ast/expop");
const Binop = require("./ast/binop");
const FuncDec = require("./ast/funcDec");
const FuncCall = require("./ast/funcCall");
// const Args = require("./ast/args");
const Arg = require("./ast/arg");
// const Params = require("./ast/params");
const Param = require("./ast/param");
const Body = require("./ast/body");
const ExpBinary = require("./ast/exp_binary");
const ExpTernary = require("./ast/exp_ternary");
const BinExp = require("./ast/binExp");
const MatchExp = require("./ast/matchExp");
// const Matches = require("./ast/matches");
const Match = require("./ast/match");
const AddExp = require("./ast/addExp");
const MullExp = require("./ast/mullExp");
const ParenExp = require("./ast/parenExp");
const Tuplit = require("./ast/tuplit");
const Numlit = require("./ast/numLit");
const Charlit = require("./ast/charLit");
const Stringlit = require("./ast/stringLit");
const ExpoExp = require("./ast/expoExp");
const PrefixExp = require("./ast/prefix_Exp");
const List = require("./ast/list");
const Stmt = require("./ast/stmt");
/* eslint-disable no-unused-vars */
const semantics = JCamlGrammar.createSemantics().addOperation("tree", {
Program(block) { return new Program(block.tree()); },
Block(stmt) { return new Block(stmt.tree()); },
Stmt_if(_1, exp, block, _2, elseIfExprs, elseIfBlocks, _3, finalBlock) {
return new StatementIfElse(exp.tree(), block.tree(), elseIfExprs.tree(),
elseIfBlocks.tree(), finalBlock.tree());
},
Decl_decl(_1, type, id, _2, exp) { return new Decl(type.tree(), id.sourceString, exp.tree()); },
Print_print(_1, _2, binexp, _3) { return new Print(binexp.tree()); },
Return(_1, arg) { return new Return(arg.tree()); },
addop(op) { return new Addop(this.sourceString); },
relop(op) { return new Relop(this.sourceString); },
mullop(op) { return new Mullop(this.sourceString); },
expop(op) { return new Expop(this.sourceString); },
binop(op) { return new Binop(this.sourceString); },
FuncDec(_1, id, _2, params, _3, type, body) {
return new FuncDec(id.sourceString, params.tree(), type.tree(), body.tree());
},
FuncCall(id, _1, args, _2) {
return new FuncCall(id.sourceString, args.tree());
},
// Args(arg) { return new Args(arg.tree()); },
NonemptyListOf(first, _, rest) {
return [first.tree()].concat(rest.tree());
},
EmptyListOf() { return []; },
Arg(id) { return new Arg(id.sourceString); },
// Params(params) {
// return new Params(params.sourceString);
// },
Param(id) { return new Param(id.sourceString); },
Type(type) { return new Type(type.sourceString); },
Body(_1, block, _2) { return new Body(block.tree()); },
Exp_binary(exp, op, matchexp) { return new ExpBinary(op.tree(), exp.tree(), matchexp.tree()); },
Exp_ternary(matchexp, _1, matchexp2, _2, matchexp3) {
return new ExpTernary(matchexp.tree(), matchexp2.tree(), matchexp3.tree());
},
BinExp_binary(binexp, op, addexp) {
return new BinExp(op.tree(), binexp.tree(), addexp.tree());
},
MatchExp_matchexp(_1, id, _2, matches) {
return new MatchExp(id.sourceString, matches.tree());
},
AddExp_binary(addexp, op, mullexp) {
return new AddExp(op.tree(), addexp.tree(), mullexp.tree());
},
MullExp_binary(mullexp, op, prefixexp) {
return new MullExp(op.tree(), mullexp.tree(), prefixexp.tree());
},
PrefixExp_binary(op, expoexp) { return new PrefixExp(op.tree(), expoexp.tree()); },
ExpoExp_binary(parenexp, op, expoexp) {
return new ExpoExp(op.tree(), parenexp.tree(), expoexp.tree());
},
ParenExp_parens(_1, addexp, _2) { return new ParenExp(addexp.tree()); },
Match_match(_1, exp1, _2, exp2) {
return new Match(exp1.tree(), exp2.tree());
},
Tuplit(_1, exp1, _2, exp2, _3) { return new Tuplit(exp1.tree(), exp2.tree()); },
List_list(_1, first, _2, rest, _3) {
return new List([first.tree()].concat(rest.tree()));
},
List_empty(_1, _2) { return new List([]); },
numlit(value) { return new Numlit(this.sourceString); },
charlit(_1, value, _2) { return new Charlit(this.sourceString); },
stringlit(_1, value, _2) { return new Stringlit(this.sourceString); },
});
/* eslint-enable no-unused-vars */
function parse(text) {
const match = JCamlGrammar.match(text);
if (match.succeeded()) {
return semantics(match).tree();
}
throw new Error(match.message);
}
module.exports = parse;
module.exports = { parse, Program, Block, Stmt, Return, Arg, Param, Stringlit, FuncCall, FuncDec };