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.lua139
1 files changed, 78 insertions, 61 deletions
diff --git a/examples/typedlua/tlparser.lua b/examples/typedlua/tlparser.lua
index 002e580..c8d03ea 100644
--- a/examples/typedlua/tlparser.lua
+++ b/examples/typedlua/tlparser.lua
@@ -4,8 +4,9 @@ local lpeg = require "lpeglabel"
4lpeg.locale(lpeg) 4lpeg.locale(lpeg)
5 5
6local tllexer = require "tllexer" 6local tllexer = require "tllexer"
7local tlerror = require "tlerror"
7 8
8local function chainl1 (pat, sep) 9local function chainl1 (pat, sep, label)
9 return pat * (sep * pat)^0 10 return pat * (sep * pat)^0
10end 11end
11 12
@@ -14,7 +15,7 @@ local G = lpeg.P { "TypedLua";
14 -- type language 15 -- type language
15 Type = lpeg.V("NilableType"); 16 Type = lpeg.V("NilableType");
16 NilableType = lpeg.V("UnionType") * tllexer.symb("?")^-1; 17 NilableType = lpeg.V("UnionType") * tllexer.symb("?")^-1;
17 UnionType = lpeg.V("PrimaryType") * (tllexer.symb("|") * lpeg.V("PrimaryType"))^0; 18 UnionType = lpeg.V("PrimaryType") * (tllexer.symb("|") * tllexer.try(lpeg.V("PrimaryType"), "UnionType"))^0;
18 PrimaryType = lpeg.V("LiteralType") + 19 PrimaryType = lpeg.V("LiteralType") +
19 lpeg.V("BaseType") + 20 lpeg.V("BaseType") +
20 lpeg.V("NilType") + 21 lpeg.V("NilType") +
@@ -24,73 +25,74 @@ local G = lpeg.P { "TypedLua";
24 lpeg.V("FunctionType") + 25 lpeg.V("FunctionType") +
25 lpeg.V("TableType") + 26 lpeg.V("TableType") +
26 lpeg.V("VariableType"); 27 lpeg.V("VariableType");
27 LiteralType = tllexer.token("false") + 28 LiteralType = tllexer.token("false", "false") +
28 tllexer.token("true") + 29 tllexer.token("true", "true") +
29 tllexer.token(tllexer.Number) + 30 tllexer.token(tllexer.Number, "Number") +
30 tllexer.token(tllexer.String); 31 tllexer.token(tllexer.String, "String");
31 BaseType = tllexer.token("boolean") + 32 BaseType = tllexer.token("boolean", "boolean") +
32 tllexer.token("number") + 33 tllexer.token("number", "number") +
33 tllexer.token("string") + 34 tllexer.token("string", "string") +
34 tllexer.token("integer"); 35 tllexer.token("integer", "integer");
35 NilType = tllexer.token("nil"); 36 NilType = tllexer.token("nil", "nil");
36 ValueType = tllexer.token("value"); 37 ValueType = tllexer.token("value", "value");
37 AnyType = tllexer.token("any"); 38 AnyType = tllexer.token("any", "any");
38 SelfType = tllexer.token("self"); 39 SelfType = tllexer.token("self", "self");
39 FunctionType = lpeg.V("InputType") * tllexer.symb("->") * lpeg.V("NilableTuple"); 40 FunctionType = lpeg.V("InputType") * tllexer.symb("->") * tllexer.try(lpeg.V("NilableTuple"), "FunctionType");
40 MethodType = lpeg.V("InputType") * tllexer.symb("=>") * lpeg.V("NilableTuple"); 41 MethodType = lpeg.V("InputType") * tllexer.symb("=>") * tllexer.try(lpeg.V("NilableTuple"), "MethodType");
41 InputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.symb(")"); 42 InputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.try(tllexer.symb(")"), "MissingCP");
42 NilableTuple = lpeg.V("UnionlistType") * tllexer.symb("?")^-1; 43 NilableTuple = lpeg.V("UnionlistType") * tllexer.symb("?")^-1;
43 UnionlistType = lpeg.V("OutputType") * (tllexer.symb("|") * lpeg.V("OutputType"))^0; 44 UnionlistType = lpeg.V("OutputType") * (tllexer.symb("|") * tllexer.try(lpeg.V("OutputType"), "UnionType"))^0;
44 OutputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.symb(")"); 45 OutputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.try(tllexer.symb(")"), "MissingCP");
45 TupleType = lpeg.V("Type") * (tllexer.symb(",") * lpeg.V("Type"))^0 * tllexer.symb("*")^-1; 46 TupleType = lpeg.V("Type") * (tllexer.symb(",") * tllexer.try(lpeg.V("Type"), "TupleType"))^0 * tllexer.symb("*")^-1;
46 TableType = tllexer.symb("{") * lpeg.V("TableTypeBody")^-1 * tllexer.symb("}"); 47 TableType = tllexer.symb("{") * lpeg.V("TableTypeBody")^-1 * tllexer.try(tllexer.symb("}"), "MissingCC");
47 TableTypeBody = lpeg.V("RecordType") + 48 TableTypeBody = lpeg.V("RecordType") +
48 lpeg.V("HashType") + 49 lpeg.V("HashType") +
49 lpeg.V("ArrayType"); 50 lpeg.V("ArrayType");
50 RecordType = lpeg.V("RecordField") * (tllexer.symb(",") * lpeg.V("RecordField"))^0 * 51 RecordType = lpeg.V("RecordField") * (tllexer.symb(",") * lpeg.V("RecordField"))^0 *
51 (tllexer.symb(",") * (lpeg.V("HashType") + lpeg.V("ArrayType")))^-1; 52 (tllexer.symb(",") * (lpeg.V("HashType") + lpeg.V("ArrayType")))^-1;
52 RecordField = tllexer.kw("const")^-1 * 53 RecordField = tllexer.kw("const")^-1 *
53 lpeg.V("LiteralType") * tllexer.symb(":") * lpeg.V("Type"); 54 lpeg.V("LiteralType") * tllexer.symb(":") * tllexer.try(lpeg.V("Type"), "Type");
54 HashType = lpeg.V("KeyType") * tllexer.symb(":") * lpeg.V("FieldType"); 55 HashType = lpeg.V("KeyType") * tllexer.symb(":") * tllexer.try(lpeg.V("FieldType"), "Type");
55 ArrayType = lpeg.V("FieldType"); 56 ArrayType = lpeg.V("FieldType");
56 KeyType = lpeg.V("BaseType") + lpeg.V("ValueType") + lpeg.V("AnyType"); 57 KeyType = lpeg.V("BaseType") + lpeg.V("ValueType") + lpeg.V("AnyType");
57 FieldType = lpeg.V("Type"); 58 FieldType = lpeg.V("Type");
58 VariableType = tllexer.token(tllexer.Name); 59 VariableType = tllexer.token(tllexer.Name, "Name");
59 RetType = lpeg.V("NilableTuple") + 60 RetType = lpeg.V("NilableTuple") +
60 lpeg.V("Type"); 61 lpeg.V("Type");
61 Id = tllexer.token(tllexer.Name); 62 Id = tllexer.token(tllexer.Name, "Name");
62 TypeDecId = (tllexer.kw("const") * lpeg.V("Id")) + 63 TypeDecId = (tllexer.kw("const") * lpeg.V("Id")) +
63 lpeg.V("Id"); 64 lpeg.V("Id");
64 IdList = lpeg.V("TypeDecId") * (tllexer.symb(",") * lpeg.V("TypeDecId"))^0; 65 IdList = lpeg.V("TypeDecId") * (tllexer.symb(",") * tllexer.try(lpeg.V("TypeDecId"), "TupleType"))^0;
65 IdDec = lpeg.V("IdList") * tllexer.symb(":") * 66 IdDec = lpeg.V("IdList") * tllexer.symb(":") * tllexer.try((lpeg.V("Type") + lpeg.V("MethodType")), "Type");
66 (lpeg.V("Type") + lpeg.V("MethodType"));
67 IdDecList = (lpeg.V("IdDec")^1)^-1; 67 IdDecList = (lpeg.V("IdDec")^1)^-1;
68 TypeDec = tllexer.token(tllexer.Name) * lpeg.V("IdDecList") * tllexer.kw("end"); 68 TypeDec = tllexer.token(tllexer.Name, "Name") * lpeg.V("IdDecList") * tllexer.try(tllexer.kw("end"), "TypeDecEnd");
69 Interface = tllexer.kw("interface") * lpeg.V("TypeDec") + 69 Interface = tllexer.kw("interface") * lpeg.V("TypeDec") +
70 tllexer.kw("typealias") * tllexer.token(tllexer.Name) * tllexer.symb("=") * lpeg.V("Type"); 70 tllexer.kw("typealias") *
71 tllexer.try(tllexer.token(tllexer.Name, "Name"), "TypeAliasName") *
72 tllexer.try(tllexer.symb("="), "MissingEqTypeAlias") * lpeg.V("Type");
71 -- parser 73 -- parser
72 Chunk = lpeg.V("Block"); 74 Chunk = lpeg.V("Block");
73 StatList = (tllexer.symb(";") + lpeg.V("Stat"))^0; 75 StatList = (tllexer.symb(";") + lpeg.V("Stat"))^0;
74 Var = lpeg.V("Id"); 76 Var = lpeg.V("Id");
75 TypedId = tllexer.token(tllexer.Name) * (tllexer.symb(":") * lpeg.V("Type"))^-1; 77 TypedId = tllexer.token(tllexer.Name, "Name") * (tllexer.symb(":") * tllexer.try(lpeg.V("Type"), "Type"))^-1;
76 FunctionDef = tllexer.kw("function") * lpeg.V("FuncBody"); 78 FunctionDef = tllexer.kw("function") * lpeg.V("FuncBody");
77 FieldSep = tllexer.symb(",") + tllexer.symb(";"); 79 FieldSep = tllexer.symb(",") + tllexer.symb(";");
78 Field = ((tllexer.symb("[") * lpeg.V("Expr") * tllexer.symb("]")) + 80 Field = ((tllexer.symb("[") * lpeg.V("Expr") * tllexer.try(tllexer.symb("]"), "MissingCB")) +
79 (tllexer.token(tllexer.Name))) * 81 (tllexer.token(tllexer.Name, "Name"))) *
80 tllexer.symb("=") * lpeg.V("Expr") + 82 tllexer.symb("=") * lpeg.V("Expr") +
81 lpeg.V("Expr"); 83 lpeg.V("Expr");
82 TField = (tllexer.kw("const") * lpeg.V("Field")) + 84 TField = (tllexer.kw("const") * lpeg.V("Field")) +
83 lpeg.V("Field"); 85 lpeg.V("Field");
84 FieldList = (lpeg.V("TField") * (lpeg.V("FieldSep") * lpeg.V("TField"))^0 * 86 FieldList = (lpeg.V("TField") * (lpeg.V("FieldSep") * lpeg.V("TField"))^0 *
85 lpeg.V("FieldSep")^-1)^-1; 87 lpeg.V("FieldSep")^-1)^-1;
86 Constructor = tllexer.symb("{") * lpeg.V("FieldList") * tllexer.symb("}"); 88 Constructor = tllexer.symb("{") * lpeg.V("FieldList") * tllexer.try(tllexer.symb("}"), "MissingCC");
87 NameList = lpeg.V("TypedId") * (tllexer.symb(",") * lpeg.V("TypedId"))^0; 89 NameList = lpeg.V("TypedId") * (tllexer.symb(",") * lpeg.V("TypedId"))^0;
88 ExpList = lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0; 90 ExpList = lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0;
89 FuncArgs = tllexer.symb("(") * 91 FuncArgs = tllexer.symb("(") *
90 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 * 92 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 *
91 tllexer.symb(")") + 93 tllexer.try(tllexer.symb(")"), "MissingCP") +
92 lpeg.V("Constructor") + 94 lpeg.V("Constructor") +
93 tllexer.token(tllexer.String); 95 tllexer.token(tllexer.String, "String");
94 OrOp = tllexer.kw("or"); 96 OrOp = tllexer.kw("or");
95 AndOp = tllexer.kw("and"); 97 AndOp = tllexer.kw("and");
96 RelOp = tllexer.symb("~=") + 98 RelOp = tllexer.symb("~=") +
@@ -131,8 +133,8 @@ local G = lpeg.P { "TypedLua";
131 SubExpr_11 = lpeg.V("UnOp") * lpeg.V("SubExpr_11") + 133 SubExpr_11 = lpeg.V("UnOp") * lpeg.V("SubExpr_11") +
132 lpeg.V("SubExpr_12"); 134 lpeg.V("SubExpr_12");
133 SubExpr_12 = lpeg.V("SimpleExp") * (lpeg.V("PowOp") * lpeg.V("SubExpr_11"))^-1; 135 SubExpr_12 = lpeg.V("SimpleExp") * (lpeg.V("PowOp") * lpeg.V("SubExpr_11"))^-1;
134 SimpleExp = tllexer.token(tllexer.Number) + 136 SimpleExp = tllexer.token(tllexer.Number, "Number") +
135 tllexer.token(tllexer.String) + 137 tllexer.token(tllexer.String, "String") +
136 tllexer.kw("nil") + 138 tllexer.kw("nil") +
137 tllexer.kw("false") + 139 tllexer.kw("false") +
138 tllexer.kw("true") + 140 tllexer.kw("true") +
@@ -141,49 +143,49 @@ local G = lpeg.P { "TypedLua";
141 lpeg.V("Constructor") + 143 lpeg.V("Constructor") +
142 lpeg.V("SuffixedExp"); 144 lpeg.V("SuffixedExp");
143 SuffixedExp = lpeg.V("PrimaryExp") * ( 145 SuffixedExp = lpeg.V("PrimaryExp") * (
144 (tllexer.symb(".") * tllexer.token(tllexer.Name)) / "index" + 146 (tllexer.symb(".") * tllexer.try(tllexer.token(tllexer.Name, "Name"), "DotIndex")) / "index" +
145 (tllexer.symb("[") * lpeg.V("Expr") * tllexer.symb("]")) / "index" + 147 (tllexer.symb("[") * lpeg.V("Expr") * tllexer.try(tllexer.symb("]"), "MissingCB")) / "index" +
146 (tllexer.symb(":") * tllexer.token(tllexer.Name) * lpeg.V("FuncArgs")) / "call" + 148 (tllexer.symb(":") * tllexer.try(tllexer.token(tllexer.Name, "Name"), "MethodName") * tllexer.try(lpeg.V("FuncArgs"), "MethodCall")) / "call" +
147 lpeg.V("FuncArgs") / "call")^0 / function (...) local l = {...}; return l[#l] end; 149 lpeg.V("FuncArgs") / "call")^0 / function (...) local l = {...}; return l[#l] end;
148 PrimaryExp = lpeg.V("Var") / "var" + 150 PrimaryExp = lpeg.V("Var") / "var" +
149 tllexer.symb("(") * lpeg.V("Expr") * tllexer.symb(")"); 151 tllexer.symb("(") * lpeg.V("Expr") * tllexer.try(tllexer.symb(")"), "MissingCP");
150 Block = lpeg.V("StatList") * lpeg.V("RetStat")^-1; 152 Block = lpeg.V("StatList") * lpeg.V("RetStat")^-1;
151 IfStat = tllexer.kw("if") * lpeg.V("Expr") * tllexer.kw("then") * lpeg.V("Block") * 153 IfStat = tllexer.kw("if") * lpeg.V("Expr") * tllexer.try(tllexer.kw("then"), "Then") * lpeg.V("Block") *
152 (tllexer.kw("elseif") * lpeg.V("Expr") * tllexer.kw("then") * lpeg.V("Block"))^0 * 154 (tllexer.kw("elseif") * lpeg.V("Expr") * tllexer.try(tllexer.kw("then"), "Then") * lpeg.V("Block"))^0 *
153 (tllexer.kw("else") * lpeg.V("Block"))^-1 * 155 (tllexer.kw("else") * lpeg.V("Block"))^-1 *
154 tllexer.kw("end"); 156 tllexer.try(tllexer.kw("end"), "IfEnd");
155 WhileStat = tllexer.kw("while") * lpeg.V("Expr") * 157 WhileStat = tllexer.kw("while") * lpeg.V("Expr") *
156 tllexer.kw("do") * lpeg.V("Block") * tllexer.kw("end"); 158 tllexer.try(tllexer.kw("do"), "WhileDo") * lpeg.V("Block") * tllexer.try(tllexer.kw("end"), "WhileEnd");
157 DoStat = tllexer.kw("do") * lpeg.V("Block") * tllexer.kw("end"); 159 DoStat = tllexer.kw("do") * lpeg.V("Block") * tllexer.try(tllexer.kw("end"), "BlockEnd");
158 ForBody = tllexer.kw("do") * lpeg.V("Block"); 160 ForBody = tllexer.try(tllexer.kw("do"), "ForDo") * lpeg.V("Block");
159 ForNum = lpeg.V("Id") * tllexer.symb("=") * lpeg.V("Expr") * tllexer.symb(",") * 161 ForNum = lpeg.V("Id") * tllexer.symb("=") * lpeg.V("Expr") * tllexer.symb(",") *
160 lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^-1 * 162 lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^-1 *
161 lpeg.V("ForBody"); 163 lpeg.V("ForBody");
162 ForGen = lpeg.V("NameList") * tllexer.kw("in") * 164 ForGen = lpeg.V("NameList") * tllexer.kw("in") *
163 lpeg.V("ExpList") * lpeg.V("ForBody"); 165 lpeg.V("ExpList") * lpeg.V("ForBody");
164 ForStat = tllexer.kw("for") * (lpeg.V("ForNum") + lpeg.V("ForGen")) * tllexer.kw("end"); 166 ForStat = tllexer.kw("for") * (lpeg.V("ForNum") + lpeg.V("ForGen")) * tllexer.try(tllexer.kw("end"), "ForEnd");
165 RepeatStat = tllexer.kw("repeat") * lpeg.V("Block") * 167 RepeatStat = tllexer.kw("repeat") * lpeg.V("Block") *
166 tllexer.kw("until") * lpeg.V("Expr"); 168 tllexer.try(tllexer.kw("until"), "Until") * lpeg.V("Expr");
167 FuncName = lpeg.V("Id") * (tllexer.symb(".") * 169 FuncName = lpeg.V("Id") * (tllexer.symb(".") *
168 (tllexer.token(tllexer.Name)))^0 * 170 (tllexer.token(tllexer.Name, "Name")))^0 *
169 (tllexer.symb(":") * (tllexer.token(tllexer.Name)))^-1; 171 (tllexer.symb(":") * (tllexer.token(tllexer.Name, "Name")))^-1;
170 ParList = lpeg.V("NameList") * (tllexer.symb(",") * lpeg.V("TypedVarArg"))^-1 + 172 ParList = lpeg.V("NameList") * (tllexer.symb(",") * tllexer.try(lpeg.V("TypedVarArg"), "ParList"))^-1 +
171 lpeg.V("TypedVarArg"); 173 lpeg.V("TypedVarArg");
172 TypedVarArg = tllexer.symb("...") * (tllexer.symb(":") * lpeg.V("Type"))^-1; 174 TypedVarArg = tllexer.symb("...") * (tllexer.symb(":") * tllexer.try(lpeg.V("Type"), "Type"))^-1;
173 FuncBody = tllexer.symb("(") * lpeg.V("ParList")^-1 * tllexer.symb(")") * 175 FuncBody = tllexer.symb("(") * lpeg.V("ParList")^-1 * tllexer.try(tllexer.symb(")"), "MissingCP") *
174 (tllexer.symb(":") * lpeg.V("RetType"))^-1 * 176 (tllexer.symb(":") * tllexer.try(lpeg.V("RetType"), "Type"))^-1 *
175 lpeg.V("Block") * tllexer.kw("end"); 177 lpeg.V("Block") * tllexer.try(tllexer.kw("end"), "FuncEnd");
176 FuncStat = tllexer.kw("const")^-1 * 178 FuncStat = tllexer.kw("const")^-1 *
177 tllexer.kw("function") * lpeg.V("FuncName") * lpeg.V("FuncBody"); 179 tllexer.kw("function") * lpeg.V("FuncName") * lpeg.V("FuncBody");
178 LocalFunc = tllexer.kw("function") * 180 LocalFunc = tllexer.kw("function") *
179 lpeg.V("Id") * lpeg.V("FuncBody"); 181 lpeg.V("Id") * lpeg.V("FuncBody");
180 LocalAssign = lpeg.V("NameList") * 182 LocalAssign = lpeg.V("NameList") *
181 ((tllexer.symb("=") * lpeg.V("ExpList")))^-1; 183 ((tllexer.symb("=") * tllexer.try(lpeg.V("ExpList"), "LocalAssign")))^-1;
182 LocalStat = tllexer.kw("local") * 184 LocalStat = tllexer.kw("local") *
183 (lpeg.V("LocalTypeDec") + lpeg.V("LocalFunc") + lpeg.V("LocalAssign")); 185 (lpeg.V("LocalTypeDec") + lpeg.V("LocalFunc") + lpeg.V("LocalAssign"));
184 LabelStat = tllexer.symb("::") * tllexer.token(tllexer.Name) * tllexer.symb("::"); 186 LabelStat = tllexer.symb("::") * tllexer.try(tllexer.token(tllexer.Name, "Name"), "Label1") * tllexer.try(tllexer.symb("::"), "Label2");
185 BreakStat = tllexer.kw("break"); 187 BreakStat = tllexer.kw("break");
186 GoToStat = tllexer.kw("goto") * tllexer.token(tllexer.Name); 188 GoToStat = tllexer.kw("goto") * tllexer.token(tllexer.Name, "Name");
187 RetStat = tllexer.kw("return") * 189 RetStat = tllexer.kw("return") *
188 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 * 190 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 *
189 tllexer.symb(";")^-1; 191 tllexer.symb(";")^-1;
@@ -214,12 +216,27 @@ local G = lpeg.P { "TypedLua";
214 lpeg.V("TypeDecStat") + lpeg.V("ExprStat"); 216 lpeg.V("TypeDecStat") + lpeg.V("ExprStat");
215} 217}
216 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
217function tlparser.parse (subject, filename, strict, integer) 226function tlparser.parse (subject, filename, strict, integer)
218 local errorinfo = {} 227 local errorinfo = {}
219 lpeg.setmaxstack(1000) 228 lpeg.setmaxstack(1000)
220 local ast, label, _ = lpeg.match(G, subject, nil, errorinfo, strict, integer) 229 local ast, label, _ = lpeg.match(G, subject, nil, errorinfo, strict, integer)
221 if not ast then 230 if not ast then
222 return nil 231 local line, col = lineno(subject, errorinfo.ffp)
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
223 else 240 else
224 return true 241 return true
225 end 242 end