From f90c67eefa15bd994dd099c5bc4c90577be9816f Mon Sep 17 00:00:00 2001 From: Andre Murbach Maidl Date: Sun, 3 Aug 2014 19:53:19 -0300 Subject: [PATCH] Updating the parser to support the syntax of Lua 5.3 --- README.md | 4 +- lua-parser/parser.lua | 38 ++++++++++++----- test.lua | 97 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 116 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index d6998bf..de416d4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ lua-parser ========== -This is a Lua 5.2 parser written with LPeg that generates an AST in +This is a Lua 5.3 parser written with LPeg that generates an AST in the format specified by [Metalua](https://github.com/fab13n/metalua-parser). The parser also implements an error reporting technique that is based on tracking the farthest failure position. @@ -77,5 +77,5 @@ Usage $ lua parse.lua "for i=1, 10 do print(i) " exemplo1.lua:1:24: syntax error, unexpected 'EOF', expecting 'end', 'return', 'Name', 'goto', 'break', '::', 'local', 'function', 'repeat', - 'for', 'do', 'while', 'if', ';', '=', ',', 'String', '{', '(', ':', '[', '.' + 'for', 'do', 'while', 'if', ';', '=', ',', 'String', '{', '(', ':', '[', '.' diff --git a/lua-parser/parser.lua b/lua-parser/parser.lua index 0373213..80a19f8 100644 --- a/lua-parser/parser.lua +++ b/lua-parser/parser.lua @@ -42,8 +42,9 @@ apply: lhs: `Id{ } | `Index{ expr expr } -opid: 'add' | 'sub' | 'mul' | 'div' | 'mod' | 'pow' | 'concat' - | 'eq' | 'lt' | 'le' | 'and' | 'or' | 'not' | 'unm' | 'len' +opid: 'add' | 'sub' | 'mul' | 'div' | 'idiv' | 'mod' | 'pow' | 'concat' + | 'band' | 'bor' | 'bxor' | 'shl' | 'shr' | 'eq' | 'lt' | 'le' + | 'and' | 'or' | 'not' | 'unm' | 'len' | 'bnot' ]] local parser = {} @@ -152,9 +153,15 @@ local function binaryop (e1, op, e2) op == "sub" or op == "mul" or op == "div" or + op == "idiv" or op == "mod" or op == "pow" or op == "concat" or + op == "band" or + op == "bor" or + op == "bxor" or + op == "shl" or + op == "shr" or op == "eq" or op == "lt" or op == "le" or @@ -227,13 +234,17 @@ local G = { V"Lua", SubExpr_1 = chainl1(V"SubExpr_2", V"OrOp"); SubExpr_2 = chainl1(V"SubExpr_3", V"AndOp"); SubExpr_3 = chainl1(V"SubExpr_4", V"RelOp"); - SubExpr_4 = V"SubExpr_5" * V"ConOp" * V"SubExpr_4" / binaryop + - V"SubExpr_5"; - SubExpr_5 = chainl1(V"SubExpr_6", V"AddOp"); - SubExpr_6 = chainl1(V"SubExpr_7", V"MulOp"); - SubExpr_7 = V"UnOp" * V"SubExpr_7" / unaryop + - V"SubExpr_8"; - SubExpr_8 = V"SimpleExp" * (V"PowOp" * V"SubExpr_7")^-1 / binaryop; + SubExpr_4 = chainl1(V"SubExpr_5", V"BOrOp"); + SubExpr_5 = chainl1(V"SubExpr_6", V"BXorOp"); + SubExpr_6 = chainl1(V"SubExpr_7", V"BAndOp"); + SubExpr_7 = chainl1(V"SubExpr_8", V"ShiftOp"); + SubExpr_8 = V"SubExpr_9" * V"ConOp" * V"SubExpr_8" / binaryop + + V"SubExpr_9"; + SubExpr_9 = chainl1(V"SubExpr_10", V"AddOp"); + SubExpr_10 = chainl1(V"SubExpr_11", V"MulOp"); + SubExpr_11 = V"UnOp" * V"SubExpr_11" / unaryop + + V"SubExpr_12"; + SubExpr_12 = V"SimpleExp" * (V"PowOp" * V"SubExpr_11")^-1 / binaryop; SimpleExp = taggedCap("Number", token(V"Number", "Number")) + taggedCap("String", token(V"String", "String")) + taggedCap("Nil", kw("nil")) + @@ -405,15 +416,22 @@ local G = { V"Lua", symb(">=") / "ge" + symb("<") / "lt" + symb(">") / "gt"; + BOrOp = symb("|") / "bor"; + BXorOp = symb("~") / "bxor"; + BAndOp = symb("&") / "band"; + ShiftOp = symb("<<") / "shl" + + symb(">>") / "shr"; ConOp = symb("..") / "concat"; AddOp = symb("+") / "add" + symb("-") / "sub"; MulOp = symb("*") / "mul" + + symb("//") / "idiv" + symb("/") / "div" + symb("%") / "mod"; UnOp = kw("not") / "not" + symb("-") / "unm" + - symb("#") / "len"; + symb("#") / "len" + + symb("~") / "bnot"; PowOp = symb("^") / "pow"; Shebang = P"#" * (P(1) - P"\n")^0 * P"\n"; -- for error reporting diff --git a/test.lua b/test.lua index a92dd58..3267e77 100755 --- a/test.lua +++ b/test.lua @@ -377,7 +377,7 @@ long string ]==] ]=] e = [=[ -test.lua:5:7: syntax error, unexpected '[', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not' +test.lua:5:7: syntax error, unexpected '[', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' ]=] r = parse(s) @@ -393,7 +393,7 @@ ss6 = "testing unfinished string -- short string test end ]=] e = [=[ -test.lua:3:7: syntax error, unexpected '"', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not' +test.lua:3:7: syntax error, unexpected '"', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' ]=] r = parse(s) @@ -488,6 +488,16 @@ e = [=[ r = parse(s) assert(r == e) +s = [=[ +q, r, f = 3//2, 3%2, 3/2 +]=] +e = [=[ +{ `Set{ { `Id "q", `Id "r", `Id "f" }, { `Op{ "idiv", `Number "3", `Number "2" }, `Op{ "mod", `Number "3", `Number "2" }, `Op{ "div", `Number "3", `Number "2" } } } } +]=] + +r = parse(s) +assert(r == e) + -- assignments s = [=[ @@ -551,6 +561,28 @@ e = [=[ r = parse(s) assert(r == e) +-- bitwise expressions + +s = [=[ +b = 1 & 0 | 1 ~ 1 +]=] +e = [=[ +{ `Set{ { `Id "b" }, { `Op{ "bor", `Op{ "band", `Number "1", `Number "0" }, `Op{ "bxor", `Number "1", `Number "1" } } } } } +]=] + +r = parse(s) +assert(r == e) + +s = [=[ +b = 1 & 0 | 1 >> 1 ~ 1 +]=] +e = [=[ +{ `Set{ { `Id "b" }, { `Op{ "bor", `Op{ "band", `Number "1", `Number "0" }, `Op{ "bxor", `Op{ "shr", `Number "1", `Number "1" }, `Number "1" } } } } } +]=] + +r = parse(s) +assert(r == e) + -- break s = [=[ @@ -1272,6 +1304,50 @@ test.lua:2:1: syntax error, unexpected 'EOF', expecting 'end', 'return', '(', 'N r = parse(s) assert(r == e) +-- arithmetic expressions + +s = [=[ +a = 3 / / 2 +]=] +e = [=[ +test.lua:1:9: syntax error, unexpected '/', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' +]=] + +r = parse(s) +assert(r == e) + +-- bitwise expressions + +s = [=[ +b = 1 && 1 +]=] +e = [=[ +test.lua:1:8: syntax error, unexpected '&', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' +]=] + +r = parse(s) +assert(r == e) + +s = [=[ +b = 1 <> 0 +]=] +e = [=[ +test.lua:1:8: syntax error, unexpected '>', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' +]=] + +r = parse(s) +assert(r == e) + +s = [=[ +b = 1 < < 0 +]=] +e = [=[ +test.lua:1:9: syntax error, unexpected '<', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' +]=] + +r = parse(s) +assert(r == e) + -- break s = [=[ @@ -1308,14 +1384,13 @@ test.lua:3:1: syntax error, not inside a loop r = parse(s) assert(r == e) - -- concatenation expressions s = [=[ concat2 = 2^3..1 ]=] e = [=[ -test.lua:1:15: syntax error, unexpected '.1', expecting 'return', '(', 'Name', 'goto', 'break', '::', 'local', 'function', 'repeat', 'for', 'do', 'while', 'if', ';', ',', 'or', 'and', '>', '<', '>=', '<=', '==', '~=', '..', '-', '+', '%', '/', '*', '^' +test.lua:1:15: syntax error, unexpected '.1', expecting 'return', '(', 'Name', 'goto', 'break', '::', 'local', 'function', 'repeat', 'for', 'do', 'while', 'if', ';', ',', 'or', 'and', '>', '<', '>=', '<=', '==', '~=', '|', '~', '&', '>>', '<<', '..', '-', '+', '%', '/', '//', '*', '^' ]=] r = parse(s) @@ -1349,7 +1424,7 @@ s = [=[ for i=1,10, do end ]=] e = [=[ -test.lua:1:13: syntax error, unexpected 'do', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not' +test.lua:1:13: syntax error, unexpected 'do', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' ]=] r = parse(s) @@ -1404,7 +1479,7 @@ s = [=[ goto label ]=] e = [=[ -test.lua:2:1: syntax error, unexpected 'goto', expecting ';', '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not' +test.lua:2:1: syntax error, unexpected 'goto', expecting ';', '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' ]=] r = parse(s) @@ -1474,7 +1549,7 @@ elseif end ]=] e = [=[ -test.lua:7:1: syntax error, unexpected 'end', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not' +test.lua:7:1: syntax error, unexpected 'end', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' ]=] r = parse(s) @@ -1521,7 +1596,7 @@ s = [=[ local a = ]=] e = [=[ -test.lua:2:1: syntax error, unexpected 'EOF', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not' +test.lua:2:1: syntax error, unexpected 'EOF', expecting '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' ]=] r = parse(s) @@ -1592,7 +1667,7 @@ return 1; return 1,1-2*3+4,"alo"; ]=] e = [=[ -test.lua:2:1: syntax error, unexpected 'return', expecting ';', '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not' +test.lua:2:1: syntax error, unexpected 'return', expecting ';', '(', 'Name', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not' ]=] r = parse(s) @@ -1604,7 +1679,7 @@ s = [=[ t = { , } ]=] e = [=[ -test.lua:1:7: syntax error, unexpected ',', expecting '}', '(', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '#', '-', 'not', 'Name', '[' +test.lua:1:7: syntax error, unexpected ',', expecting '}', '(', '{', 'function', '...', 'true', 'false', 'nil', 'String', 'Number', '~', '#', '-', 'not', 'Name', '[' ]=] r = parse(s) @@ -1671,7 +1746,7 @@ while (i < 10) end ]=] e = [=[ -test.lua:3:3: syntax error, unexpected 'i', expecting 'do', 'or', 'and', '>', '<', '>=', '<=', '==', '~=', '..', '-', '+', '%', '/', '*', '^', 'String', '{', '(', ':', '[', '.' +test.lua:3:3: syntax error, unexpected 'i', expecting 'do', 'or', 'and', '>', '<', '>=', '<=', '==', '~=', '|', '~', '&', '>>', '<<', '..', '-', '+', '%', '/', '//', '*', '^', 'String', '{', '(', ':', '[', '.' ]=] r = parse(s)