diff options
Diffstat (limited to 'examples/typedlua/tlparser.lua')
-rw-r--r-- | examples/typedlua/tlparser.lua | 245 |
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 @@ | |||
1 | local tlparser = {} | ||
2 | |||
3 | local lpeg = require "lpeglabel" | ||
4 | lpeg.locale(lpeg) | ||
5 | |||
6 | local tllexer = require "tllexer" | ||
7 | local tlerror = require "tlerror" | ||
8 | |||
9 | local function chainl1 (pat, sep, label) | ||
10 | return pat * (sep * tllexer.try(pat, label))^0 | ||
11 | end | ||
12 | |||
13 | local 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 | |||
219 | local 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 | ||
224 | end | ||
225 | |||
226 | function 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 | ||
243 | end | ||
244 | |||
245 | return tlparser | ||