aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Murbach Maidl <andremm@gmail.com>2015-10-04 20:10:05 -0300
committerAndre Murbach Maidl <andremm@gmail.com>2015-10-04 20:10:05 -0300
commit781fd9653ed0a89dd8f3d8ccfab63e249f1edb07 (patch)
tree298232c6c2585b49bc1c03e89aa9428d95d9f403
parent8ac31b94b88227222b189c447aeea1b4131eed18 (diff)
downloadlpeglabel-781fd9653ed0a89dd8f3d8ccfab63e249f1edb07.tar.gz
lpeglabel-781fd9653ed0a89dd8f3d8ccfab63e249f1edb07.tar.bz2
lpeglabel-781fd9653ed0a89dd8f3d8ccfab63e249f1edb07.zip
Adding Typed Lua parser
-rw-r--r--examples/typedlua/tllexer.lua80
-rw-r--r--examples/typedlua/tlp.lua18
-rw-r--r--examples/typedlua/tlparser.lua228
3 files changed, 326 insertions, 0 deletions
diff --git a/examples/typedlua/tllexer.lua b/examples/typedlua/tllexer.lua
new file mode 100644
index 0000000..bcfa802
--- /dev/null
+++ b/examples/typedlua/tllexer.lua
@@ -0,0 +1,80 @@
1local tllexer = {}
2
3local lpeg = require "lpeglabel"
4lpeg.locale(lpeg)
5
6local function setffp (s, i, t)
7 if not t.ffp or i > t.ffp then
8 t.ffp = i
9 end
10 return false
11end
12
13local function updateffp ()
14 return lpeg.Cmt(lpeg.Carg(1), setffp)
15end
16
17tllexer.Shebang = lpeg.P("#") * (lpeg.P(1) - lpeg.P("\n"))^0 * lpeg.P("\n")
18
19local Space = lpeg.space^1
20
21local Equals = lpeg.P("=")^0
22local Open = "[" * lpeg.Cg(Equals, "init") * "[" * lpeg.P("\n")^-1
23local Close = "]" * lpeg.C(Equals) * "]"
24local CloseEQ = lpeg.Cmt(Close * lpeg.Cb("init"),
25 function (s, i, a, b) return a == b end)
26
27local LongString = Open * (lpeg.P(1) - CloseEQ)^0 * Close /
28 function (s, o) return s end
29
30local Comment = lpeg.P("--") * LongString /
31 function () return end +
32 lpeg.P("--") * (lpeg.P(1) - lpeg.P("\n"))^0
33
34tllexer.Skip = (Space + Comment)^0
35
36local idStart = lpeg.alpha + lpeg.P("_")
37local idRest = lpeg.alnum + lpeg.P("_")
38
39local Keywords = lpeg.P("and") + "break" + "do" + "elseif" + "else" + "end" +
40 "false" + "for" + "function" + "goto" + "if" + "in" +
41 "local" + "nil" + "not" + "or" + "repeat" + "return" +
42 "then" + "true" + "until" + "while"
43
44tllexer.Reserved = Keywords * -idRest
45
46local Identifier = idStart * idRest^0
47
48tllexer.Name = -tllexer.Reserved * Identifier * -idRest
49
50function tllexer.token (pat)
51 return pat * tllexer.Skip + updateffp() * lpeg.P(false)
52end
53
54function tllexer.symb (str)
55 return tllexer.token(lpeg.P(str))
56end
57
58function tllexer.kw (str)
59 return tllexer.token(lpeg.P(str) * -idRest)
60end
61
62local Hex = (lpeg.P("0x") + lpeg.P("0X")) * lpeg.xdigit^1
63local Expo = lpeg.S("eE") * lpeg.S("+-")^-1 * lpeg.digit^1
64local Float = (((lpeg.digit^1 * lpeg.P(".") * lpeg.digit^0) +
65 (lpeg.P(".") * lpeg.digit^1)) * Expo^-1) +
66 (lpeg.digit^1 * Expo)
67local Int = lpeg.digit^1
68
69tllexer.Number = Hex + Float + Int
70
71local ShortString = lpeg.P('"') *
72 ((lpeg.P('\\') * lpeg.P(1)) + (lpeg.P(1) - lpeg.P('"')))^0 *
73 lpeg.P('"') +
74 lpeg.P("'") *
75 ((lpeg.P("\\") * lpeg.P(1)) + (lpeg.P(1) - lpeg.P("'")))^0 *
76 lpeg.P("'")
77
78tllexer.String = LongString + ShortString
79
80return tllexer
diff --git a/examples/typedlua/tlp.lua b/examples/typedlua/tlp.lua
new file mode 100644
index 0000000..4605751
--- /dev/null
+++ b/examples/typedlua/tlp.lua
@@ -0,0 +1,18 @@
1local tlparser = require "tlparser"
2
3local function getcontents(filename)
4 file = assert(io.open(filename, "r"))
5 contents = file:read("*a")
6 file:close()
7 return contents
8end
9
10if #arg ~= 1 then
11 print ("Usage: lua tlp.lua <file>")
12 os.exit(1)
13end
14
15local filename = arg[1]
16local subject = getcontents(filename)
17
18print(tlparser.parse(subject, filename, false, true))
diff --git a/examples/typedlua/tlparser.lua b/examples/typedlua/tlparser.lua
new file mode 100644
index 0000000..002e580
--- /dev/null
+++ b/examples/typedlua/tlparser.lua
@@ -0,0 +1,228 @@
1local tlparser = {}
2
3local lpeg = require "lpeglabel"
4lpeg.locale(lpeg)
5
6local tllexer = require "tllexer"
7
8local function chainl1 (pat, sep)
9 return pat * (sep * pat)^0
10end
11
12local G = lpeg.P { "TypedLua";
13 TypedLua = tllexer.Shebang^-1 * tllexer.Skip * lpeg.V("Chunk") * -1;
14 -- type language
15 Type = lpeg.V("NilableType");
16 NilableType = lpeg.V("UnionType") * tllexer.symb("?")^-1;
17 UnionType = lpeg.V("PrimaryType") * (tllexer.symb("|") * lpeg.V("PrimaryType"))^0;
18 PrimaryType = lpeg.V("LiteralType") +
19 lpeg.V("BaseType") +
20 lpeg.V("NilType") +
21 lpeg.V("ValueType") +
22 lpeg.V("AnyType") +
23 lpeg.V("SelfType") +
24 lpeg.V("FunctionType") +
25 lpeg.V("TableType") +
26 lpeg.V("VariableType");
27 LiteralType = tllexer.token("false") +
28 tllexer.token("true") +
29 tllexer.token(tllexer.Number) +
30 tllexer.token(tllexer.String);
31 BaseType = tllexer.token("boolean") +
32 tllexer.token("number") +
33 tllexer.token("string") +
34 tllexer.token("integer");
35 NilType = tllexer.token("nil");
36 ValueType = tllexer.token("value");
37 AnyType = tllexer.token("any");
38 SelfType = tllexer.token("self");
39 FunctionType = lpeg.V("InputType") * tllexer.symb("->") * lpeg.V("NilableTuple");
40 MethodType = lpeg.V("InputType") * tllexer.symb("=>") * lpeg.V("NilableTuple");
41 InputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.symb(")");
42 NilableTuple = lpeg.V("UnionlistType") * tllexer.symb("?")^-1;
43 UnionlistType = lpeg.V("OutputType") * (tllexer.symb("|") * lpeg.V("OutputType"))^0;
44 OutputType = tllexer.symb("(") * lpeg.V("TupleType")^-1 * tllexer.symb(")");
45 TupleType = lpeg.V("Type") * (tllexer.symb(",") * lpeg.V("Type"))^0 * tllexer.symb("*")^-1;
46 TableType = tllexer.symb("{") * lpeg.V("TableTypeBody")^-1 * tllexer.symb("}");
47 TableTypeBody = lpeg.V("RecordType") +
48 lpeg.V("HashType") +
49 lpeg.V("ArrayType");
50 RecordType = lpeg.V("RecordField") * (tllexer.symb(",") * lpeg.V("RecordField"))^0 *
51 (tllexer.symb(",") * (lpeg.V("HashType") + lpeg.V("ArrayType")))^-1;
52 RecordField = tllexer.kw("const")^-1 *
53 lpeg.V("LiteralType") * tllexer.symb(":") * lpeg.V("Type");
54 HashType = lpeg.V("KeyType") * tllexer.symb(":") * lpeg.V("FieldType");
55 ArrayType = lpeg.V("FieldType");
56 KeyType = lpeg.V("BaseType") + lpeg.V("ValueType") + lpeg.V("AnyType");
57 FieldType = lpeg.V("Type");
58 VariableType = tllexer.token(tllexer.Name);
59 RetType = lpeg.V("NilableTuple") +
60 lpeg.V("Type");
61 Id = tllexer.token(tllexer.Name);
62 TypeDecId = (tllexer.kw("const") * lpeg.V("Id")) +
63 lpeg.V("Id");
64 IdList = lpeg.V("TypeDecId") * (tllexer.symb(",") * lpeg.V("TypeDecId"))^0;
65 IdDec = lpeg.V("IdList") * tllexer.symb(":") *
66 (lpeg.V("Type") + lpeg.V("MethodType"));
67 IdDecList = (lpeg.V("IdDec")^1)^-1;
68 TypeDec = tllexer.token(tllexer.Name) * lpeg.V("IdDecList") * tllexer.kw("end");
69 Interface = tllexer.kw("interface") * lpeg.V("TypeDec") +
70 tllexer.kw("typealias") * tllexer.token(tllexer.Name) * tllexer.symb("=") * lpeg.V("Type");
71 -- parser
72 Chunk = lpeg.V("Block");
73 StatList = (tllexer.symb(";") + lpeg.V("Stat"))^0;
74 Var = lpeg.V("Id");
75 TypedId = tllexer.token(tllexer.Name) * (tllexer.symb(":") * lpeg.V("Type"))^-1;
76 FunctionDef = tllexer.kw("function") * lpeg.V("FuncBody");
77 FieldSep = tllexer.symb(",") + tllexer.symb(";");
78 Field = ((tllexer.symb("[") * lpeg.V("Expr") * tllexer.symb("]")) +
79 (tllexer.token(tllexer.Name))) *
80 tllexer.symb("=") * lpeg.V("Expr") +
81 lpeg.V("Expr");
82 TField = (tllexer.kw("const") * lpeg.V("Field")) +
83 lpeg.V("Field");
84 FieldList = (lpeg.V("TField") * (lpeg.V("FieldSep") * lpeg.V("TField"))^0 *
85 lpeg.V("FieldSep")^-1)^-1;
86 Constructor = tllexer.symb("{") * lpeg.V("FieldList") * tllexer.symb("}");
87 NameList = lpeg.V("TypedId") * (tllexer.symb(",") * lpeg.V("TypedId"))^0;
88 ExpList = lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0;
89 FuncArgs = tllexer.symb("(") *
90 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 *
91 tllexer.symb(")") +
92 lpeg.V("Constructor") +
93 tllexer.token(tllexer.String);
94 OrOp = tllexer.kw("or");
95 AndOp = tllexer.kw("and");
96 RelOp = tllexer.symb("~=") +
97 tllexer.symb("==") +
98 tllexer.symb("<=") +
99 tllexer.symb(">=") +
100 tllexer.symb("<") +
101 tllexer.symb(">");
102 BOrOp = tllexer.symb("|");
103 BXorOp = tllexer.symb("~");
104 BAndOp = tllexer.symb("&");
105 ShiftOp = tllexer.symb("<<") +
106 tllexer.symb(">>");
107 ConOp = tllexer.symb("..");
108 AddOp = tllexer.symb("+") +
109 tllexer.symb("-");
110 MulOp = tllexer.symb("*") +
111 tllexer.symb("//") +
112 tllexer.symb("/") +
113 tllexer.symb("%");
114 UnOp = tllexer.kw("not") +
115 tllexer.symb("-") +
116 tllexer.symb("~") +
117 tllexer.symb("#");
118 PowOp = tllexer.symb("^");
119 Expr = lpeg.V("SubExpr_1");
120 SubExpr_1 = chainl1(lpeg.V("SubExpr_2"), lpeg.V("OrOp"));
121 SubExpr_2 = chainl1(lpeg.V("SubExpr_3"), lpeg.V("AndOp"));
122 SubExpr_3 = chainl1(lpeg.V("SubExpr_4"), lpeg.V("RelOp"));
123 SubExpr_4 = chainl1(lpeg.V("SubExpr_5"), lpeg.V("BOrOp"));
124 SubExpr_5 = chainl1(lpeg.V("SubExpr_6"), lpeg.V("BXorOp"));
125 SubExpr_6 = chainl1(lpeg.V("SubExpr_7"), lpeg.V("BAndOp"));
126 SubExpr_7 = chainl1(lpeg.V("SubExpr_8"), lpeg.V("ShiftOp"));
127 SubExpr_8 = lpeg.V("SubExpr_9") * lpeg.V("ConOp") * lpeg.V("SubExpr_8") +
128 lpeg.V("SubExpr_9");
129 SubExpr_9 = chainl1(lpeg.V("SubExpr_10"), lpeg.V("AddOp"));
130 SubExpr_10 = chainl1(lpeg.V("SubExpr_11"), lpeg.V("MulOp"));
131 SubExpr_11 = lpeg.V("UnOp") * lpeg.V("SubExpr_11") +
132 lpeg.V("SubExpr_12");
133 SubExpr_12 = lpeg.V("SimpleExp") * (lpeg.V("PowOp") * lpeg.V("SubExpr_11"))^-1;
134 SimpleExp = tllexer.token(tllexer.Number) +
135 tllexer.token(tllexer.String) +
136 tllexer.kw("nil") +
137 tllexer.kw("false") +
138 tllexer.kw("true") +
139 tllexer.symb("...") +
140 lpeg.V("FunctionDef") +
141 lpeg.V("Constructor") +
142 lpeg.V("SuffixedExp");
143 SuffixedExp = lpeg.V("PrimaryExp") * (
144 (tllexer.symb(".") * tllexer.token(tllexer.Name)) / "index" +
145 (tllexer.symb("[") * lpeg.V("Expr") * tllexer.symb("]")) / "index" +
146 (tllexer.symb(":") * tllexer.token(tllexer.Name) * lpeg.V("FuncArgs")) / "call" +
147 lpeg.V("FuncArgs") / "call")^0 / function (...) local l = {...}; return l[#l] end;
148 PrimaryExp = lpeg.V("Var") / "var" +
149 tllexer.symb("(") * lpeg.V("Expr") * tllexer.symb(")");
150 Block = lpeg.V("StatList") * lpeg.V("RetStat")^-1;
151 IfStat = tllexer.kw("if") * lpeg.V("Expr") * tllexer.kw("then") * lpeg.V("Block") *
152 (tllexer.kw("elseif") * lpeg.V("Expr") * tllexer.kw("then") * lpeg.V("Block"))^0 *
153 (tllexer.kw("else") * lpeg.V("Block"))^-1 *
154 tllexer.kw("end");
155 WhileStat = tllexer.kw("while") * lpeg.V("Expr") *
156 tllexer.kw("do") * lpeg.V("Block") * tllexer.kw("end");
157 DoStat = tllexer.kw("do") * lpeg.V("Block") * tllexer.kw("end");
158 ForBody = tllexer.kw("do") * lpeg.V("Block");
159 ForNum = lpeg.V("Id") * tllexer.symb("=") * lpeg.V("Expr") * tllexer.symb(",") *
160 lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^-1 *
161 lpeg.V("ForBody");
162 ForGen = lpeg.V("NameList") * tllexer.kw("in") *
163 lpeg.V("ExpList") * lpeg.V("ForBody");
164 ForStat = tllexer.kw("for") * (lpeg.V("ForNum") + lpeg.V("ForGen")) * tllexer.kw("end");
165 RepeatStat = tllexer.kw("repeat") * lpeg.V("Block") *
166 tllexer.kw("until") * lpeg.V("Expr");
167 FuncName = lpeg.V("Id") * (tllexer.symb(".") *
168 (tllexer.token(tllexer.Name)))^0 *
169 (tllexer.symb(":") * (tllexer.token(tllexer.Name)))^-1;
170 ParList = lpeg.V("NameList") * (tllexer.symb(",") * lpeg.V("TypedVarArg"))^-1 +
171 lpeg.V("TypedVarArg");
172 TypedVarArg = tllexer.symb("...") * (tllexer.symb(":") * lpeg.V("Type"))^-1;
173 FuncBody = tllexer.symb("(") * lpeg.V("ParList")^-1 * tllexer.symb(")") *
174 (tllexer.symb(":") * lpeg.V("RetType"))^-1 *
175 lpeg.V("Block") * tllexer.kw("end");
176 FuncStat = tllexer.kw("const")^-1 *
177 tllexer.kw("function") * lpeg.V("FuncName") * lpeg.V("FuncBody");
178 LocalFunc = tllexer.kw("function") *
179 lpeg.V("Id") * lpeg.V("FuncBody");
180 LocalAssign = lpeg.V("NameList") *
181 ((tllexer.symb("=") * lpeg.V("ExpList")))^-1;
182 LocalStat = tllexer.kw("local") *
183 (lpeg.V("LocalTypeDec") + lpeg.V("LocalFunc") + lpeg.V("LocalAssign"));
184 LabelStat = tllexer.symb("::") * tllexer.token(tllexer.Name) * tllexer.symb("::");
185 BreakStat = tllexer.kw("break");
186 GoToStat = tllexer.kw("goto") * tllexer.token(tllexer.Name);
187 RetStat = tllexer.kw("return") *
188 (lpeg.V("Expr") * (tllexer.symb(",") * lpeg.V("Expr"))^0)^-1 *
189 tllexer.symb(";")^-1;
190 TypeDecStat = lpeg.V("Interface");
191 LocalTypeDec = lpeg.V("TypeDecStat");
192 LVar = (tllexer.kw("const") * lpeg.V("SuffixedExp")) +
193 lpeg.V("SuffixedExp");
194 ExprStat = lpeg.Cmt(lpeg.V("LVar") * lpeg.V("Assignment"),
195 function (s, i, ...)
196 local l = {...}
197 local i = 1
198 while l[i] ~= "=" do
199 local se = l[i]
200 if se ~= "var" and se ~= "index" then return false end
201 i = i + 1
202 end
203 return true
204 end) +
205 lpeg.Cmt(lpeg.V("SuffixedExp"),
206 function (s, i, se)
207 if se ~= "call" then return false end
208 return true
209 end);
210 Assignment = ((tllexer.symb(",") * lpeg.V("LVar"))^1)^-1 * (tllexer.symb("=") / "=") * lpeg.V("ExpList");
211 Stat = lpeg.V("IfStat") + lpeg.V("WhileStat") + lpeg.V("DoStat") + lpeg.V("ForStat") +
212 lpeg.V("RepeatStat") + lpeg.V("FuncStat") + lpeg.V("LocalStat") +
213 lpeg.V("LabelStat") + lpeg.V("BreakStat") + lpeg.V("GoToStat") +
214 lpeg.V("TypeDecStat") + lpeg.V("ExprStat");
215}
216
217function tlparser.parse (subject, filename, strict, integer)
218 local errorinfo = {}
219 lpeg.setmaxstack(1000)
220 local ast, label, _ = lpeg.match(G, subject, nil, errorinfo, strict, integer)
221 if not ast then
222 return nil
223 else
224 return true
225 end
226end
227
228return tlparser