diff options
author | Andre Murbach Maidl <andremm@gmail.com> | 2015-10-04 20:10:05 -0300 |
---|---|---|
committer | Andre Murbach Maidl <andremm@gmail.com> | 2015-10-04 20:10:05 -0300 |
commit | 781fd9653ed0a89dd8f3d8ccfab63e249f1edb07 (patch) | |
tree | 298232c6c2585b49bc1c03e89aa9428d95d9f403 | |
parent | 8ac31b94b88227222b189c447aeea1b4131eed18 (diff) | |
download | lpeglabel-781fd9653ed0a89dd8f3d8ccfab63e249f1edb07.tar.gz lpeglabel-781fd9653ed0a89dd8f3d8ccfab63e249f1edb07.tar.bz2 lpeglabel-781fd9653ed0a89dd8f3d8ccfab63e249f1edb07.zip |
Adding Typed Lua parser
-rw-r--r-- | examples/typedlua/tllexer.lua | 80 | ||||
-rw-r--r-- | examples/typedlua/tlp.lua | 18 | ||||
-rw-r--r-- | examples/typedlua/tlparser.lua | 228 |
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 @@ | |||
1 | local tllexer = {} | ||
2 | |||
3 | local lpeg = require "lpeglabel" | ||
4 | lpeg.locale(lpeg) | ||
5 | |||
6 | local function setffp (s, i, t) | ||
7 | if not t.ffp or i > t.ffp then | ||
8 | t.ffp = i | ||
9 | end | ||
10 | return false | ||
11 | end | ||
12 | |||
13 | local function updateffp () | ||
14 | return lpeg.Cmt(lpeg.Carg(1), setffp) | ||
15 | end | ||
16 | |||
17 | tllexer.Shebang = lpeg.P("#") * (lpeg.P(1) - lpeg.P("\n"))^0 * lpeg.P("\n") | ||
18 | |||
19 | local Space = lpeg.space^1 | ||
20 | |||
21 | local Equals = lpeg.P("=")^0 | ||
22 | local Open = "[" * lpeg.Cg(Equals, "init") * "[" * lpeg.P("\n")^-1 | ||
23 | local Close = "]" * lpeg.C(Equals) * "]" | ||
24 | local CloseEQ = lpeg.Cmt(Close * lpeg.Cb("init"), | ||
25 | function (s, i, a, b) return a == b end) | ||
26 | |||
27 | local LongString = Open * (lpeg.P(1) - CloseEQ)^0 * Close / | ||
28 | function (s, o) return s end | ||
29 | |||
30 | local Comment = lpeg.P("--") * LongString / | ||
31 | function () return end + | ||
32 | lpeg.P("--") * (lpeg.P(1) - lpeg.P("\n"))^0 | ||
33 | |||
34 | tllexer.Skip = (Space + Comment)^0 | ||
35 | |||
36 | local idStart = lpeg.alpha + lpeg.P("_") | ||
37 | local idRest = lpeg.alnum + lpeg.P("_") | ||
38 | |||
39 | local 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 | |||
44 | tllexer.Reserved = Keywords * -idRest | ||
45 | |||
46 | local Identifier = idStart * idRest^0 | ||
47 | |||
48 | tllexer.Name = -tllexer.Reserved * Identifier * -idRest | ||
49 | |||
50 | function tllexer.token (pat) | ||
51 | return pat * tllexer.Skip + updateffp() * lpeg.P(false) | ||
52 | end | ||
53 | |||
54 | function tllexer.symb (str) | ||
55 | return tllexer.token(lpeg.P(str)) | ||
56 | end | ||
57 | |||
58 | function tllexer.kw (str) | ||
59 | return tllexer.token(lpeg.P(str) * -idRest) | ||
60 | end | ||
61 | |||
62 | local Hex = (lpeg.P("0x") + lpeg.P("0X")) * lpeg.xdigit^1 | ||
63 | local Expo = lpeg.S("eE") * lpeg.S("+-")^-1 * lpeg.digit^1 | ||
64 | local Float = (((lpeg.digit^1 * lpeg.P(".") * lpeg.digit^0) + | ||
65 | (lpeg.P(".") * lpeg.digit^1)) * Expo^-1) + | ||
66 | (lpeg.digit^1 * Expo) | ||
67 | local Int = lpeg.digit^1 | ||
68 | |||
69 | tllexer.Number = Hex + Float + Int | ||
70 | |||
71 | local 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 | |||
78 | tllexer.String = LongString + ShortString | ||
79 | |||
80 | return 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 @@ | |||
1 | local tlparser = require "tlparser" | ||
2 | |||
3 | local function getcontents(filename) | ||
4 | file = assert(io.open(filename, "r")) | ||
5 | contents = file:read("*a") | ||
6 | file:close() | ||
7 | return contents | ||
8 | end | ||
9 | |||
10 | if #arg ~= 1 then | ||
11 | print ("Usage: lua tlp.lua <file>") | ||
12 | os.exit(1) | ||
13 | end | ||
14 | |||
15 | local filename = arg[1] | ||
16 | local subject = getcontents(filename) | ||
17 | |||
18 | print(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 @@ | |||
1 | local tlparser = {} | ||
2 | |||
3 | local lpeg = require "lpeglabel" | ||
4 | lpeg.locale(lpeg) | ||
5 | |||
6 | local tllexer = require "tllexer" | ||
7 | |||
8 | local function chainl1 (pat, sep) | ||
9 | return pat * (sep * pat)^0 | ||
10 | end | ||
11 | |||
12 | local 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 | |||
217 | function 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 | ||
226 | end | ||
227 | |||
228 | return tlparser | ||