aboutsummaryrefslogtreecommitdiff
path: root/examples/typedlua/tlparser.lua
diff options
context:
space:
mode:
Diffstat (limited to 'examples/typedlua/tlparser.lua')
-rw-r--r--examples/typedlua/tlparser.lua245
1 files changed, 245 insertions, 0 deletions
diff --git a/examples/typedlua/tlparser.lua b/examples/typedlua/tlparser.lua
new file mode 100644
index 0000000..a301fa6
--- /dev/null
+++ b/examples/typedlua/tlparser.lua
@@ -0,0 +1,245 @@
1local tlparser = {}
2
3local lpeg = require "lpeglabel"
4lpeg.locale(lpeg)
5
6local tllexer = require "tllexer"
7local tlerror = require "tlerror"
8
9local function chainl1 (pat, sep, label)
10 return pat * (sep * tllexer.try(pat, label))^0
11end
12
13local G = lpeg.P { "TypedLua";
14 TypedLua = tllexer.Shebang^-1 * tllexer.Skip * lpeg.V("Chunk") * tllexer.try(-1, "Stat");
15 -- type language
16 Type = lpeg.V("NilableType");
17 NilableType = lpeg.V("UnionType") * tllexer.symb("?")^-1;
18 UnionType = lpeg.V("PrimaryType") * (tllexer.symb("|") * tllexer.try(lpeg.V("PrimaryType"), "UnionType"))^0;
19 PrimaryType = lpeg.V("LiteralType") +
20 lpeg.V("BaseType") +
21 lpeg.V("NilType") +
22 lpeg.V("ValueType") +
23 lpeg.V("AnyType") +
24 lpeg.V("SelfType") +
25 lpeg.V("FunctionType") +
26 lpeg.V("TableType") +
27 lpeg.V("VariableType");
28 LiteralType = tllexer.token("false", "false") +
29 tllexer.token("true", "true") +
30 tllexer.token(tllexer.Number, "Number") +
31 tllexer.token(tllexer.String, "String");
32 BaseType = tllexer.token("boolean", "boolean") +
33 tllexer.token("number", "number") +
34 tllexer.token("string", "string") +
35 tllexer.token("integer", "integer");
36 NilType = tllexer.token("nil", "nil");
37 ValueType = tllexer.token("value", "value");
38 AnyType = tllexer.token("any", "any");
39 SelfType = tllexer.token("self", "self");
40 FunctionType = lpeg.V("InputType") * tllexer.symb("->") * tllexer.try(lpeg.V("NilableTuple"), "FunctionType");
41 MethodType = lpeg.V("InputType") * tllexer.symb("=>") * tllexer.try(lpeg.V("NilableTuple"), "MethodType");
42 InputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.try(tllexer.symb(")"), "MissingCP");
43 NilableTuple = lpeg.V("UnionlistType") * tllexer.symb("?")^-1;
44 UnionlistType = lpeg.V("OutputType") * (tllexer.symb("|") * tllexer.try(lpeg.V("OutputType"), "UnionType"))^0;
45 OutputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.try(tllexer.symb(")"), "MissingCP");
46 TupleType = lpeg.V("Type") * (tllexer.symb(",") * tllexer.try(lpeg.V("Type"), "TupleType"))^0 * tllexer.symb("*")^-1;
47 TableType = tllexer.symb("{") * lpeg.V("TableTypeBody")^-1 * tllexer.try(tllexer.symb("}"), "MissingCC");
48 TableTypeBody = lpeg.V("RecordType") +
49 lpeg.V("HashType") +
50 lpeg.V("ArrayType");
51 RecordType = lpeg.V("RecordField") * (tllexer.symb(",") * lpeg.V("RecordField"))^0 *
52 (tllexer.symb(",") * (lpeg.V("HashType") + lpeg.V("ArrayType")))^-1;
53 RecordField = tllexer.kw("const")^-1 *
54 lpeg.V("LiteralType") * tllexer.symb(":") * tllexer.try(lpeg.V("Type"), "Type");
55 HashType = lpeg.V("KeyType") * tllexer.symb(":") * tllexer.try(lpeg.V("FieldType"), "Type");
56 ArrayType = lpeg.V("FieldType");
57 KeyType = lpeg.V("BaseType") + lpeg.V("ValueType") + lpeg.V("AnyType");
58 FieldType = lpeg.V("Type");
59 VariableType = tllexer.token(tllexer.Name, "Name");
60 RetType = lpeg.V("NilableTuple") +
61 lpeg.V("Type");
62 Id = tllexer.token(tllexer.Name, "Name");
63 TypeDecId = (tllexer.kw("const") * lpeg.V("Id")) +
64 lpeg.V("Id");
65 IdList = lpeg.V("TypeDecId") * (tllexer.symb(",") * tllexer.try(lpeg.V("TypeDecId"), "TupleType"))^0;
66 IdDec = lpeg.V("IdList") * tllexer.symb(":") * tllexer.try((lpeg.V("Type") + lpeg.V("MethodType")), "Type");
67 IdDecList = (lpeg.V("IdDec")^1)^-1;
68 TypeDec = tllexer.token(tllexer.Name, "Name") * lpeg.V("IdDecList") * tllexer.try(tllexer.kw("end"), "TypeDecEnd");
69 Interface = tllexer.kw("interface") * lpeg.V("TypeDec") +
70 tllexer.kw("typealias") *
71 tllexer.try(tllexer.token(tllexer.Name, "Name"), "TypeAliasName") *
72 tllexer.try(tllexer.symb("="), "MissingEqTypeAlias") * lpeg.V("Type");
73 -- parser
74 Chunk = lpeg.V("Block");
75 StatList = (tllexer.symb(";") + lpeg.V("Stat"))^0;
76 Var = lpeg.V("Id");
77 TypedId = tllexer.token(tllexer.Name, "Name") * (tllexer.symb(":") * tllexer.try(lpeg.V("Type"), "Type"))^-1;
78 FunctionDef = tllexer.kw("function") * lpeg.V("FuncBody");
79 FieldSep = tllexer.symb(",") + tllexer.symb(";");
80 Field = ((tllexer.symb("[") * lpeg.V("Expr") * tllexer.try(tllexer.symb("]"), "MissingCB")) +
81 (tllexer.token(tllexer.Name, "Name"))) *
82 tllexer.symb("=") * lpeg.V("Expr") +
83 lpeg.V("Expr");
84 TField = (tllexer.kw("const") * lpeg.V("Field")) +
85 lpeg.V("Field");
86 FieldList = (lpeg.V("TField") * (lpeg.V("FieldSep") * lpeg.V("TField"))^0 *
87 lpeg.V("FieldSep")^-1)^-1;
88 Constructor = tllexer.symb("{") * lpeg.V("FieldList") * tllexer.try(tllexer.symb("}"), "MissingCC");
89 NameList = lpeg.V("TypedId") * (tllexer.symb(",") * lpeg.V("TypedId"))^0;
90 ExpList = lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0;
91 FuncArgs = tllexer.symb("(") *
92 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 *
93 tllexer.try(tllexer.symb(")"), "MissingCP") +
94 lpeg.V("Constructor") +
95 tllexer.token(tllexer.String, "String");
96 OrOp = tllexer.kw("or");
97 AndOp = tllexer.kw("and");
98 RelOp = tllexer.symb("~=") +
99 tllexer.symb("==") +
100 tllexer.symb("<=") +
101 tllexer.symb(">=") +
102 tllexer.symb("<") +
103 tllexer.symb(">");
104 BOrOp = tllexer.symb("|");
105 BXorOp = tllexer.symb("~") * -lpeg.P("=");
106 BAndOp = tllexer.symb("&");
107 ShiftOp = tllexer.symb("<<") +
108 tllexer.symb(">>");
109 ConOp = tllexer.symb("..");
110 AddOp = tllexer.symb("+") +
111 tllexer.symb("-");
112 MulOp = tllexer.symb("*") +
113 tllexer.symb("//") +
114 tllexer.symb("/") +
115 tllexer.symb("%");
116 UnOp = tllexer.kw("not") +
117 tllexer.symb("-") +
118 tllexer.symb("~") +
119 tllexer.symb("#");
120 PowOp = tllexer.symb("^");
121 Expr = lpeg.V("SubExpr_1");
122 SubExpr_1 = chainl1(lpeg.V("SubExpr_2"), lpeg.V("OrOp"), "SubExpr_1");
123 SubExpr_2 = chainl1(lpeg.V("SubExpr_3"), lpeg.V("AndOp"), "SubExpr_2");
124 SubExpr_3 = chainl1(lpeg.V("SubExpr_4"), lpeg.V("RelOp"), "SubExpr_3");
125 SubExpr_4 = chainl1(lpeg.V("SubExpr_5"), lpeg.V("BOrOp"), "SubExpr_4");
126 SubExpr_5 = chainl1(lpeg.V("SubExpr_6"), lpeg.V("BXorOp"), "SubExpr_5");
127 SubExpr_6 = chainl1(lpeg.V("SubExpr_7"), lpeg.V("BAndOp"), "SubExpr_6");
128 SubExpr_7 = chainl1(lpeg.V("SubExpr_8"), lpeg.V("ShiftOp"), "SubExpr_7");
129 SubExpr_8 = lpeg.V("SubExpr_9") * lpeg.V("ConOp") * tllexer.try(lpeg.V("SubExpr_8"), "SubExpr_8") +
130 lpeg.V("SubExpr_9");
131 SubExpr_9 = chainl1(lpeg.V("SubExpr_10"), lpeg.V("AddOp"), "SubExpr_9");
132 SubExpr_10 = chainl1(lpeg.V("SubExpr_11"), lpeg.V("MulOp"), "SubExpr_10");
133 SubExpr_11 = lpeg.V("UnOp") * tllexer.try(lpeg.V("SubExpr_11"), "SubExpr_11") +
134 lpeg.V("SubExpr_12");
135 SubExpr_12 = lpeg.V("SimpleExp") * (lpeg.V("PowOp") * tllexer.try(lpeg.V("SubExpr_11"), "SubExpr_12"))^-1;
136 SimpleExp = tllexer.token(tllexer.Number, "Number") +
137 tllexer.token(tllexer.String, "String") +
138 tllexer.kw("nil") +
139 tllexer.kw("false") +
140 tllexer.kw("true") +
141 tllexer.symb("...") +
142 lpeg.V("FunctionDef") +
143 lpeg.V("Constructor") +
144 lpeg.V("SuffixedExp");
145 SuffixedExp = lpeg.V("PrimaryExp") * (
146 (tllexer.symb(".") * tllexer.try(tllexer.token(tllexer.Name, "Name"), "DotIndex")) / "index" +
147 (tllexer.symb("[") * lpeg.V("Expr") * tllexer.try(tllexer.symb("]"), "MissingCB")) / "index" +
148 (tllexer.symb(":") * tllexer.try(tllexer.token(tllexer.Name, "Name"), "MethodName") * tllexer.try(lpeg.V("FuncArgs"), "MethodCall")) / "call" +
149 lpeg.V("FuncArgs") / "call")^0 / function (...) local l = {...}; return l[#l] end;
150 PrimaryExp = lpeg.V("Var") / "var" +
151 tllexer.symb("(") * lpeg.V("Expr") * tllexer.try(tllexer.symb(")"), "MissingCP");
152 Block = lpeg.V("StatList") * lpeg.V("RetStat")^-1;
153 IfStat = tllexer.kw("if") * lpeg.V("Expr") * tllexer.try(tllexer.kw("then"), "Then") * lpeg.V("Block") *
154 (tllexer.kw("elseif") * tllexer.try(lpeg.V("Expr"), "ElseIf") * tllexer.try(tllexer.kw("then"), "Then") * lpeg.V("Block"))^0 *
155 (tllexer.kw("else") * lpeg.V("Block"))^-1 *
156 tllexer.try(tllexer.kw("end"), "IfEnd");
157 WhileStat = tllexer.kw("while") * lpeg.V("Expr") *
158 tllexer.try(tllexer.kw("do"), "WhileDo") * lpeg.V("Block") * tllexer.try(tllexer.kw("end"), "WhileEnd");
159 DoStat = tllexer.kw("do") * lpeg.V("Block") * tllexer.try(tllexer.kw("end"), "BlockEnd");
160 ForBody = tllexer.try(tllexer.kw("do"), "ForDo") * lpeg.V("Block");
161 ForNum = lpeg.V("Id") * tllexer.symb("=") * lpeg.V("Expr") * tllexer.symb(",") *
162 lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^-1 *
163 lpeg.V("ForBody");
164 ForGen = lpeg.V("NameList") * tllexer.try(tllexer.kw("in"), "ForGen") *
165 lpeg.V("ExpList") * lpeg.V("ForBody");
166 ForStat = tllexer.kw("for") * (lpeg.V("ForNum") + lpeg.V("ForGen")) * tllexer.try(tllexer.kw("end"), "ForEnd");
167 RepeatStat = tllexer.kw("repeat") * lpeg.V("Block") *
168 tllexer.try(tllexer.kw("until"), "Until") * lpeg.V("Expr");
169 FuncName = lpeg.V("Id") * (tllexer.symb(".") *
170 (tllexer.token(tllexer.Name, "Name")))^0 *
171 (tllexer.symb(":") * (tllexer.token(tllexer.Name, "Name")))^-1;
172 ParList = lpeg.V("NameList") * (tllexer.symb(",") * tllexer.try(lpeg.V("TypedVarArg"), "ParList"))^-1 +
173 lpeg.V("TypedVarArg");
174 TypedVarArg = tllexer.symb("...") * (tllexer.symb(":") * tllexer.try(lpeg.V("Type"), "Type"))^-1;
175 FuncBody = tllexer.try(tllexer.symb("("), "MissingOP") * lpeg.V("ParList")^-1 * tllexer.try(tllexer.symb(")"), "MissingCP") *
176 (tllexer.symb(":") * tllexer.try(lpeg.V("RetType"), "Type"))^-1 *
177 lpeg.V("Block") * tllexer.try(tllexer.kw("end"), "FuncEnd");
178 FuncStat = tllexer.kw("const")^-1 *
179 tllexer.kw("function") * lpeg.V("FuncName") * lpeg.V("FuncBody");
180 LocalFunc = tllexer.kw("function") *
181 tllexer.try(lpeg.V("Id"), "LocalFunc") * lpeg.V("FuncBody");
182 LocalAssign = lpeg.V("NameList") * tllexer.symb("=") * tllexer.try(lpeg.V("ExpList"), "LocalAssign1") +
183 lpeg.V("NameList") * (#(-tllexer.symb("=") * (lpeg.V("Stat") + -1)) * lpeg.P(true)) + lpeg.T(tlerror.labels["LocalAssign2"]);
184 LocalStat = tllexer.kw("local") *
185 (lpeg.V("LocalTypeDec") + lpeg.V("LocalFunc") + lpeg.V("LocalAssign"));
186 LabelStat = tllexer.symb("::") * tllexer.try(tllexer.token(tllexer.Name, "Name"), "Label1") * tllexer.try(tllexer.symb("::"), "Label2");
187 BreakStat = tllexer.kw("break");
188 GoToStat = tllexer.kw("goto") * tllexer.token(tllexer.Name, "Name");
189 RetStat = tllexer.kw("return") * tllexer.try(-lpeg.V("Stat"), "RetStat") *
190 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 *
191 tllexer.symb(";")^-1;
192 TypeDecStat = lpeg.V("Interface");
193 LocalTypeDec = lpeg.V("TypeDecStat");
194 LVar = (tllexer.kw("const") * lpeg.V("SuffixedExp")) +
195 lpeg.V("SuffixedExp");
196 ExprStat = lpeg.Cmt(lpeg.V("LVar") * lpeg.V("Assignment"),
197 function (s, i, ...)
198 local l = {...}
199 local i = 1
200 while l[i] ~= "=" do
201 local se = l[i]
202 if se ~= "var" and se ~= "index" then return false end
203 i = i + 1
204 end
205 return true
206 end) +
207 lpeg.Cmt(lpeg.V("SuffixedExp"),
208 function (s, i, se)
209 if se ~= "call" then return false end
210 return true
211 end);
212 Assignment = ((tllexer.symb(",") * lpeg.V("LVar"))^1)^-1 * (tllexer.symb("=") / "=") * lpeg.V("ExpList");
213 Stat = lpeg.V("IfStat") + lpeg.V("WhileStat") + lpeg.V("DoStat") + lpeg.V("ForStat") +
214 lpeg.V("RepeatStat") + lpeg.V("FuncStat") + lpeg.V("LocalStat") +
215 lpeg.V("LabelStat") + lpeg.V("BreakStat") + lpeg.V("GoToStat") +
216 lpeg.V("TypeDecStat") + lpeg.V("ExprStat");
217}
218
219local function lineno (s, i)
220 if i == 1 then return 1, 1 end
221 local rest, num = s:sub(1,i):gsub("[^\n]*\n", "")
222 local r = #rest
223 return 1 + num, r ~= 0 and r or 1
224end
225
226function tlparser.parse (subject, filename, strict, integer)
227 local errorinfo = {}
228 lpeg.setmaxstack(1000)
229 local ast, label, suffix = lpeg.match(G, subject, nil, errorinfo, strict, integer)
230 if not ast then
231 local line, col = lineno(subject, string.len(subject) - string.len(suffix))
232 local error_msg = string.format("%s:%d:%d: ", filename, line, col)
233 if label ~= 0 then
234 error_msg = error_msg .. tlerror.errors[label].msg
235 else
236 local u = lpeg.match(lpeg.C(tllexer.OneWord) + lpeg.Cc("EOF"), subject, errorinfo.ffp)
237 error_msg = error_msg .. string.format("unexpected '%s', expecting %s", u, errorinfo.expected)
238 end
239 return nil, error_msg
240 else
241 return true
242 end
243end
244
245return tlparser