├── .travis.yml ├── LICENSE ├── README.md ├── lua-parser ├── parser.lua ├── pp.lua ├── scope.lua └── validator.lua ├── rockspecs ├── lua-parser-0.1.1-1.rockspec ├── lua-parser-1.0.0-1.rockspec ├── lua-parser-1.0.1-1.rockspec ├── lua-parser-1.0.2-1.rockspec ├── lua-parser-1.0.3-1.rockspec └── lua-parser-1.0.4-1.rockspec └── test.lua /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: false 3 | 4 | env: 5 | - LUA="lua=5.1" 6 | - LUA="lua=5.2" 7 | - LUA="lua=5.3" 8 | - LUA="luajit=2.0" 9 | - LUA="luajit=2.1" 10 | 11 | before_install: 12 | - pip install hererocks 13 | - hererocks lua_install -r^ --$LUA 14 | - export PATH=$PATH:$PWD/lua_install/bin 15 | # - luarocks install luacheck 16 | - luarocks install luacov 17 | - luarocks install lpeglabel 18 | # - luarocks install luacov-coveralls 19 | 20 | install: 21 | - luarocks make 22 | 23 | script: 24 | # Don't fail due to luacheck 25 | #- luacheck --std max lua-parser test.lua || true 26 | - lua -lluacov test.lua 27 | 28 | #after_success: 29 | # - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Andre Murbach Maidl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lua-parser 2 | ========== 3 | [![Build Status](https://travis-ci.org/andremm/lua-parser.svg?branch=master)](https://travis-ci.org/andremm/lua-parser) 4 | 5 | This is a Lua 5.3 parser written with [LPegLabel](https://github.com/sqmedeiros/lpeglabel) that 6 | generates an AST in a format that is similar to the one specified by [Metalua](https://github.com/fab13n/metalua-parser). 7 | The parser uses LPegLabel to provide more specific error messages. 8 | 9 | Requirements 10 | ------------ 11 | 12 | lua >= 5.1 13 | lpeglabel >= 1.6.0 14 | 15 | API 16 | --- 17 | 18 | The package `lua-parser` has two modules: `lua-parser.parser` 19 | and `lua-parser.pp`. 20 | 21 | The module `lua-parser.parser` implements the function `parser.parse`: 22 | 23 | * `parser.parse (subject, filename)` 24 | 25 | Both subject and filename should be strings. 26 | It tries to parse subject and returns the AST in case of success. 27 | It returns **nil** plus an error message in case of error. 28 | In case of error, the parser uses the string filename to build an 29 | error message. 30 | 31 | The module `lua-parser.pp` implements a pretty printer to the AST and 32 | a dump function: 33 | 34 | * `pp.tostring (ast)` 35 | 36 | It converts the AST to a string and returns this string. 37 | 38 | * `pp.print (ast)` 39 | 40 | It converts the AST to a string and prints this string. 41 | 42 | * `pp.dump (ast[, i])` 43 | 44 | It dumps the AST to the screen. 45 | The parameter **i** sets the indentation level. 46 | 47 | AST format 48 | ---------- 49 | 50 | block: { stat* } 51 | 52 | stat: 53 | `Do{ stat* } 54 | | `Set{ {lhs+} {expr+} } -- lhs1, lhs2... = e1, e2... 55 | | `While{ expr block } -- while e do b end 56 | | `Repeat{ block expr } -- repeat b until e 57 | | `If{ (expr block)+ block? } -- if e1 then b1 [elseif e2 then b2] ... [else bn] end 58 | | `Fornum{ ident expr expr expr? block } -- for ident = e, e[, e] do b end 59 | | `Forin{ {ident+} {expr+} block } -- for i1, i2... in e1, e2... do b end 60 | | `Local{ {ident+} {expr+}? } -- local i1, i2... = e1, e2... 61 | | `Localrec{ ident expr } -- only used for 'local function' 62 | | `Goto{ } -- goto str 63 | | `Label{ } -- ::str:: 64 | | `Return{ } -- return e1, e2... 65 | | `Break -- break 66 | | apply 67 | 68 | expr: 69 | `Nil 70 | | `Dots 71 | | `Boolean{ } 72 | | `Number{ } 73 | | `String{ } 74 | | `Function{ { `Id{ }* `Dots? } block } 75 | | `Table{ ( `Pair{ expr expr } | expr )* } 76 | | `Op{ opid expr expr? } 77 | | `Paren{ expr } -- significant to cut multiple values returns 78 | | apply 79 | | lhs 80 | 81 | apply: 82 | `Call{ expr expr* } 83 | | `Invoke{ expr `String{ } expr* } 84 | 85 | lhs: `Id{ } | `Index{ expr expr } 86 | 87 | opid: -- includes additional operators from Lua 5.3 and all relational operators 88 | 'add' | 'sub' | 'mul' | 'div' 89 | | 'idiv' | 'mod' | 'pow' | 'concat' 90 | | 'band' | 'bor' | 'bxor' | 'shl' | 'shr' 91 | | 'eq' | 'ne' | 'lt' | 'gt' | 'le' | 'ge' 92 | | 'and' | 'or' | 'unm' | 'len' | 'bnot' | 'not' 93 | 94 | 95 | Usage 96 | -------- 97 | 98 | **Code example for parsing a string:** 99 | 100 | 101 | local parser = require "lua-parser.parser" 102 | local pp = require "lua-parser.pp" 103 | 104 | if #arg ~= 1 then 105 | print("Usage: parse.lua ") 106 | os.exit(1) 107 | end 108 | 109 | local ast, error_msg = parser.parse(arg[1], "example.lua") 110 | if not ast then 111 | print(error_msg) 112 | os.exit(1) 113 | end 114 | 115 | pp.print(ast) 116 | os.exit(0) 117 | 118 | **Running the above code example using a string without syntax error:** 119 | 120 | $ lua parse.lua "for i=1, 10 do print(i) end" 121 | { `Fornum{ `Id "i", `Number "1", `Number "10", { `Call{ `Id "print", `Id "i" } } } } 122 | 123 | **Running the above code example using a string with syntax error:** 124 | 125 | $ lua parse.lua "for i=1, 10 do print(i) " 126 | example.lua:1:24: syntax error, expected 'end' to close the for loop 127 | 128 | -------------------------------------------------------------------------------- /lua-parser/parser.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | This module implements a parser for Lua 5.3 with LPeg, 3 | and generates an Abstract Syntax Tree that is similar to the one generated by Metalua. 4 | For more information about Metalua, please, visit: 5 | https://github.com/fab13n/metalua-parser 6 | 7 | block: { stat* } 8 | 9 | stat: 10 | `Do{ stat* } 11 | | `Set{ {lhs+} {expr+} } -- lhs1, lhs2... = e1, e2... 12 | | `While{ expr block } -- while e do b end 13 | | `Repeat{ block expr } -- repeat b until e 14 | | `If{ (expr block)+ block? } -- if e1 then b1 [elseif e2 then b2] ... [else bn] end 15 | | `Fornum{ ident expr expr expr? block } -- for ident = e, e[, e] do b end 16 | | `Forin{ {ident+} {expr+} block } -- for i1, i2... in e1, e2... do b end 17 | | `Local{ {ident+} {expr+}? } -- local i1, i2... = e1, e2... 18 | | `Localrec{ ident expr } -- only used for 'local function' 19 | | `Goto{ } -- goto str 20 | | `Label{ } -- ::str:: 21 | | `Return{ } -- return e1, e2... 22 | | `Break -- break 23 | | apply 24 | 25 | expr: 26 | `Nil 27 | | `Dots 28 | | `Boolean{ } 29 | | `Number{ } 30 | | `String{ } 31 | | `Function{ { `Id{ }* `Dots? } block } 32 | | `Table{ ( `Pair{ expr expr } | expr )* } 33 | | `Op{ opid expr expr? } 34 | | `Paren{ expr } -- significant to cut multiple values returns 35 | | apply 36 | | lhs 37 | 38 | apply: 39 | `Call{ expr expr* } 40 | | `Invoke{ expr `String{ } expr* } 41 | 42 | lhs: `Id{ } | `Index{ expr expr } 43 | 44 | opid: -- includes additional operators from Lua 5.3 and all relational operators 45 | 'add' | 'sub' | 'mul' | 'div' 46 | | 'idiv' | 'mod' | 'pow' | 'concat' 47 | | 'band' | 'bor' | 'bxor' | 'shl' | 'shr' 48 | | 'eq' | 'ne' | 'lt' | 'gt' | 'le' | 'ge' 49 | | 'and' | 'or' | 'unm' | 'len' | 'bnot' | 'not' 50 | ]] 51 | 52 | local lpeg = require "lpeglabel" 53 | 54 | lpeg.locale(lpeg) 55 | 56 | local P, S, V = lpeg.P, lpeg.S, lpeg.V 57 | local C, Carg, Cb, Cc = lpeg.C, lpeg.Carg, lpeg.Cb, lpeg.Cc 58 | local Cf, Cg, Cmt, Cp, Cs, Ct = lpeg.Cf, lpeg.Cg, lpeg.Cmt, lpeg.Cp, lpeg.Cs, lpeg.Ct 59 | local Lc, T = lpeg.Lc, lpeg.T 60 | 61 | local alpha, digit, alnum = lpeg.alpha, lpeg.digit, lpeg.alnum 62 | local xdigit = lpeg.xdigit 63 | local space = lpeg.space 64 | 65 | 66 | -- error message auxiliary functions 67 | 68 | local labels = { 69 | { "ErrExtra", "unexpected character(s), expected EOF" }, 70 | { "ErrInvalidStat", "unexpected token, invalid start of statement" }, 71 | 72 | { "ErrEndIf", "expected 'end' to close the if statement" }, 73 | { "ErrExprIf", "expected a condition after 'if'" }, 74 | { "ErrThenIf", "expected 'then' after the condition" }, 75 | { "ErrExprEIf", "expected a condition after 'elseif'" }, 76 | { "ErrThenEIf", "expected 'then' after the condition" }, 77 | 78 | { "ErrEndDo", "expected 'end' to close the do block" }, 79 | { "ErrExprWhile", "expected a condition after 'while'" }, 80 | { "ErrDoWhile", "expected 'do' after the condition" }, 81 | { "ErrEndWhile", "expected 'end' to close the while loop" }, 82 | { "ErrUntilRep", "expected 'until' at the end of the repeat loop" }, 83 | { "ErrExprRep", "expected a conditions after 'until'" }, 84 | 85 | { "ErrForRange", "expected a numeric or generic range after 'for'" }, 86 | { "ErrEndFor", "expected 'end' to close the for loop" }, 87 | { "ErrExprFor1", "expected a starting expression for the numeric range" }, 88 | { "ErrCommaFor", "expected ',' to split the start and end of the range" }, 89 | { "ErrExprFor2", "expected an ending expression for the numeric range" }, 90 | { "ErrExprFor3", "expected a step expression for the numeric range after ','" }, 91 | { "ErrInFor", "expected '=' or 'in' after the variable(s)" }, 92 | { "ErrEListFor", "expected one or more expressions after 'in'" }, 93 | { "ErrDoFor", "expected 'do' after the range of the for loop" }, 94 | 95 | { "ErrDefLocal", "expected a function definition or assignment after local" }, 96 | { "ErrNameLFunc", "expected a function name after 'function'" }, 97 | { "ErrEListLAssign", "expected one or more expressions after '='" }, 98 | { "ErrEListAssign", "expected one or more expressions after '='" }, 99 | 100 | { "ErrFuncName", "expected a function name after 'function'" }, 101 | { "ErrNameFunc1", "expected a function name after '.'" }, 102 | { "ErrNameFunc2", "expected a method name after ':'" }, 103 | { "ErrOParenPList", "expected '(' for the parameter list" }, 104 | { "ErrCParenPList", "expected ')' to close the parameter list" }, 105 | { "ErrEndFunc", "expected 'end' to close the function body" }, 106 | { "ErrParList", "expected a variable name or '...' after ','" }, 107 | 108 | { "ErrLabel", "expected a label name after '::'" }, 109 | { "ErrCloseLabel", "expected '::' after the label" }, 110 | { "ErrGoto", "expected a label after 'goto'" }, 111 | { "ErrRetList", "expected an expression after ',' in the return statement" }, 112 | 113 | { "ErrVarList", "expected a variable name after ','" }, 114 | { "ErrExprList", "expected an expression after ','" }, 115 | 116 | { "ErrOrExpr", "expected an expression after 'or'" }, 117 | { "ErrAndExpr", "expected an expression after 'and'" }, 118 | { "ErrRelExpr", "expected an expression after the relational operator" }, 119 | { "ErrBOrExpr", "expected an expression after '|'" }, 120 | { "ErrBXorExpr", "expected an expression after '~'" }, 121 | { "ErrBAndExpr", "expected an expression after '&'" }, 122 | { "ErrShiftExpr", "expected an expression after the bit shift" }, 123 | { "ErrConcatExpr", "expected an expression after '..'" }, 124 | { "ErrAddExpr", "expected an expression after the additive operator" }, 125 | { "ErrMulExpr", "expected an expression after the multiplicative operator" }, 126 | { "ErrUnaryExpr", "expected an expression after the unary operator" }, 127 | { "ErrPowExpr", "expected an expression after '^'" }, 128 | 129 | { "ErrExprParen", "expected an expression after '('" }, 130 | { "ErrCParenExpr", "expected ')' to close the expression" }, 131 | { "ErrNameIndex", "expected a field name after '.'" }, 132 | { "ErrExprIndex", "expected an expression after '['" }, 133 | { "ErrCBracketIndex", "expected ']' to close the indexing expression" }, 134 | { "ErrNameMeth", "expected a method name after ':'" }, 135 | { "ErrMethArgs", "expected some arguments for the method call (or '()')" }, 136 | 137 | { "ErrArgList", "expected an expression after ',' in the argument list" }, 138 | { "ErrCParenArgs", "expected ')' to close the argument list" }, 139 | 140 | { "ErrCBraceTable", "expected '}' to close the table constructor" }, 141 | { "ErrEqField", "expected '=' after the table key" }, 142 | { "ErrExprField", "expected an expression after '='" }, 143 | { "ErrExprFKey", "expected an expression after '[' for the table key" }, 144 | { "ErrCBracketFKey", "expected ']' to close the table key" }, 145 | 146 | { "ErrDigitHex", "expected one or more hexadecimal digits after '0x'" }, 147 | { "ErrDigitDeci", "expected one or more digits after the decimal point" }, 148 | { "ErrDigitExpo", "expected one or more digits for the exponent" }, 149 | 150 | { "ErrQuote", "unclosed string" }, 151 | { "ErrHexEsc", "expected exactly two hexadecimal digits after '\\x'" }, 152 | { "ErrOBraceUEsc", "expected '{' after '\\u'" }, 153 | { "ErrDigitUEsc", "expected one or more hexadecimal digits for the UTF-8 code point" }, 154 | { "ErrCBraceUEsc", "expected '}' after the code point" }, 155 | { "ErrEscSeq", "invalid escape sequence" }, 156 | { "ErrCloseLStr", "unclosed long string" }, 157 | } 158 | 159 | local function throw(label) 160 | label = "Err" .. label 161 | for i, labelinfo in ipairs(labels) do 162 | if labelinfo[1] == label then 163 | return T(i) 164 | end 165 | end 166 | 167 | error("Label not found: " .. label) 168 | end 169 | 170 | local function expect (patt, label) 171 | return patt + throw(label) 172 | end 173 | 174 | 175 | -- regular combinators and auxiliary functions 176 | 177 | local function token (patt) 178 | return patt * V"Skip" 179 | end 180 | 181 | local function sym (str) 182 | return token(P(str)) 183 | end 184 | 185 | local function kw (str) 186 | return token(P(str) * -V"IdRest") 187 | end 188 | 189 | local function dec(n) 190 | return n - 1 191 | end 192 | 193 | local function tagC (tag, patt) 194 | return Ct(Cg(Cp(), "pos") * Cg(Cc(tag), "tag") * patt * Cg(Cp() / dec, "end_pos")) 195 | end 196 | 197 | local function unaryOp (op, e) 198 | return { tag = "Op", pos = e.pos, end_pos = e.end_pos, [1] = op, [2] = e } 199 | end 200 | 201 | local function binaryOp (e1, op, e2) 202 | if not op then 203 | return e1 204 | else 205 | return { tag = "Op", pos = e1.pos, end_pos = e2.end_pos, [1] = op, [2] = e1, [3] = e2 } 206 | end 207 | end 208 | 209 | local function sepBy (patt, sep, label) 210 | if label then 211 | return patt * Cg(sep * expect(patt, label))^0 212 | else 213 | return patt * Cg(sep * patt)^0 214 | end 215 | end 216 | 217 | local function cut(s, idx, match) 218 | return idx, match 219 | end 220 | 221 | local function chainOp (patt, sep, label) 222 | return Cmt(Cf(sepBy(patt, sep, label), binaryOp), cut) 223 | end 224 | 225 | local function commaSep (patt, label) 226 | return sepBy(patt, sym(","), label) 227 | end 228 | 229 | local function tagDo (block) 230 | block.tag = "Do" 231 | return block 232 | end 233 | 234 | local function fixFuncStat (func) 235 | if func[1].is_method then table.insert(func[2][1], 1, { tag = "Id", [1] = "self" }) end 236 | func[1] = {func[1]} 237 | func[2] = {func[2]} 238 | return func 239 | end 240 | 241 | local function addDots (params, dots) 242 | if dots then table.insert(params, dots) end 243 | return params 244 | end 245 | 246 | local function insertIndex (t, index) 247 | return { tag = "Index", pos = t.pos, end_pos = index.end_pos, [1] = t, [2] = index } 248 | end 249 | 250 | local function markMethod(t, method) 251 | if method then 252 | return { tag = "Index", pos = t.pos, end_pos = method.end_pos, is_method = true, [1] = t, [2] = method } 253 | end 254 | return t 255 | end 256 | 257 | local function makeIndexOrCall (t1, t2) 258 | if t2.tag == "Call" or t2.tag == "Invoke" then 259 | local t = { tag = t2.tag, pos = t1.pos, end_pos = t2.end_pos, [1] = t1 } 260 | for k, v in ipairs(t2) do 261 | table.insert(t, v) 262 | end 263 | return t 264 | end 265 | return { tag = "Index", pos = t1.pos, end_pos = t2.end_pos, [1] = t1, [2] = t2[1] } 266 | end 267 | 268 | -- grammar 269 | local G = { V"Lua", 270 | Lua = V"Shebang"^-1 * V"Skip" * V"Block" * expect(P(-1), "Extra"); 271 | Shebang = P"#!" * (P(1) - P"\n")^0; 272 | 273 | Block = tagC("Block", V"Stat"^0 * V"RetStat"^-1); 274 | Stat = V"IfStat" + V"DoStat" + V"WhileStat" + V"RepeatStat" + V"ForStat" 275 | + V"LocalStat" + V"FuncStat" + V"BreakStat" + V"LabelStat" + V"GoToStat" 276 | + V"FuncCall" + V"Assignment" + sym(";") + -V"BlockEnd" * throw("InvalidStat"); 277 | BlockEnd = P"return" + "end" + "elseif" + "else" + "until" + -1; 278 | 279 | IfStat = tagC("If", V"IfPart" * V"ElseIfPart"^0 * V"ElsePart"^-1 * expect(kw("end"), "EndIf")); 280 | IfPart = kw("if") * expect(V"Expr", "ExprIf") * expect(kw("then"), "ThenIf") * V"Block"; 281 | ElseIfPart = kw("elseif") * expect(V"Expr", "ExprEIf") * expect(kw("then"), "ThenEIf") * V"Block"; 282 | ElsePart = kw("else") * V"Block"; 283 | 284 | DoStat = kw("do") * V"Block" * expect(kw("end"), "EndDo") / tagDo; 285 | WhileStat = tagC("While", kw("while") * expect(V"Expr", "ExprWhile") * V"WhileBody"); 286 | WhileBody = expect(kw("do"), "DoWhile") * V"Block" * expect(kw("end"), "EndWhile"); 287 | RepeatStat = tagC("Repeat", kw("repeat") * V"Block" * expect(kw("until"), "UntilRep") * expect(V"Expr", "ExprRep")); 288 | 289 | ForStat = kw("for") * expect(V"ForNum" + V"ForIn", "ForRange") * expect(kw("end"), "EndFor"); 290 | ForNum = tagC("Fornum", V"Id" * sym("=") * V"NumRange" * V"ForBody"); 291 | NumRange = expect(V"Expr", "ExprFor1") * expect(sym(","), "CommaFor") *expect(V"Expr", "ExprFor2") 292 | * (sym(",") * expect(V"Expr", "ExprFor3"))^-1; 293 | ForIn = tagC("Forin", V"NameList" * expect(kw("in"), "InFor") * expect(V"ExprList", "EListFor") * V"ForBody"); 294 | ForBody = expect(kw("do"), "DoFor") * V"Block"; 295 | 296 | LocalStat = kw("local") * expect(V"LocalFunc" + V"LocalAssign", "DefLocal"); 297 | LocalFunc = tagC("Localrec", kw("function") * expect(V"Id", "NameLFunc") * V"FuncBody") / fixFuncStat; 298 | LocalAssign = tagC("Local", V"NameList" * (sym("=") * expect(V"ExprList", "EListLAssign") + Ct(Cc()))); 299 | Assignment = tagC("Set", V"VarList" * sym("=") * expect(V"ExprList", "EListAssign")); 300 | 301 | FuncStat = tagC("Set", kw("function") * expect(V"FuncName", "FuncName") * V"FuncBody") / fixFuncStat; 302 | FuncName = Cf(V"Id" * (sym(".") * expect(V"StrId", "NameFunc1"))^0, insertIndex) 303 | * (sym(":") * expect(V"StrId", "NameFunc2"))^-1 / markMethod; 304 | FuncBody = tagC("Function", V"FuncParams" * V"Block" * expect(kw("end"), "EndFunc")); 305 | FuncParams = expect(sym("("), "OParenPList") * V"ParList" * expect(sym(")"), "CParenPList"); 306 | ParList = V"NameList" * (sym(",") * expect(tagC("Dots", sym("...")), "ParList"))^-1 / addDots 307 | + Ct(tagC("Dots", sym("..."))) 308 | + Ct(Cc()); -- Cc({}) generates a bug since the {} would be shared across parses 309 | 310 | LabelStat = tagC("Label", sym("::") * expect(V"Name", "Label") * expect(sym("::"), "CloseLabel")); 311 | GoToStat = tagC("Goto", kw("goto") * expect(V"Name", "Goto")); 312 | BreakStat = tagC("Break", kw("break")); 313 | RetStat = tagC("Return", kw("return") * commaSep(V"Expr", "RetList")^-1 * sym(";")^-1); 314 | 315 | NameList = tagC("NameList", commaSep(V"Id")); 316 | VarList = tagC("VarList", commaSep(V"VarExpr", "VarList")); 317 | ExprList = tagC("ExpList", commaSep(V"Expr", "ExprList")); 318 | 319 | Expr = V"OrExpr"; 320 | OrExpr = chainOp(V"AndExpr", V"OrOp", "OrExpr"); 321 | AndExpr = chainOp(V"RelExpr", V"AndOp", "AndExpr"); 322 | RelExpr = chainOp(V"BOrExpr", V"RelOp", "RelExpr"); 323 | BOrExpr = chainOp(V"BXorExpr", V"BOrOp", "BOrExpr"); 324 | BXorExpr = chainOp(V"BAndExpr", V"BXorOp", "BXorExpr"); 325 | BAndExpr = chainOp(V"ShiftExpr", V"BAndOp", "BAndExpr"); 326 | ShiftExpr = chainOp(V"ConcatExpr", V"ShiftOp", "ShiftExpr"); 327 | ConcatExpr = V"AddExpr" * (V"ConcatOp" * expect(V"ConcatExpr", "ConcatExpr"))^-1 / binaryOp; 328 | AddExpr = chainOp(V"MulExpr", V"AddOp", "AddExpr"); 329 | MulExpr = chainOp(V"UnaryExpr", V"MulOp", "MulExpr"); 330 | UnaryExpr = V"UnaryOp" * expect(V"UnaryExpr", "UnaryExpr") / unaryOp 331 | + V"PowExpr"; 332 | PowExpr = V"SimpleExpr" * (V"PowOp" * expect(V"UnaryExpr", "PowExpr"))^-1 / binaryOp; 333 | 334 | SimpleExpr = tagC("Number", V"Number") 335 | + tagC("String", V"String") 336 | + tagC("Nil", kw("nil")) 337 | + tagC("Boolean", kw("false") * Cc(false)) 338 | + tagC("Boolean", kw("true") * Cc(true)) 339 | + tagC("Dots", sym("...")) 340 | + V"FuncDef" 341 | + V"Table" 342 | + V"SuffixedExpr"; 343 | 344 | FuncCall = Cmt(V"SuffixedExpr", function(s, i, exp) return exp.tag == "Call" or exp.tag == "Invoke", exp end); 345 | VarExpr = Cmt(V"SuffixedExpr", function(s, i, exp) return exp.tag == "Id" or exp.tag == "Index", exp end); 346 | 347 | SuffixedExpr = Cf(V"PrimaryExpr" * (V"Index" + V"Call")^0, makeIndexOrCall); 348 | PrimaryExpr = V"Id" + tagC("Paren", sym("(") * expect(V"Expr", "ExprParen") * expect(sym(")"), "CParenExpr")); 349 | Index = tagC("DotIndex", sym("." * -P".") * expect(V"StrId", "NameIndex")) 350 | + tagC("ArrayIndex", sym("[" * -P(S"=[")) * expect(V"Expr", "ExprIndex") * expect(sym("]"), "CBracketIndex")); 351 | Call = tagC("Invoke", Cg(sym(":" * -P":") * expect(V"StrId", "NameMeth") * expect(V"FuncArgs", "MethArgs"))) 352 | + tagC("Call", V"FuncArgs"); 353 | 354 | FuncDef = kw("function") * V"FuncBody"; 355 | FuncArgs = sym("(") * commaSep(V"Expr", "ArgList")^-1 * expect(sym(")"), "CParenArgs") 356 | + V"Table" 357 | + tagC("String", V"String"); 358 | 359 | Table = tagC("Table", sym("{") * V"FieldList"^-1 * expect(sym("}"), "CBraceTable")); 360 | FieldList = sepBy(V"Field", V"FieldSep") * V"FieldSep"^-1; 361 | Field = tagC("Pair", V"FieldKey" * expect(sym("="), "EqField") * expect(V"Expr", "ExprField")) 362 | + V"Expr"; 363 | FieldKey = sym("[" * -P(S"=[")) * expect(V"Expr", "ExprFKey") * expect(sym("]"), "CBracketFKey") 364 | + V"StrId" * #("=" * -P"="); 365 | FieldSep = sym(",") + sym(";"); 366 | 367 | Id = tagC("Id", V"Name"); 368 | StrId = tagC("String", V"Name"); 369 | 370 | -- lexer 371 | Skip = (V"Space" + V"Comment")^0; 372 | Space = space^1; 373 | Comment = P"--" * V"LongStr" / function () return end 374 | + P"--" * (P(1) - P"\n")^0; 375 | 376 | Name = token(-V"Reserved" * C(V"Ident")); 377 | Reserved = V"Keywords" * -V"IdRest"; 378 | Keywords = P"and" + "break" + "do" + "elseif" + "else" + "end" 379 | + "false" + "for" + "function" + "goto" + "if" + "in" 380 | + "local" + "nil" + "not" + "or" + "repeat" + "return" 381 | + "then" + "true" + "until" + "while"; 382 | Ident = V"IdStart" * V"IdRest"^0; 383 | IdStart = alpha + P"_"; 384 | IdRest = alnum + P"_"; 385 | 386 | Number = token((V"Hex" + V"Float" + V"Int") / tonumber); 387 | Hex = (P"0x" + "0X") * expect(xdigit^1, "DigitHex"); 388 | Float = V"Decimal" * V"Expo"^-1 389 | + V"Int" * V"Expo"; 390 | Decimal = digit^1 * "." * digit^0 391 | + P"." * -P"." * expect(digit^1, "DigitDeci"); 392 | Expo = S"eE" * S"+-"^-1 * expect(digit^1, "DigitExpo"); 393 | Int = digit^1; 394 | 395 | String = token(V"ShortStr" + V"LongStr"); 396 | ShortStr = P'"' * Cs((V"EscSeq" + (P(1)-S'"\n'))^0) * expect(P'"', "Quote") 397 | + P"'" * Cs((V"EscSeq" + (P(1)-S"'\n"))^0) * expect(P"'", "Quote"); 398 | 399 | EscSeq = P"\\" / "" -- remove backslash 400 | * ( P"a" / "\a" 401 | + P"b" / "\b" 402 | + P"f" / "\f" 403 | + P"n" / "\n" 404 | + P"r" / "\r" 405 | + P"t" / "\t" 406 | + P"v" / "\v" 407 | 408 | + P"\n" / "\n" 409 | + P"\r" / "\n" 410 | 411 | + P"\\" / "\\" 412 | + P"\"" / "\"" 413 | + P"\'" / "\'" 414 | 415 | + P"z" * space^0 / "" 416 | 417 | + digit * digit^-2 / tonumber / string.char 418 | + P"x" * expect(C(xdigit * xdigit), "HexEsc") * Cc(16) / tonumber / string.char 419 | + P"u" * expect("{", "OBraceUEsc") 420 | * expect(C(xdigit^1), "DigitUEsc") * Cc(16) 421 | * expect("}", "CBraceUEsc") 422 | / tonumber 423 | / (utf8 and utf8.char or string.char) -- true max is \u{10FFFF} 424 | -- utf8.char needs Lua 5.3 425 | -- string.char works only until \u{FF} 426 | 427 | + throw("EscSeq") 428 | ); 429 | 430 | LongStr = V"Open" * C((P(1) - V"CloseEq")^0) * expect(V"Close", "CloseLStr") / function (s, eqs) return s end; 431 | Open = "[" * Cg(V"Equals", "openEq") * "[" * P"\n"^-1; 432 | Close = "]" * C(V"Equals") * "]"; 433 | Equals = P"="^0; 434 | CloseEq = Cmt(V"Close" * Cb("openEq"), function (s, i, closeEq, openEq) return #openEq == #closeEq end); 435 | 436 | OrOp = kw("or") / "or"; 437 | AndOp = kw("and") / "and"; 438 | RelOp = sym("~=") / "ne" 439 | + sym("==") / "eq" 440 | + sym("<=") / "le" 441 | + sym(">=") / "ge" 442 | + sym("<") / "lt" 443 | + sym(">") / "gt"; 444 | BOrOp = sym("|") / "bor"; 445 | BXorOp = sym("~" * -P"=") / "bxor"; 446 | BAndOp = sym("&") / "band"; 447 | ShiftOp = sym("<<") / "shl" 448 | + sym(">>") / "shr"; 449 | ConcatOp = sym("..") / "concat"; 450 | AddOp = sym("+") / "add" 451 | + sym("-") / "sub"; 452 | MulOp = sym("*") / "mul" 453 | + sym("//") / "idiv" 454 | + sym("/") / "div" 455 | + sym("%") / "mod"; 456 | UnaryOp = kw("not") / "not" 457 | + sym("-") / "unm" 458 | + sym("#") / "len" 459 | + sym("~") / "bnot"; 460 | PowOp = sym("^") / "pow"; 461 | } 462 | 463 | local parser = { detailed_errors = false } 464 | 465 | local validator = require("lua-parser.validator") 466 | local validate = validator.validate 467 | local syntaxerror = validator.syntaxerror 468 | 469 | function parser.parse (subject, filename) 470 | local errorinfo = { subject = subject, filename = filename } 471 | lpeg.setmaxstack(1000) 472 | local ast, label, errorpos = lpeg.match(G, subject, nil, errorinfo) 473 | if not ast then 474 | if parser.detailed_errors then 475 | local re = require "relabel" 476 | local line, col = re.calcline(subject, errorpos) 477 | return ast, { 478 | line = line; 479 | column = col; 480 | id = labels[label][1]; 481 | message = labels[label][2]; 482 | position = errorpos; 483 | } 484 | else 485 | local errmsg = labels[label][2] 486 | return ast, syntaxerror(errorinfo, errorpos, errmsg) 487 | end 488 | end 489 | return validate(ast, errorinfo) 490 | end 491 | 492 | return parser 493 | -------------------------------------------------------------------------------- /lua-parser/pp.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | This module impements a pretty printer to the AST 3 | ]] 4 | local pp = {} 5 | 6 | local block2str, stm2str, exp2str, var2str 7 | local explist2str, varlist2str, parlist2str, fieldlist2str 8 | 9 | local function iscntrl (x) 10 | if (x >= 0 and x <= 31) or (x == 127) then return true end 11 | return false 12 | end 13 | 14 | local function isprint (x) 15 | return not iscntrl(x) 16 | end 17 | 18 | local function fixed_string (str) 19 | local new_str = "" 20 | for i=1,string.len(str) do 21 | char = string.byte(str, i) 22 | if char == 34 then new_str = new_str .. string.format("\\\"") 23 | elseif char == 92 then new_str = new_str .. string.format("\\\\") 24 | elseif char == 7 then new_str = new_str .. string.format("\\a") 25 | elseif char == 8 then new_str = new_str .. string.format("\\b") 26 | elseif char == 12 then new_str = new_str .. string.format("\\f") 27 | elseif char == 10 then new_str = new_str .. string.format("\\n") 28 | elseif char == 13 then new_str = new_str .. string.format("\\r") 29 | elseif char == 9 then new_str = new_str .. string.format("\\t") 30 | elseif char == 11 then new_str = new_str .. string.format("\\v") 31 | else 32 | if isprint(char) then 33 | new_str = new_str .. string.format("%c", char) 34 | else 35 | new_str = new_str .. string.format("\\%03d", char) 36 | end 37 | end 38 | end 39 | return new_str 40 | end 41 | 42 | local function name2str (name) 43 | return string.format('"%s"', name) 44 | end 45 | 46 | local function boolean2str (b) 47 | return string.format('"%s"', tostring(b)) 48 | end 49 | 50 | local function number2str (n) 51 | return string.format('"%s"', tostring(n)) 52 | end 53 | 54 | local function string2str (s) 55 | return string.format('"%s"', fixed_string(s)) 56 | end 57 | 58 | function var2str (var) 59 | local tag = var.tag 60 | local str = "`" .. tag 61 | if tag == "Id" then -- `Id{ } 62 | str = str .. " " .. name2str(var[1]) 63 | elseif tag == "Index" then -- `Index{ expr expr } 64 | str = str .. "{ " 65 | str = str .. exp2str(var[1]) .. ", " 66 | str = str .. exp2str(var[2]) 67 | str = str .. " }" 68 | else 69 | error("expecting a variable, but got a " .. tag) 70 | end 71 | return str 72 | end 73 | 74 | function varlist2str (varlist) 75 | local l = {} 76 | for k, v in ipairs(varlist) do 77 | l[k] = var2str(v) 78 | end 79 | return "{ " .. table.concat(l, ", ") .. " }" 80 | end 81 | 82 | function parlist2str (parlist) 83 | local l = {} 84 | local len = #parlist 85 | local is_vararg = false 86 | if len > 0 and parlist[len].tag == "Dots" then 87 | is_vararg = true 88 | len = len - 1 89 | end 90 | local i = 1 91 | while i <= len do 92 | l[i] = var2str(parlist[i]) 93 | i = i + 1 94 | end 95 | if is_vararg then 96 | l[i] = "`" .. parlist[i].tag 97 | end 98 | return "{ " .. table.concat(l, ", ") .. " }" 99 | end 100 | 101 | function fieldlist2str (fieldlist) 102 | local l = {} 103 | for k, v in ipairs(fieldlist) do 104 | local tag = v.tag 105 | if tag == "Pair" then -- `Pair{ expr expr } 106 | l[k] = "`" .. tag .. "{ " 107 | l[k] = l[k] .. exp2str(v[1]) .. ", " .. exp2str(v[2]) 108 | l[k] = l[k] .. " }" 109 | else -- expr 110 | l[k] = exp2str(v) 111 | end 112 | end 113 | if #l > 0 then 114 | return "{ " .. table.concat(l, ", ") .. " }" 115 | else 116 | return "" 117 | end 118 | end 119 | 120 | function exp2str (exp) 121 | local tag = exp.tag 122 | local str = "`" .. tag 123 | if tag == "Nil" or 124 | tag == "Dots" then 125 | elseif tag == "Boolean" then -- `Boolean{ } 126 | str = str .. " " .. boolean2str(exp[1]) 127 | elseif tag == "Number" then -- `Number{ } 128 | str = str .. " " .. number2str(exp[1]) 129 | elseif tag == "String" then -- `String{ } 130 | str = str .. " " .. string2str(exp[1]) 131 | elseif tag == "Function" then -- `Function{ { `Id{ }* `Dots? } block } 132 | str = str .. "{ " 133 | str = str .. parlist2str(exp[1]) .. ", " 134 | str = str .. block2str(exp[2]) 135 | str = str .. " }" 136 | elseif tag == "Table" then -- `Table{ ( `Pair{ expr expr } | expr )* } 137 | str = str .. fieldlist2str(exp) 138 | elseif tag == "Op" then -- `Op{ opid expr expr? } 139 | str = str .. "{ " 140 | str = str .. name2str(exp[1]) .. ", " 141 | str = str .. exp2str(exp[2]) 142 | if exp[3] then 143 | str = str .. ", " .. exp2str(exp[3]) 144 | end 145 | str = str .. " }" 146 | elseif tag == "Paren" then -- `Paren{ expr } 147 | str = str .. "{ " .. exp2str(exp[1]) .. " }" 148 | elseif tag == "Call" then -- `Call{ expr expr* } 149 | str = str .. "{ " 150 | str = str .. exp2str(exp[1]) 151 | if exp[2] then 152 | for i=2, #exp do 153 | str = str .. ", " .. exp2str(exp[i]) 154 | end 155 | end 156 | str = str .. " }" 157 | elseif tag == "Invoke" then -- `Invoke{ expr `String{ } expr* } 158 | str = str .. "{ " 159 | str = str .. exp2str(exp[1]) .. ", " 160 | str = str .. exp2str(exp[2]) 161 | if exp[3] then 162 | for i=3, #exp do 163 | str = str .. ", " .. exp2str(exp[i]) 164 | end 165 | end 166 | str = str .. " }" 167 | elseif tag == "Id" or -- `Id{ } 168 | tag == "Index" then -- `Index{ expr expr } 169 | str = var2str(exp) 170 | else 171 | error("expecting an expression, but got a " .. tag) 172 | end 173 | return str 174 | end 175 | 176 | function explist2str (explist) 177 | local l = {} 178 | for k, v in ipairs(explist) do 179 | l[k] = exp2str(v) 180 | end 181 | if #l > 0 then 182 | return "{ " .. table.concat(l, ", ") .. " }" 183 | else 184 | return "" 185 | end 186 | end 187 | 188 | function stm2str (stm) 189 | local tag = stm.tag 190 | local str = "`" .. tag 191 | if tag == "Do" then -- `Do{ stat* } 192 | local l = {} 193 | for k, v in ipairs(stm) do 194 | l[k] = stm2str(v) 195 | end 196 | str = str .. "{ " .. table.concat(l, ", ") .. " }" 197 | elseif tag == "Set" then -- `Set{ {lhs+} {expr+} } 198 | str = str .. "{ " 199 | str = str .. varlist2str(stm[1]) .. ", " 200 | str = str .. explist2str(stm[2]) 201 | str = str .. " }" 202 | elseif tag == "While" then -- `While{ expr block } 203 | str = str .. "{ " 204 | str = str .. exp2str(stm[1]) .. ", " 205 | str = str .. block2str(stm[2]) 206 | str = str .. " }" 207 | elseif tag == "Repeat" then -- `Repeat{ block expr } 208 | str = str .. "{ " 209 | str = str .. block2str(stm[1]) .. ", " 210 | str = str .. exp2str(stm[2]) 211 | str = str .. " }" 212 | elseif tag == "If" then -- `If{ (expr block)+ block? } 213 | str = str .. "{ " 214 | local len = #stm 215 | if len % 2 == 0 then 216 | local l = {} 217 | for i=1,len-2,2 do 218 | str = str .. exp2str(stm[i]) .. ", " .. block2str(stm[i+1]) .. ", " 219 | end 220 | str = str .. exp2str(stm[len-1]) .. ", " .. block2str(stm[len]) 221 | else 222 | local l = {} 223 | for i=1,len-3,2 do 224 | str = str .. exp2str(stm[i]) .. ", " .. block2str(stm[i+1]) .. ", " 225 | end 226 | str = str .. exp2str(stm[len-2]) .. ", " .. block2str(stm[len-1]) .. ", " 227 | str = str .. block2str(stm[len]) 228 | end 229 | str = str .. " }" 230 | elseif tag == "Fornum" then -- `Fornum{ ident expr expr expr? block } 231 | str = str .. "{ " 232 | str = str .. var2str(stm[1]) .. ", " 233 | str = str .. exp2str(stm[2]) .. ", " 234 | str = str .. exp2str(stm[3]) .. ", " 235 | if stm[5] then 236 | str = str .. exp2str(stm[4]) .. ", " 237 | str = str .. block2str(stm[5]) 238 | else 239 | str = str .. block2str(stm[4]) 240 | end 241 | str = str .. " }" 242 | elseif tag == "Forin" then -- `Forin{ {ident+} {expr+} block } 243 | str = str .. "{ " 244 | str = str .. varlist2str(stm[1]) .. ", " 245 | str = str .. explist2str(stm[2]) .. ", " 246 | str = str .. block2str(stm[3]) 247 | str = str .. " }" 248 | elseif tag == "Local" then -- `Local{ {ident+} {expr+}? } 249 | str = str .. "{ " 250 | str = str .. varlist2str(stm[1]) 251 | if #stm[2] > 0 then 252 | str = str .. ", " .. explist2str(stm[2]) 253 | else 254 | str = str .. ", " .. "{ }" 255 | end 256 | str = str .. " }" 257 | elseif tag == "Localrec" then -- `Localrec{ ident expr } 258 | str = str .. "{ " 259 | str = str .. "{ " .. var2str(stm[1][1]) .. " }, " 260 | str = str .. "{ " .. exp2str(stm[2][1]) .. " }" 261 | str = str .. " }" 262 | elseif tag == "Goto" or -- `Goto{ } 263 | tag == "Label" then -- `Label{ } 264 | str = str .. "{ " .. name2str(stm[1]) .. " }" 265 | elseif tag == "Return" then -- `Return{ * } 266 | str = str .. explist2str(stm) 267 | elseif tag == "Break" then 268 | elseif tag == "Call" then -- `Call{ expr expr* } 269 | str = str .. "{ " 270 | str = str .. exp2str(stm[1]) 271 | if stm[2] then 272 | for i=2, #stm do 273 | str = str .. ", " .. exp2str(stm[i]) 274 | end 275 | end 276 | str = str .. " }" 277 | elseif tag == "Invoke" then -- `Invoke{ expr `String{ } expr* } 278 | str = str .. "{ " 279 | str = str .. exp2str(stm[1]) .. ", " 280 | str = str .. exp2str(stm[2]) 281 | if stm[3] then 282 | for i=3, #stm do 283 | str = str .. ", " .. exp2str(stm[i]) 284 | end 285 | end 286 | str = str .. " }" 287 | else 288 | error("expecting a statement, but got a " .. tag) 289 | end 290 | return str 291 | end 292 | 293 | function block2str (block) 294 | local l = {} 295 | for k, v in ipairs(block) do 296 | l[k] = stm2str(v) 297 | end 298 | return "{ " .. table.concat(l, ", ") .. " }" 299 | end 300 | 301 | function pp.tostring (t) 302 | assert(type(t) == "table") 303 | return block2str(t) 304 | end 305 | 306 | function pp.print (t) 307 | assert(type(t) == "table") 308 | print(pp.tostring(t)) 309 | end 310 | 311 | function pp.dump (t, i) 312 | if i == nil then i = 0 end 313 | io.write(string.format("{\n")) 314 | io.write(string.format("%s[tag] = %s\n", string.rep(" ", i+2), t.tag or "nil")) 315 | io.write(string.format("%s[pos] = %s\n", string.rep(" ", i+2), t.pos or "nil")) 316 | for k,v in ipairs(t) do 317 | io.write(string.format("%s[%s] = ", string.rep(" ", i+2), tostring(k))) 318 | if type(v) == "table" then 319 | pp.dump(v,i+2) 320 | else 321 | io.write(string.format("%s\n", tostring(v))) 322 | end 323 | end 324 | io.write(string.format("%s}\n", string.rep(" ", i))) 325 | end 326 | 327 | return pp 328 | -------------------------------------------------------------------------------- /lua-parser/scope.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | This module implements functions that handle scoping rules 3 | ]] 4 | local scope = {} 5 | 6 | function scope.lineno (s, i) 7 | if i == 1 then return 1, 1 end 8 | local l, lastline = 0, "" 9 | s = s:sub(1, i) .. "\n" 10 | for line in s:gmatch("[^\n]*[\n]") do 11 | l = l + 1 12 | lastline = line 13 | end 14 | local c = lastline:len() - 1 15 | return l, c ~= 0 and c or 1 16 | end 17 | 18 | function scope.new_scope (env) 19 | if not env.scope then 20 | env.scope = 0 21 | else 22 | env.scope = env.scope + 1 23 | end 24 | local scope = env.scope 25 | env.maxscope = scope 26 | env[scope] = {} 27 | env[scope]["label"] = {} 28 | env[scope]["local"] = {} 29 | env[scope]["goto"] = {} 30 | end 31 | 32 | function scope.begin_scope (env) 33 | env.scope = env.scope + 1 34 | end 35 | 36 | function scope.end_scope (env) 37 | env.scope = env.scope - 1 38 | end 39 | 40 | function scope.new_function (env) 41 | if not env.fscope then 42 | env.fscope = 0 43 | else 44 | env.fscope = env.fscope + 1 45 | end 46 | local fscope = env.fscope 47 | env["function"][fscope] = {} 48 | end 49 | 50 | function scope.begin_function (env) 51 | env.fscope = env.fscope + 1 52 | end 53 | 54 | function scope.end_function (env) 55 | env.fscope = env.fscope - 1 56 | end 57 | 58 | function scope.begin_loop (env) 59 | if not env.loop then 60 | env.loop = 1 61 | else 62 | env.loop = env.loop + 1 63 | end 64 | end 65 | 66 | function scope.end_loop (env) 67 | env.loop = env.loop - 1 68 | end 69 | 70 | function scope.insideloop (env) 71 | return env.loop and env.loop > 0 72 | end 73 | 74 | return scope 75 | -------------------------------------------------------------------------------- /lua-parser/validator.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | This module impements a validator for the AST 3 | ]] 4 | local scope = require "lua-parser.scope" 5 | 6 | local lineno = scope.lineno 7 | local new_scope, end_scope = scope.new_scope, scope.end_scope 8 | local new_function, end_function = scope.new_function, scope.end_function 9 | local begin_loop, end_loop = scope.begin_loop, scope.end_loop 10 | local insideloop = scope.insideloop 11 | 12 | -- creates an error message for the input string 13 | local function syntaxerror (errorinfo, pos, msg) 14 | local l, c = lineno(errorinfo.subject, pos) 15 | local error_msg = "%s:%d:%d: syntax error, %s" 16 | return string.format(error_msg, errorinfo.filename, l, c, msg) 17 | end 18 | 19 | local function exist_label (env, scope, stm) 20 | local l = stm[1] 21 | for s=scope, 0, -1 do 22 | if env[s]["label"][l] then return true end 23 | end 24 | return false 25 | end 26 | 27 | local function set_label (env, label, pos) 28 | local scope = env.scope 29 | local l = env[scope]["label"][label] 30 | if not l then 31 | env[scope]["label"][label] = { name = label, pos = pos } 32 | return true 33 | else 34 | local msg = "label '%s' already defined at line %d" 35 | local line = lineno(env.errorinfo.subject, l.pos) 36 | msg = string.format(msg, label, line) 37 | return nil, syntaxerror(env.errorinfo, pos, msg) 38 | end 39 | end 40 | 41 | local function set_pending_goto (env, stm) 42 | local scope = env.scope 43 | table.insert(env[scope]["goto"], stm) 44 | return true 45 | end 46 | 47 | local function verify_pending_gotos (env) 48 | for s=env.maxscope, 0, -1 do 49 | for k, v in ipairs(env[s]["goto"]) do 50 | if not exist_label(env, s, v) then 51 | local msg = "no visible label '%s' for " 52 | msg = string.format(msg, v[1]) 53 | return nil, syntaxerror(env.errorinfo, v.pos, msg) 54 | end 55 | end 56 | end 57 | return true 58 | end 59 | 60 | local function set_vararg (env, is_vararg) 61 | env["function"][env.fscope].is_vararg = is_vararg 62 | end 63 | 64 | local traverse_stm, traverse_exp, traverse_var 65 | local traverse_block, traverse_explist, traverse_varlist, traverse_parlist 66 | 67 | function traverse_parlist (env, parlist) 68 | local len = #parlist 69 | local is_vararg = false 70 | if len > 0 and parlist[len].tag == "Dots" then 71 | is_vararg = true 72 | end 73 | set_vararg(env, is_vararg) 74 | return true 75 | end 76 | 77 | local function traverse_function (env, exp) 78 | new_function(env) 79 | new_scope(env) 80 | local status, msg = traverse_parlist(env, exp[1]) 81 | if not status then return status, msg end 82 | status, msg = traverse_block(env, exp[2]) 83 | if not status then return status, msg end 84 | end_scope(env) 85 | end_function(env) 86 | return true 87 | end 88 | 89 | local function traverse_op (env, exp) 90 | local status, msg = traverse_exp(env, exp[2]) 91 | if not status then return status, msg end 92 | if exp[3] then 93 | status, msg = traverse_exp(env, exp[3]) 94 | if not status then return status, msg end 95 | end 96 | return true 97 | end 98 | 99 | local function traverse_paren (env, exp) 100 | local status, msg = traverse_exp(env, exp[1]) 101 | if not status then return status, msg end 102 | return true 103 | end 104 | 105 | local function traverse_table (env, fieldlist) 106 | for k, v in ipairs(fieldlist) do 107 | local tag = v.tag 108 | if tag == "Pair" then 109 | local status, msg = traverse_exp(env, v[1]) 110 | if not status then return status, msg end 111 | status, msg = traverse_exp(env, v[2]) 112 | if not status then return status, msg end 113 | else 114 | local status, msg = traverse_exp(env, v) 115 | if not status then return status, msg end 116 | end 117 | end 118 | return true 119 | end 120 | 121 | local function traverse_vararg (env, exp) 122 | if not env["function"][env.fscope].is_vararg then 123 | local msg = "cannot use '...' outside a vararg function" 124 | return nil, syntaxerror(env.errorinfo, exp.pos, msg) 125 | end 126 | return true 127 | end 128 | 129 | local function traverse_call (env, call) 130 | local status, msg = traverse_exp(env, call[1]) 131 | if not status then return status, msg end 132 | for i=2, #call do 133 | status, msg = traverse_exp(env, call[i]) 134 | if not status then return status, msg end 135 | end 136 | return true 137 | end 138 | 139 | local function traverse_invoke (env, invoke) 140 | local status, msg = traverse_exp(env, invoke[1]) 141 | if not status then return status, msg end 142 | for i=3, #invoke do 143 | status, msg = traverse_exp(env, invoke[i]) 144 | if not status then return status, msg end 145 | end 146 | return true 147 | end 148 | 149 | local function traverse_assignment (env, stm) 150 | local status, msg = traverse_varlist(env, stm[1]) 151 | if not status then return status, msg end 152 | status, msg = traverse_explist(env, stm[2]) 153 | if not status then return status, msg end 154 | return true 155 | end 156 | 157 | local function traverse_break (env, stm) 158 | if not insideloop(env) then 159 | local msg = " not inside a loop" 160 | return nil, syntaxerror(env.errorinfo, stm.pos, msg) 161 | end 162 | return true 163 | end 164 | 165 | local function traverse_forin (env, stm) 166 | begin_loop(env) 167 | new_scope(env) 168 | local status, msg = traverse_explist(env, stm[2]) 169 | if not status then return status, msg end 170 | status, msg = traverse_block(env, stm[3]) 171 | if not status then return status, msg end 172 | end_scope(env) 173 | end_loop(env) 174 | return true 175 | end 176 | 177 | local function traverse_fornum (env, stm) 178 | local status, msg 179 | begin_loop(env) 180 | new_scope(env) 181 | status, msg = traverse_exp(env, stm[2]) 182 | if not status then return status, msg end 183 | status, msg = traverse_exp(env, stm[3]) 184 | if not status then return status, msg end 185 | if stm[5] then 186 | status, msg = traverse_exp(env, stm[4]) 187 | if not status then return status, msg end 188 | status, msg = traverse_block(env, stm[5]) 189 | if not status then return status, msg end 190 | else 191 | status, msg = traverse_block(env, stm[4]) 192 | if not status then return status, msg end 193 | end 194 | end_scope(env) 195 | end_loop(env) 196 | return true 197 | end 198 | 199 | local function traverse_goto (env, stm) 200 | local status, msg = set_pending_goto(env, stm) 201 | if not status then return status, msg end 202 | return true 203 | end 204 | 205 | local function traverse_if (env, stm) 206 | local len = #stm 207 | if len % 2 == 0 then 208 | for i=1, len, 2 do 209 | local status, msg = traverse_exp(env, stm[i]) 210 | if not status then return status, msg end 211 | status, msg = traverse_block(env, stm[i+1]) 212 | if not status then return status, msg end 213 | end 214 | else 215 | for i=1, len-1, 2 do 216 | local status, msg = traverse_exp(env, stm[i]) 217 | if not status then return status, msg end 218 | status, msg = traverse_block(env, stm[i+1]) 219 | if not status then return status, msg end 220 | end 221 | local status, msg = traverse_block(env, stm[len]) 222 | if not status then return status, msg end 223 | end 224 | return true 225 | end 226 | 227 | local function traverse_label (env, stm) 228 | local status, msg = set_label(env, stm[1], stm.pos) 229 | if not status then return status, msg end 230 | return true 231 | end 232 | 233 | local function traverse_let (env, stm) 234 | local status, msg = traverse_explist(env, stm[2]) 235 | if not status then return status, msg end 236 | return true 237 | end 238 | 239 | local function traverse_letrec (env, stm) 240 | local status, msg = traverse_exp(env, stm[2][1]) 241 | if not status then return status, msg end 242 | return true 243 | end 244 | 245 | local function traverse_repeat (env, stm) 246 | begin_loop(env) 247 | local status, msg = traverse_block(env, stm[1]) 248 | if not status then return status, msg end 249 | status, msg = traverse_exp(env, stm[2]) 250 | if not status then return status, msg end 251 | end_loop(env) 252 | return true 253 | end 254 | 255 | local function traverse_return (env, stm) 256 | local status, msg = traverse_explist(env, stm) 257 | if not status then return status, msg end 258 | return true 259 | end 260 | 261 | local function traverse_while (env, stm) 262 | begin_loop(env) 263 | local status, msg = traverse_exp(env, stm[1]) 264 | if not status then return status, msg end 265 | status, msg = traverse_block(env, stm[2]) 266 | if not status then return status, msg end 267 | end_loop(env) 268 | return true 269 | end 270 | 271 | function traverse_var (env, var) 272 | local tag = var.tag 273 | if tag == "Id" then -- `Id{ } 274 | return true 275 | elseif tag == "Index" then -- `Index{ expr expr } 276 | local status, msg = traverse_exp(env, var[1]) 277 | if not status then return status, msg end 278 | status, msg = traverse_exp(env, var[2]) 279 | if not status then return status, msg end 280 | return true 281 | else 282 | error("expecting a variable, but got a " .. tag) 283 | end 284 | end 285 | 286 | function traverse_varlist (env, varlist) 287 | for k, v in ipairs(varlist) do 288 | local status, msg = traverse_var(env, v) 289 | if not status then return status, msg end 290 | end 291 | return true 292 | end 293 | 294 | function traverse_exp (env, exp) 295 | local tag = exp.tag 296 | if tag == "Nil" or 297 | tag == "Boolean" or -- `Boolean{ } 298 | tag == "Number" or -- `Number{ } 299 | tag == "String" then -- `String{ } 300 | return true 301 | elseif tag == "Dots" then 302 | return traverse_vararg(env, exp) 303 | elseif tag == "Function" then -- `Function{ { `Id{ }* `Dots? } block } 304 | return traverse_function(env, exp) 305 | elseif tag == "Table" then -- `Table{ ( `Pair{ expr expr } | expr )* } 306 | return traverse_table(env, exp) 307 | elseif tag == "Op" then -- `Op{ opid expr expr? } 308 | return traverse_op(env, exp) 309 | elseif tag == "Paren" then -- `Paren{ expr } 310 | return traverse_paren(env, exp) 311 | elseif tag == "Call" then -- `Call{ expr expr* } 312 | return traverse_call(env, exp) 313 | elseif tag == "Invoke" then -- `Invoke{ expr `String{ } expr* } 314 | return traverse_invoke(env, exp) 315 | elseif tag == "Id" or -- `Id{ } 316 | tag == "Index" then -- `Index{ expr expr } 317 | return traverse_var(env, exp) 318 | else 319 | error("expecting an expression, but got a " .. tag) 320 | end 321 | end 322 | 323 | function traverse_explist (env, explist) 324 | for k, v in ipairs(explist) do 325 | local status, msg = traverse_exp(env, v) 326 | if not status then return status, msg end 327 | end 328 | return true 329 | end 330 | 331 | function traverse_stm (env, stm) 332 | local tag = stm.tag 333 | if tag == "Do" then -- `Do{ stat* } 334 | return traverse_block(env, stm) 335 | elseif tag == "Set" then -- `Set{ {lhs+} {expr+} } 336 | return traverse_assignment(env, stm) 337 | elseif tag == "While" then -- `While{ expr block } 338 | return traverse_while(env, stm) 339 | elseif tag == "Repeat" then -- `Repeat{ block expr } 340 | return traverse_repeat(env, stm) 341 | elseif tag == "If" then -- `If{ (expr block)+ block? } 342 | return traverse_if(env, stm) 343 | elseif tag == "Fornum" then -- `Fornum{ ident expr expr expr? block } 344 | return traverse_fornum(env, stm) 345 | elseif tag == "Forin" then -- `Forin{ {ident+} {expr+} block } 346 | return traverse_forin(env, stm) 347 | elseif tag == "Local" then -- `Local{ {ident+} {expr+}? } 348 | return traverse_let(env, stm) 349 | elseif tag == "Localrec" then -- `Localrec{ ident expr } 350 | return traverse_letrec(env, stm) 351 | elseif tag == "Goto" then -- `Goto{ } 352 | return traverse_goto(env, stm) 353 | elseif tag == "Label" then -- `Label{ } 354 | return traverse_label(env, stm) 355 | elseif tag == "Return" then -- `Return{ * } 356 | return traverse_return(env, stm) 357 | elseif tag == "Break" then 358 | return traverse_break(env, stm) 359 | elseif tag == "Call" then -- `Call{ expr expr* } 360 | return traverse_call(env, stm) 361 | elseif tag == "Invoke" then -- `Invoke{ expr `String{ } expr* } 362 | return traverse_invoke(env, stm) 363 | else 364 | error("expecting a statement, but got a " .. tag) 365 | end 366 | end 367 | 368 | function traverse_block (env, block) 369 | local l = {} 370 | new_scope(env) 371 | for k, v in ipairs(block) do 372 | local status, msg = traverse_stm(env, v) 373 | if not status then return status, msg end 374 | end 375 | end_scope(env) 376 | return true 377 | end 378 | 379 | 380 | local function traverse (ast, errorinfo) 381 | assert(type(ast) == "table") 382 | assert(type(errorinfo) == "table") 383 | local env = { errorinfo = errorinfo, ["function"] = {} } 384 | new_function(env) 385 | set_vararg(env, true) 386 | local status, msg = traverse_block(env, ast) 387 | if not status then return status, msg end 388 | end_function(env) 389 | status, msg = verify_pending_gotos(env) 390 | if not status then return status, msg end 391 | return ast 392 | end 393 | 394 | return { validate = traverse, syntaxerror = syntaxerror } 395 | -------------------------------------------------------------------------------- /rockspecs/lua-parser-0.1.1-1.rockspec: -------------------------------------------------------------------------------- 1 | --*-lua-*-- 2 | package = "lua-parser" 3 | version = "0.1.1-1" 4 | source = { 5 | url = "git://github.com/andremm/lua-parser", 6 | tag = "v0.1.1", 7 | } 8 | description = { 9 | summary = "A Lua 5.3 parser written with LPeg", 10 | detailed = [[ 11 | This is a Lua 5.3 parser written with LPeg that generates an AST in 12 | the format specified by Metalua. 13 | The parser also implements an error reporting technique that is 14 | based on tracking the farthest failure position. 15 | ]], 16 | homepage = "https://github.com/andremm/lua-parser", 17 | license = "MIT" 18 | } 19 | dependencies = { 20 | "lua >= 5.1", 21 | "lpeg >= 0.12", 22 | } 23 | build = { 24 | type="builtin", 25 | modules={ 26 | ["lua-parser.parser"] = "lua-parser/parser.lua", 27 | ["lua-parser.pp"] = "lua-parser/pp.lua", 28 | ["lua-parser.scope"] = "lua-parser/scope.lua", 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /rockspecs/lua-parser-1.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | --*-lua-*-- 2 | package = "lua-parser" 3 | version = "1.0.0-1" 4 | source = { 5 | url = "git://github.com/andremm/lua-parser", 6 | tag = "v1.0.0", 7 | } 8 | description = { 9 | summary = "A Lua 5.3 parser written with LPegLabel", 10 | detailed = [[ 11 | This is a Lua 5.3 parser written with LPegLabel that generates an AST in 12 | the format specified by Metalua. 13 | The parser uses LPegLabel to provide more specific error messages. 14 | ]], 15 | homepage = "https://github.com/andremm/lua-parser", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1", 20 | "lpeglabel >= 1.0.0", 21 | } 22 | build = { 23 | type="builtin", 24 | modules={ 25 | ["lua-parser.parser"] = "lua-parser/parser.lua", 26 | ["lua-parser.pp"] = "lua-parser/pp.lua", 27 | ["lua-parser.scope"] = "lua-parser/scope.lua", 28 | ["lua-parser.validator"] = "lua-parser/validator.lua", 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /rockspecs/lua-parser-1.0.1-1.rockspec: -------------------------------------------------------------------------------- 1 | --*-lua-*-- 2 | package = "lua-parser" 3 | version = "1.0.1-1" 4 | source = { 5 | url = "git://github.com/andremm/lua-parser", 6 | tag = "v1.0.1", 7 | } 8 | description = { 9 | summary = "A Lua 5.3 parser written with LPegLabel", 10 | detailed = [[ 11 | This is a Lua 5.3 parser written with LPegLabel that generates an AST in 12 | the format specified by Metalua. 13 | The parser uses LPegLabel to provide more specific error messages. 14 | ]], 15 | homepage = "https://github.com/andremm/lua-parser", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1", 20 | "lpeglabel >= 1.6.0", 21 | } 22 | build = { 23 | type="builtin", 24 | modules={ 25 | ["lua-parser.parser"] = "lua-parser/parser.lua", 26 | ["lua-parser.pp"] = "lua-parser/pp.lua", 27 | ["lua-parser.scope"] = "lua-parser/scope.lua", 28 | ["lua-parser.validator"] = "lua-parser/validator.lua", 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /rockspecs/lua-parser-1.0.2-1.rockspec: -------------------------------------------------------------------------------- 1 | --*-lua-*-- 2 | package = "lua-parser" 3 | version = "1.0.2-1" 4 | source = { 5 | url = "git://github.com/andremm/lua-parser", 6 | tag = "v1.0.2", 7 | } 8 | description = { 9 | summary = "A Lua 5.3 parser written with LPegLabel", 10 | detailed = [[ 11 | This is a Lua 5.3 parser written with LPegLabel that generates an AST in 12 | the format specified by Metalua. 13 | The parser uses LPegLabel to provide more specific error messages. 14 | ]], 15 | homepage = "https://github.com/andremm/lua-parser", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1", 20 | "lpeglabel >= 1.6.0", 21 | } 22 | build = { 23 | type="builtin", 24 | modules={ 25 | ["lua-parser.parser"] = "lua-parser/parser.lua", 26 | ["lua-parser.pp"] = "lua-parser/pp.lua", 27 | ["lua-parser.scope"] = "lua-parser/scope.lua", 28 | ["lua-parser.validator"] = "lua-parser/validator.lua", 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /rockspecs/lua-parser-1.0.3-1.rockspec: -------------------------------------------------------------------------------- 1 | --*-lua-*-- 2 | package = "lua-parser" 3 | version = "1.0.3-1" 4 | source = { 5 | url = "git://github.com/andremm/lua-parser", 6 | tag = "v1.0.3", 7 | } 8 | description = { 9 | summary = "A Lua 5.3 parser written with LPegLabel", 10 | detailed = [[ 11 | This is a Lua 5.3 parser written with LPegLabel that generates an AST in 12 | the format specified by Metalua. 13 | The parser uses LPegLabel to provide more specific error messages. 14 | ]], 15 | homepage = "https://github.com/andremm/lua-parser", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1", 20 | "lpeglabel >= 1.6.0", 21 | } 22 | build = { 23 | type="builtin", 24 | modules={ 25 | ["lua-parser.parser"] = "lua-parser/parser.lua", 26 | ["lua-parser.pp"] = "lua-parser/pp.lua", 27 | ["lua-parser.scope"] = "lua-parser/scope.lua", 28 | ["lua-parser.validator"] = "lua-parser/validator.lua", 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /rockspecs/lua-parser-1.0.4-1.rockspec: -------------------------------------------------------------------------------- 1 | --*-lua-*-- 2 | package = "lua-parser" 3 | version = "1.0.4-1" 4 | source = { 5 | url = "git://github.com/andremm/lua-parser", 6 | tag = "v1.0.4", 7 | } 8 | description = { 9 | summary = "A Lua 5.3 parser written with LPegLabel", 10 | detailed = [[ 11 | This is a Lua 5.3 parser written with LPegLabel that generates an AST in 12 | the format specified by Metalua. 13 | The parser uses LPegLabel to provide more specific error messages. 14 | ]], 15 | homepage = "https://github.com/andremm/lua-parser", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1", 20 | "lpeglabel >= 1.6.0", 21 | } 22 | build = { 23 | type="builtin", 24 | modules={ 25 | ["lua-parser.parser"] = "lua-parser/parser.lua", 26 | ["lua-parser.pp"] = "lua-parser/pp.lua", 27 | ["lua-parser.scope"] = "lua-parser/scope.lua", 28 | ["lua-parser.validator"] = "lua-parser/validator.lua", 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local parser = require "lua-parser.parser" 4 | local pp = require "lua-parser.pp" 5 | 6 | -- expected result, result, subject 7 | local e, r, s 8 | 9 | local filename = "test.lua" 10 | 11 | local function parse (s) 12 | local t,m = parser.parse(s,filename) 13 | local r 14 | if not t then 15 | r = m 16 | else 17 | r = pp.tostring(t) 18 | end 19 | return r .. "\n" 20 | end 21 | 22 | local function fixint (s) 23 | return _VERSION < "Lua 5.3" and s:gsub("%.0","") or s 24 | end 25 | 26 | print("> testing lexer...") 27 | 28 | -- syntax ok 29 | 30 | -- empty files 31 | 32 | s = [=[ 33 | ]=] 34 | e = [=[ 35 | { } 36 | ]=] 37 | 38 | r = parse(s) 39 | assert(r == e) 40 | 41 | s = [=[ 42 | -- testing empty file 43 | ]=] 44 | e = [=[ 45 | { } 46 | ]=] 47 | 48 | r = parse(s) 49 | assert(r == e) 50 | 51 | -- expressions 52 | 53 | s = [=[ 54 | _nil,_false,_true,_dots = nil,false,true,... 55 | ]=] 56 | e = [=[ 57 | { `Set{ { `Id "_nil", `Id "_false", `Id "_true", `Id "_dots" }, { `Nil, `Boolean "false", `Boolean "true", `Dots } } } 58 | ]=] 59 | 60 | r = parse(s) 61 | assert(r == e) 62 | 63 | -- floating points 64 | 65 | s = [=[ 66 | f1 = 1. 67 | f2 = 1.1 68 | ]=] 69 | e = [=[ 70 | { `Set{ { `Id "f1" }, { `Number "1.0" } }, `Set{ { `Id "f2" }, { `Number "1.1" } } } 71 | ]=] 72 | 73 | r = parse(s) 74 | assert(r == fixint(e)) 75 | 76 | s = [=[ 77 | f1 = 1.e-1 78 | f2 = 1.e1 79 | ]=] 80 | e = [=[ 81 | { `Set{ { `Id "f1" }, { `Number "0.1" } }, `Set{ { `Id "f2" }, { `Number "10.0" } } } 82 | ]=] 83 | 84 | r = parse(s) 85 | assert(r == fixint(e)) 86 | 87 | s = [=[ 88 | f1 = 1.1e+1 89 | f2 = 1.1e1 90 | ]=] 91 | e = [=[ 92 | { `Set{ { `Id "f1" }, { `Number "11.0" } }, `Set{ { `Id "f2" }, { `Number "11.0" } } } 93 | ]=] 94 | 95 | r = parse(s) 96 | assert(r == fixint(e)) 97 | 98 | s = [=[ 99 | f1 = .1 100 | f2 = .1e1 101 | ]=] 102 | e = [=[ 103 | { `Set{ { `Id "f1" }, { `Number "0.1" } }, `Set{ { `Id "f2" }, { `Number "1.0" } } } 104 | ]=] 105 | 106 | r = parse(s) 107 | assert(r == fixint(e)) 108 | 109 | s = [=[ 110 | f1 = 1E1 111 | f2 = 1e-1 112 | ]=] 113 | e = [=[ 114 | { `Set{ { `Id "f1" }, { `Number "10.0" } }, `Set{ { `Id "f2" }, { `Number "0.1" } } } 115 | ]=] 116 | 117 | r = parse(s) 118 | assert(r == fixint(e)) 119 | 120 | -- integers 121 | 122 | s = [=[ 123 | i = 1 124 | h = 0xff 125 | ]=] 126 | e = [=[ 127 | { `Set{ { `Id "i" }, { `Number "1" } }, `Set{ { `Id "h" }, { `Number "255" } } } 128 | ]=] 129 | 130 | r = parse(s) 131 | assert(r == e) 132 | 133 | s = [=[ 134 | h = 0x76c 135 | i = 4294967296 -- 2^32 136 | ]=] 137 | e = [=[ 138 | { `Set{ { `Id "h" }, { `Number "1900" } }, `Set{ { `Id "i" }, { `Number "4294967296" } } } 139 | ]=] 140 | 141 | r = parse(s) 142 | assert(r == e) 143 | 144 | -- long comments 145 | 146 | s = [=[ 147 | --[======[ 148 | testing 149 | long 150 | comment 151 | [==[ one ]==] 152 | [===[ more ]===] 153 | [====[ time ]====] 154 | bye 155 | ]======] 156 | ]=] 157 | e = [=[ 158 | { } 159 | ]=] 160 | 161 | r = parse(s) 162 | assert(r == e) 163 | 164 | -- long strings 165 | 166 | s = [=[ 167 | --[[ 168 | testing long string1 begin 169 | ]] 170 | 171 | ls1 = 172 | [[ 173 | testing long string 174 | ]] 175 | 176 | --[[ 177 | testing long string1 end 178 | ]] 179 | ]=] 180 | e = [=[ 181 | { `Set{ { `Id "ls1" }, { `String "testing long string\n" } } } 182 | ]=] 183 | 184 | r = parse(s) 185 | assert(r == e) 186 | 187 | s = [=[ 188 | --[==[ 189 | testing long string2 begin 190 | ]==] 191 | 192 | ls2 = [==[ testing \n [[ long ]] \t [===[ string ]===] 193 | \a ]==] 194 | 195 | --[==[ 196 | [[ testing long string2 end ]] 197 | ]==] 198 | ]=] 199 | e = [=[ 200 | { `Set{ { `Id "ls2" }, { `String " testing \\n [[ long ]] \\t [===[ string ]===]\n\\a " } } } 201 | ]=] 202 | 203 | r = parse(s) 204 | assert(r == e) 205 | 206 | -- short strings 207 | 208 | s = [=[ 209 | -- short string test begin 210 | 211 | ss1_a = "ola mundo\a" 212 | ss1_b = 'ola mundo\a' 213 | 214 | -- short string test end 215 | ]=] 216 | e = [=[ 217 | { `Set{ { `Id "ss1_a" }, { `String "ola mundo\a" } }, `Set{ { `Id "ss1_b" }, { `String "ola mundo\a" } } } 218 | ]=] 219 | 220 | r = parse(s) 221 | assert(r == e) 222 | 223 | s = [=[ 224 | -- short string test begin 225 | 226 | ss2_a = "testando,\tteste\n1\n2\n3 --> \"tchau\"" 227 | ss2_b = 'testando,\tteste\n1\n2\n3 --> \'tchau\'' 228 | 229 | -- short string test end 230 | ]=] 231 | e = [=[ 232 | { `Set{ { `Id "ss2_a" }, { `String "testando,\tteste\n1\n2\n3 --> \"tchau\"" } }, `Set{ { `Id "ss2_b" }, { `String "testando,\tteste\n1\n2\n3 --> 'tchau'" } } } 233 | ]=] 234 | 235 | r = parse(s) 236 | assert(r == e) 237 | 238 | s = [=[ 239 | -- short string test begin 240 | 241 | ss3_a = "ola \ 242 | 'mundo'!" 243 | 244 | ss3_b = 'ola \ 245 | "mundo"!' 246 | 247 | -- short string test end 248 | ]=] 249 | e = [=[ 250 | { `Set{ { `Id "ss3_a" }, { `String "ola \n'mundo'!" } }, `Set{ { `Id "ss3_b" }, { `String "ola \n\"mundo\"!" } } } 251 | ]=] 252 | 253 | r = parse(s) 254 | assert(r == e) 255 | 256 | s = [=[ 257 | -- short string test begin 258 | 259 | ss4_a = "C:\\Temp/" 260 | 261 | ss4_b = 'C:\\Temp/' 262 | 263 | -- short string test end 264 | ]=] 265 | e = [=[ 266 | { `Set{ { `Id "ss4_a" }, { `String "C:\\Temp/" } }, `Set{ { `Id "ss4_b" }, { `String "C:\\Temp/" } } } 267 | ]=] 268 | 269 | r = parse(s) 270 | assert(r == e) 271 | 272 | s = [=[ 273 | -- short string test begin 274 | 275 | lf = "\\n" 276 | 277 | -- short string test end 278 | ]=] 279 | e = [=[ 280 | { `Set{ { `Id "lf" }, { `String "\\n" } } } 281 | ]=] 282 | 283 | r = parse(s) 284 | assert(r == e) 285 | 286 | s = [=[ 287 | -- short string test begin 288 | 289 | ss5_a = "ola \ 290 | mundo \\ \ 291 | cruel" 292 | 293 | ss5_b = 'ola \ 294 | mundo \\ \ 295 | cruel' 296 | 297 | -- short string test end 298 | ]=] 299 | e = [=[ 300 | { `Set{ { `Id "ss5_a" }, { `String "ola \nmundo \\ \ncruel" } }, `Set{ { `Id "ss5_b" }, { `String "ola \nmundo \\ \ncruel" } } } 301 | ]=] 302 | 303 | r = parse(s) 304 | assert(r == e) 305 | 306 | s = [=[ 307 | -- short string test begin 308 | 309 | s1 = 'a \z b' 310 | s2 = "adeus \z 311 | mundo\ 312 | \z maravilhoso" 313 | 314 | -- short string test end 315 | ]=] 316 | e = [=[ 317 | { `Set{ { `Id "s1" }, { `String "a b" } }, `Set{ { `Id "s2" }, { `String "adeus mundo\nmaravilhoso" } } } 318 | ]=] 319 | 320 | r = parse(s) 321 | assert(r == e) 322 | 323 | s = [=[ 324 | -- short string test begin 325 | 326 | deci = '\28' 327 | hex = '\x1C' 328 | uni = '\u{001C}' 329 | 330 | -- short string test end 331 | ]=] 332 | e = [=[ 333 | { `Set{ { `Id "deci" }, { `String "\028" } }, `Set{ { `Id "hex" }, { `String "\028" } }, `Set{ { `Id "uni" }, { `String "\028" } } } 334 | ]=] 335 | 336 | r = parse(s) 337 | assert(r == e) 338 | 339 | -- syntax error 340 | 341 | -- floating points 342 | 343 | s = [=[ 344 | f = 9e 345 | ]=] 346 | e = [=[ 347 | test.lua:2:1: syntax error, expected one or more digits for the exponent 348 | ]=] 349 | 350 | r = parse(s) 351 | assert(r == e) 352 | 353 | s = [=[ 354 | f = 5.e 355 | ]=] 356 | e = [=[ 357 | test.lua:2:1: syntax error, expected one or more digits for the exponent 358 | ]=] 359 | 360 | r = parse(s) 361 | assert(r == e) 362 | 363 | s = [=[ 364 | f = .9e- 365 | ]=] 366 | e = [=[ 367 | test.lua:2:1: syntax error, expected one or more digits for the exponent 368 | ]=] 369 | 370 | r = parse(s) 371 | assert(r == e) 372 | 373 | s = [=[ 374 | f = 5.9e+ 375 | ]=] 376 | e = [=[ 377 | test.lua:2:1: syntax error, expected one or more digits for the exponent 378 | ]=] 379 | 380 | r = parse(s) 381 | assert(r == e) 382 | 383 | -- integers 384 | 385 | s = [=[ 386 | -- invalid hexadecimal number 387 | 388 | hex = 0xG 389 | ]=] 390 | e = [=[ 391 | test.lua:3:9: syntax error, expected one or more hexadecimal digits after '0x' 392 | ]=] 393 | 394 | r = parse(s) 395 | assert(r == e) 396 | 397 | -- long strings 398 | 399 | s = [=[ 400 | --[==[ 401 | testing long string3 begin 402 | ]==] 403 | 404 | ls3 = [===[ 405 | testing 406 | unfinised 407 | long string 408 | ]==] 409 | 410 | --[==[ 411 | [[ testing long string3 end ]] 412 | ]==] 413 | ]=] 414 | e = [=[ 415 | test.lua:14:1: syntax error, unclosed long string 416 | ]=] 417 | 418 | r = parse(s) 419 | assert(r == e) 420 | 421 | -- short strings 422 | 423 | s = [=[ 424 | -- short string test begin 425 | 426 | ss6 = "testing unfinished string 427 | 428 | -- short string test end 429 | ]=] 430 | e = [=[ 431 | test.lua:4:1: syntax error, unclosed string 432 | ]=] 433 | 434 | r = parse(s) 435 | assert(r == e) 436 | 437 | s = [=[ 438 | -- short string test begin 439 | 440 | ss7 = 'testing \\ 441 | unfinished \\ 442 | string' 443 | 444 | -- short string test end 445 | ]=] 446 | e = [=[ 447 | test.lua:4:1: syntax error, unclosed string 448 | ]=] 449 | 450 | r = parse(s) 451 | assert(r == e) 452 | 453 | -- unfinished comments 454 | 455 | s = [=[ 456 | --[[ testing 457 | unfinished 458 | comment 459 | ]=] 460 | e = [=[ 461 | test.lua:4:1: syntax error, unclosed long string 462 | ]=] 463 | 464 | r = parse(s) 465 | assert(r == e) 466 | 467 | print("> testing parser...") 468 | 469 | -- syntax ok 470 | 471 | -- anonymous functions 472 | 473 | s = [=[ 474 | local a,b,c = function () end 475 | ]=] 476 | e = [=[ 477 | { `Local{ { `Id "a", `Id "b", `Id "c" }, { `Function{ { }, { } } } } } 478 | ]=] 479 | 480 | r = parse(s) 481 | assert(r == e) 482 | 483 | s = [=[ 484 | local test = function ( a , b , ... ) end 485 | ]=] 486 | e = [=[ 487 | { `Local{ { `Id "test" }, { `Function{ { `Id "a", `Id "b", `Dots }, { } } } } } 488 | ]=] 489 | 490 | r = parse(s) 491 | assert(r == e) 492 | 493 | s = [=[ 494 | test = function (...) return ...,0 end 495 | ]=] 496 | e = [=[ 497 | { `Set{ { `Id "test" }, { `Function{ { `Dots }, { `Return{ `Dots, `Number "0" } } } } } } 498 | ]=] 499 | 500 | r = parse(s) 501 | assert(r == e) 502 | 503 | -- arithmetic expressions 504 | 505 | s = [=[ 506 | arithmetic = 1 - 2 * 3 + 4 507 | ]=] 508 | e = [=[ 509 | { `Set{ { `Id "arithmetic" }, { `Op{ "add", `Op{ "sub", `Number "1", `Op{ "mul", `Number "2", `Number "3" } }, `Number "4" } } } } 510 | ]=] 511 | 512 | r = parse(s) 513 | assert(r == e) 514 | 515 | s = [=[ 516 | pow = -3^-2^2 517 | ]=] 518 | e = [=[ 519 | { `Set{ { `Id "pow" }, { `Op{ "unm", `Op{ "pow", `Number "3", `Op{ "unm", `Op{ "pow", `Number "2", `Number "2" } } } } } } } 520 | ]=] 521 | 522 | r = parse(s) 523 | assert(r == e) 524 | 525 | s = [=[ 526 | q, r, f = 3//2, 3%2, 3/2 527 | ]=] 528 | e = [=[ 529 | { `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" } } } } 530 | ]=] 531 | 532 | r = parse(s) 533 | assert(r == e) 534 | 535 | -- assignments 536 | 537 | s = [=[ 538 | a = f()[1] 539 | ]=] 540 | e = [=[ 541 | { `Set{ { `Id "a" }, { `Index{ `Call{ `Id "f" }, `Number "1" } } } } 542 | ]=] 543 | 544 | r = parse(s) 545 | assert(r == e) 546 | 547 | s = [=[ 548 | a()[1] = 1; 549 | ]=] 550 | e = [=[ 551 | { `Set{ { `Index{ `Call{ `Id "a" }, `Number "1" } }, { `Number "1" } } } 552 | ]=] 553 | 554 | r = parse(s) 555 | assert(r == e) 556 | 557 | s = [=[ 558 | i = a.f(1) 559 | ]=] 560 | e = [=[ 561 | { `Set{ { `Id "i" }, { `Call{ `Index{ `Id "a", `String "f" }, `Number "1" } } } } 562 | ]=] 563 | 564 | r = parse(s) 565 | assert(r == e) 566 | 567 | s = [=[ 568 | i = a[f(1)] 569 | ]=] 570 | e = [=[ 571 | { `Set{ { `Id "i" }, { `Index{ `Id "a", `Call{ `Id "f", `Number "1" } } } } } 572 | ]=] 573 | 574 | r = parse(s) 575 | assert(r == e) 576 | 577 | s = [=[ 578 | a[f()] = sub 579 | i = i + 1 580 | ]=] 581 | e = [=[ 582 | { `Set{ { `Index{ `Id "a", `Call{ `Id "f" } } }, { `Id "sub" } }, `Set{ { `Id "i" }, { `Op{ "add", `Id "i", `Number "1" } } } } 583 | ]=] 584 | 585 | r = parse(s) 586 | assert(r == e) 587 | 588 | s = [=[ 589 | a:b(1)._ = some_value 590 | ]=] 591 | e = [=[ 592 | { `Set{ { `Index{ `Invoke{ `Id "a", `String "b", `Number "1" }, `String "_" } }, { `Id "some_value" } } } 593 | ]=] 594 | 595 | r = parse(s) 596 | assert(r == e) 597 | 598 | -- bitwise expressions 599 | 600 | s = [=[ 601 | b = 1 & 0 | 1 ~ 1 602 | ]=] 603 | e = [=[ 604 | { `Set{ { `Id "b" }, { `Op{ "bor", `Op{ "band", `Number "1", `Number "0" }, `Op{ "bxor", `Number "1", `Number "1" } } } } } 605 | ]=] 606 | 607 | r = parse(s) 608 | assert(r == e) 609 | 610 | s = [=[ 611 | b = 1 & 0 | 1 >> 1 ~ 1 612 | ]=] 613 | e = [=[ 614 | { `Set{ { `Id "b" }, { `Op{ "bor", `Op{ "band", `Number "1", `Number "0" }, `Op{ "bxor", `Op{ "shr", `Number "1", `Number "1" }, `Number "1" } } } } } 615 | ]=] 616 | 617 | r = parse(s) 618 | assert(r == e) 619 | 620 | -- break 621 | 622 | s = [=[ 623 | while 1 do 624 | break 625 | end 626 | ]=] 627 | e = [=[ 628 | { `While{ `Number "1", { `Break } } } 629 | ]=] 630 | 631 | r = parse(s) 632 | assert(r == e) 633 | 634 | s = [=[ 635 | while 1 do 636 | while 1 do 637 | break 638 | end 639 | break 640 | end 641 | ]=] 642 | e = [=[ 643 | { `While{ `Number "1", { `While{ `Number "1", { `Break } }, `Break } } } 644 | ]=] 645 | 646 | r = parse(s) 647 | assert(r == e) 648 | 649 | s = [=[ 650 | repeat 651 | if 2 > 1 then break end 652 | until 1 653 | ]=] 654 | e = [=[ 655 | { `Repeat{ { `If{ `Op{ "gt", `Number "2", `Number "1" }, { `Break } } }, `Number "1" } } 656 | ]=] 657 | 658 | r = parse(s) 659 | assert(r == e) 660 | 661 | s = [=[ 662 | for i=1,10 do 663 | do 664 | break 665 | break 666 | return 667 | end 668 | end 669 | ]=] 670 | e = [=[ 671 | { `Fornum{ `Id "i", `Number "1", `Number "10", { `Do{ `Break, `Break, `Return } } } } 672 | ]=] 673 | 674 | r = parse(s) 675 | assert(r == e) 676 | 677 | -- block statements 678 | 679 | s = [=[ 680 | do 681 | var = 2+2; 682 | return 683 | end 684 | ]=] 685 | e = [=[ 686 | { `Do{ `Set{ { `Id "var" }, { `Op{ "add", `Number "2", `Number "2" } } }, `Return } } 687 | ]=] 688 | 689 | r = parse(s) 690 | assert(r == e) 691 | 692 | -- concatenation expressions 693 | 694 | s = [=[ 695 | concat1 = 1 .. 2^3 696 | ]=] 697 | e = [=[ 698 | { `Set{ { `Id "concat1" }, { `Op{ "concat", `Number "1", `Op{ "pow", `Number "2", `Number "3" } } } } } 699 | ]=] 700 | 701 | r = parse(s) 702 | assert(r == e) 703 | 704 | -- empty files 705 | 706 | s = [=[ 707 | ; 708 | ]=] 709 | e = [=[ 710 | { } 711 | ]=] 712 | 713 | r = parse(s) 714 | assert(r == e) 715 | 716 | -- for generic 717 | 718 | s = [=[ 719 | for k,v in pairs(t) do print (k,v) end 720 | ]=] 721 | e = [=[ 722 | { `Forin{ { `Id "k", `Id "v" }, { `Call{ `Id "pairs", `Id "t" } }, { `Call{ `Id "print", `Id "k", `Id "v" } } } } 723 | ]=] 724 | 725 | r = parse(s) 726 | assert(r == e) 727 | 728 | -- for numeric 729 | 730 | s = [=[ 731 | for i = 1 , 10 , 2 do end 732 | ]=] 733 | e = [=[ 734 | { `Fornum{ `Id "i", `Number "1", `Number "10", `Number "2", { } } } 735 | ]=] 736 | 737 | r = parse(s) 738 | assert(r == e) 739 | 740 | s = [=[ 741 | for i=1,10 do end 742 | ]=] 743 | e = [=[ 744 | { `Fornum{ `Id "i", `Number "1", `Number "10", { } } } 745 | ]=] 746 | 747 | r = parse(s) 748 | assert(r == e) 749 | 750 | -- global functions 751 | 752 | s = [=[ 753 | function test(a , b , ...) end 754 | ]=] 755 | e = [=[ 756 | { `Set{ { `Id "test" }, { `Function{ { `Id "a", `Id "b", `Dots }, { } } } } } 757 | ]=] 758 | 759 | r = parse(s) 760 | assert(r == e) 761 | 762 | s = [=[ 763 | function test (...) end 764 | ]=] 765 | e = [=[ 766 | { `Set{ { `Id "test" }, { `Function{ { `Dots }, { } } } } } 767 | ]=] 768 | 769 | r = parse(s) 770 | assert(r == e) 771 | 772 | s = [=[ 773 | function t.a:b() end 774 | ]=] 775 | e = [=[ 776 | { `Set{ { `Index{ `Index{ `Id "t", `String "a" }, `String "b" } }, { `Function{ { `Id "self" }, { } } } } } 777 | ]=] 778 | 779 | r = parse(s) 780 | assert(r == e) 781 | 782 | s = [=[ 783 | function t.a() end 784 | ]=] 785 | e = [=[ 786 | { `Set{ { `Index{ `Id "t", `String "a" } }, { `Function{ { }, { } } } } } 787 | ]=] 788 | 789 | r = parse(s) 790 | assert(r == e) 791 | 792 | s = [=[ 793 | function testando . funcao . com : espcacos ( e, com , parametros, ... ) end 794 | ]=] 795 | e = [=[ 796 | { `Set{ { `Index{ `Index{ `Index{ `Id "testando", `String "funcao" }, `String "com" }, `String "espcacos" } }, { `Function{ { `Id "self", `Id "e", `Id "com", `Id "parametros", `Dots }, { } } } } } 797 | ]=] 798 | 799 | r = parse(s) 800 | assert(r == e) 801 | 802 | -- goto 803 | 804 | s = [=[ 805 | goto label 806 | :: label :: return 807 | ]=] 808 | e = [=[ 809 | { `Goto{ "label" }, `Label{ "label" }, `Return } 810 | ]=] 811 | 812 | r = parse(s) 813 | assert(r == e) 814 | 815 | s = [=[ 816 | ::label:: 817 | goto label 818 | ]=] 819 | e = [=[ 820 | { `Label{ "label" }, `Goto{ "label" } } 821 | ]=] 822 | 823 | r = parse(s) 824 | assert(r == e) 825 | 826 | s = [=[ 827 | goto label 828 | ::label:: 829 | ]=] 830 | e = [=[ 831 | { `Goto{ "label" }, `Label{ "label" } } 832 | ]=] 833 | 834 | r = parse(s) 835 | assert(r == e) 836 | 837 | s = [=[ 838 | ::label:: 839 | do ::label:: goto label end 840 | ]=] 841 | e = [=[ 842 | { `Label{ "label" }, `Do{ `Label{ "label" }, `Goto{ "label" } } } 843 | ]=] 844 | 845 | r = parse(s) 846 | assert(r == e) 847 | 848 | s = [=[ 849 | ::label:: 850 | do goto label ; ::label:: end 851 | ]=] 852 | e = [=[ 853 | { `Label{ "label" }, `Do{ `Goto{ "label" }, `Label{ "label" } } } 854 | ]=] 855 | 856 | r = parse(s) 857 | assert(r == e) 858 | 859 | s = [=[ 860 | ::label:: 861 | do goto label end 862 | ]=] 863 | e = [=[ 864 | { `Label{ "label" }, `Do{ `Goto{ "label" } } } 865 | ]=] 866 | 867 | r = parse(s) 868 | assert(r == e) 869 | 870 | s = [=[ 871 | do goto label end 872 | ::label:: 873 | ]=] 874 | e = [=[ 875 | { `Do{ `Goto{ "label" } }, `Label{ "label" } } 876 | ]=] 877 | 878 | r = parse(s) 879 | assert(r == e) 880 | 881 | s = [=[ 882 | do do do do do goto label end end end end end 883 | ::label:: 884 | ]=] 885 | e = [=[ 886 | { `Do{ `Do{ `Do{ `Do{ `Do{ `Goto{ "label" } } } } } }, `Label{ "label" } } 887 | ]=] 888 | 889 | r = parse(s) 890 | assert(r == e) 891 | 892 | -- if-else 893 | 894 | s = [=[ 895 | if a then end 896 | ]=] 897 | e = [=[ 898 | { `If{ `Id "a", { } } } 899 | ]=] 900 | 901 | r = parse(s) 902 | assert(r == e) 903 | 904 | s = [=[ 905 | if a then return a else return end 906 | ]=] 907 | e = [=[ 908 | { `If{ `Id "a", { `Return{ `Id "a" } }, { `Return } } } 909 | ]=] 910 | 911 | r = parse(s) 912 | assert(r == e) 913 | 914 | s = [=[ 915 | if a then 916 | return a 917 | else 918 | local c = d 919 | d = d + 1 920 | return d 921 | end 922 | ]=] 923 | e = [=[ 924 | { `If{ `Id "a", { `Return{ `Id "a" } }, { `Local{ { `Id "c" }, { `Id "d" } }, `Set{ { `Id "d" }, { `Op{ "add", `Id "d", `Number "1" } } }, `Return{ `Id "d" } } } } 925 | ]=] 926 | 927 | r = parse(s) 928 | assert(r == e) 929 | 930 | s = [=[ 931 | if a then 932 | return a 933 | elseif b then 934 | return b 935 | elseif c then 936 | return c 937 | end 938 | ]=] 939 | e = [=[ 940 | { `If{ `Id "a", { `Return{ `Id "a" } }, `Id "b", { `Return{ `Id "b" } }, `Id "c", { `Return{ `Id "c" } } } } 941 | ]=] 942 | 943 | r = parse(s) 944 | assert(r == e) 945 | 946 | s = [=[ 947 | if a then return a 948 | elseif b then return 949 | else ; 950 | end 951 | ]=] 952 | e = [=[ 953 | { `If{ `Id "a", { `Return{ `Id "a" } }, `Id "b", { `Return }, { } } } 954 | ]=] 955 | 956 | r = parse(s) 957 | assert(r == e) 958 | 959 | s = [=[ 960 | if a then 961 | return 962 | elseif c then 963 | end 964 | ]=] 965 | e = [=[ 966 | { `If{ `Id "a", { `Return }, `Id "c", { } } } 967 | ]=] 968 | 969 | r = parse(s) 970 | assert(r == e) 971 | 972 | -- labels 973 | 974 | s = [=[ 975 | ::label:: 976 | do ::label:: end 977 | ::other_label:: 978 | ]=] 979 | e = [=[ 980 | { `Label{ "label" }, `Do{ `Label{ "label" } }, `Label{ "other_label" } } 981 | ]=] 982 | 983 | r = parse(s) 984 | assert(r == e) 985 | 986 | s = [=[ 987 | local x = glob 988 | ::label:: 989 | foo() 990 | ]=] 991 | e = [=[ 992 | { `Local{ { `Id "x" }, { `Id "glob" } }, `Label{ "label" }, `Call{ `Id "foo" } } 993 | ]=] 994 | 995 | r = parse(s) 996 | assert(r == e) 997 | 998 | -- locals 999 | 1000 | s = [=[ 1001 | local a 1002 | ]=] 1003 | e = [=[ 1004 | { `Local{ { `Id "a" }, { } } } 1005 | ]=] 1006 | 1007 | r = parse(s) 1008 | assert(r == e) 1009 | 1010 | s = [=[ 1011 | local a,b,c 1012 | ]=] 1013 | e = [=[ 1014 | { `Local{ { `Id "a", `Id "b", `Id "c" }, { } } } 1015 | ]=] 1016 | 1017 | r = parse(s) 1018 | assert(r == e) 1019 | 1020 | s = [=[ 1021 | local a = 1 , 1 + 2, 5.1 1022 | ]=] 1023 | e = [=[ 1024 | { `Local{ { `Id "a" }, { `Number "1", `Op{ "add", `Number "1", `Number "2" }, `Number "5.1" } } } 1025 | ]=] 1026 | 1027 | r = parse(s) 1028 | assert(r == e) 1029 | 1030 | s = [=[ 1031 | local a,b,c = 1.9 1032 | ]=] 1033 | e = [=[ 1034 | { `Local{ { `Id "a", `Id "b", `Id "c" }, { `Number "1.9" } } } 1035 | ]=] 1036 | 1037 | r = parse(s) 1038 | assert(r == e) 1039 | 1040 | s = [=[ 1041 | local function test() end 1042 | ]=] 1043 | e = [=[ 1044 | { `Localrec{ { `Id "test" }, { `Function{ { }, { } } } } } 1045 | ]=] 1046 | 1047 | r = parse(s) 1048 | assert(r == e) 1049 | 1050 | s = [=[ 1051 | local function test ( a , b , c , ... ) end 1052 | ]=] 1053 | e = [=[ 1054 | { `Localrec{ { `Id "test" }, { `Function{ { `Id "a", `Id "b", `Id "c", `Dots }, { } } } } } 1055 | ]=] 1056 | 1057 | r = parse(s) 1058 | assert(r == e) 1059 | 1060 | s = [=[ 1061 | local function test(...) return ... end 1062 | ]=] 1063 | e = [=[ 1064 | { `Localrec{ { `Id "test" }, { `Function{ { `Dots }, { `Return{ `Dots } } } } } } 1065 | ]=] 1066 | 1067 | r = parse(s) 1068 | assert(r == e) 1069 | 1070 | -- relational expressions 1071 | 1072 | s = [=[ 1073 | relational = 1 < 2 >= 3 == 4 ~= 5 < 6 <= 7 1074 | ]=] 1075 | e = [=[ 1076 | { `Set{ { `Id "relational" }, { `Op{ "le", `Op{ "lt", `Op{ "ne", `Op{ "eq", `Op{ "ge", `Op{ "lt", `Number "1", `Number "2" }, `Number "3" }, `Number "4" }, `Number "5" }, `Number "6" }, `Number "7" } } } } 1077 | ]=] 1078 | 1079 | r = parse(s) 1080 | assert(r == e) 1081 | 1082 | -- repeat 1083 | 1084 | s = [=[ 1085 | repeat 1086 | a,b,c = 1+1,2+2,3+3 1087 | break 1088 | until a < 1 1089 | ]=] 1090 | e = [=[ 1091 | { `Repeat{ { `Set{ { `Id "a", `Id "b", `Id "c" }, { `Op{ "add", `Number "1", `Number "1" }, `Op{ "add", `Number "2", `Number "2" }, `Op{ "add", `Number "3", `Number "3" } } }, `Break }, `Op{ "lt", `Id "a", `Number "1" } } } 1092 | ]=] 1093 | 1094 | r = parse(s) 1095 | assert(r == e) 1096 | 1097 | -- return 1098 | 1099 | s = [=[ 1100 | return 1101 | ]=] 1102 | e = [=[ 1103 | { `Return } 1104 | ]=] 1105 | 1106 | r = parse(s) 1107 | assert(r == e) 1108 | 1109 | s = [=[ 1110 | return 1 1111 | ]=] 1112 | e = [=[ 1113 | { `Return{ `Number "1" } } 1114 | ]=] 1115 | 1116 | r = parse(s) 1117 | assert(r == e) 1118 | 1119 | s = [=[ 1120 | return 1,1-2*3+4,"alo" 1121 | ]=] 1122 | e = [=[ 1123 | { `Return{ `Number "1", `Op{ "add", `Op{ "sub", `Number "1", `Op{ "mul", `Number "2", `Number "3" } }, `Number "4" }, `String "alo" } } 1124 | ]=] 1125 | 1126 | r = parse(s) 1127 | assert(r == e) 1128 | 1129 | s = [=[ 1130 | return; 1131 | ]=] 1132 | e = [=[ 1133 | { `Return } 1134 | ]=] 1135 | 1136 | r = parse(s) 1137 | assert(r == e) 1138 | 1139 | s = [=[ 1140 | return 1; 1141 | ]=] 1142 | e = [=[ 1143 | { `Return{ `Number "1" } } 1144 | ]=] 1145 | 1146 | r = parse(s) 1147 | assert(r == e) 1148 | 1149 | s = [=[ 1150 | return 1,1-2*3+4,"alo"; 1151 | ]=] 1152 | e = [=[ 1153 | { `Return{ `Number "1", `Op{ "add", `Op{ "sub", `Number "1", `Op{ "mul", `Number "2", `Number "3" } }, `Number "4" }, `String "alo" } } 1154 | ]=] 1155 | 1156 | r = parse(s) 1157 | assert(r == e) 1158 | 1159 | -- tables 1160 | 1161 | s = [=[ 1162 | t = { [1] = "alo", alo = 1, 2; } 1163 | ]=] 1164 | e = [=[ 1165 | { `Set{ { `Id "t" }, { `Table{ `Pair{ `Number "1", `String "alo" }, `Pair{ `String "alo", `Number "1" }, `Number "2" } } } } 1166 | ]=] 1167 | 1168 | r = parse(s) 1169 | assert(r == e) 1170 | 1171 | s = [=[ 1172 | t = { 1.5 } 1173 | ]=] 1174 | e = [=[ 1175 | { `Set{ { `Id "t" }, { `Table{ `Number "1.5" } } } } 1176 | ]=] 1177 | 1178 | r = parse(s) 1179 | assert(r == e) 1180 | 1181 | s = [=[ 1182 | t = {1,2; 1183 | 3, 1184 | 4, 1185 | 1186 | 1187 | 1188 | 5} 1189 | ]=] 1190 | e = [=[ 1191 | { `Set{ { `Id "t" }, { `Table{ `Number "1", `Number "2", `Number "3", `Number "4", `Number "5" } } } } 1192 | ]=] 1193 | 1194 | r = parse(s) 1195 | assert(r == e) 1196 | 1197 | s = [=[ 1198 | t = {[1]=1,[2]=2; 1199 | [3]=3, 1200 | [4]=4, 1201 | 1202 | 1203 | 1204 | [5]=5} 1205 | ]=] 1206 | e = [=[ 1207 | { `Set{ { `Id "t" }, { `Table{ `Pair{ `Number "1", `Number "1" }, `Pair{ `Number "2", `Number "2" }, `Pair{ `Number "3", `Number "3" }, `Pair{ `Number "4", `Number "4" }, `Pair{ `Number "5", `Number "5" } } } } } 1208 | ]=] 1209 | 1210 | r = parse(s) 1211 | assert(r == e) 1212 | 1213 | s = [=[ 1214 | local t = {{{}}, {"alo"}} 1215 | ]=] 1216 | e = [=[ 1217 | { `Local{ { `Id "t" }, { `Table{ `Table{ `Table }, `Table{ `String "alo" } } } } } 1218 | ]=] 1219 | 1220 | r = parse(s) 1221 | assert(r == e) 1222 | 1223 | s = [=[ 1224 | local x = 0 1225 | local t = {x} 1226 | ]=] 1227 | e = [=[ 1228 | { `Local{ { `Id "x" }, { `Number "0" } }, `Local{ { `Id "t" }, { `Table{ `Id "x" } } } } 1229 | ]=] 1230 | 1231 | r = parse(s) 1232 | assert(r == e) 1233 | 1234 | s = [=[ 1235 | local x = 0 1236 | local t = {x = 1} 1237 | ]=] 1238 | e = [=[ 1239 | { `Local{ { `Id "x" }, { `Number "0" } }, `Local{ { `Id "t" }, { `Table{ `Pair{ `String "x", `Number "1" } } } } } 1240 | ]=] 1241 | 1242 | r = parse(s) 1243 | assert(r == e) 1244 | 1245 | s = [=[ 1246 | local x = 0 1247 | local t = {x == 1} 1248 | ]=] 1249 | e = [=[ 1250 | { `Local{ { `Id "x" }, { `Number "0" } }, `Local{ { `Id "t" }, { `Table{ `Op{ "eq", `Id "x", `Number "1" } } } } } 1251 | ]=] 1252 | 1253 | r = parse(s) 1254 | assert(r == e) 1255 | 1256 | -- vararg 1257 | 1258 | s = [=[ 1259 | function f (...) 1260 | return ... 1261 | end 1262 | ]=] 1263 | e = [=[ 1264 | { `Set{ { `Id "f" }, { `Function{ { `Dots }, { `Return{ `Dots } } } } } } 1265 | ]=] 1266 | 1267 | r = parse(s) 1268 | assert(r == e) 1269 | 1270 | s = [=[ 1271 | function f () 1272 | function g (x, y, ...) 1273 | return ...,...,... 1274 | end 1275 | end 1276 | ]=] 1277 | e = [=[ 1278 | { `Set{ { `Id "f" }, { `Function{ { }, { `Set{ { `Id "g" }, { `Function{ { `Id "x", `Id "y", `Dots }, { `Return{ `Dots, `Dots, `Dots } } } } } } } } } } 1279 | ]=] 1280 | 1281 | r = parse(s) 1282 | assert(r == e) 1283 | 1284 | s = [=[ 1285 | local function f (x, ...) 1286 | return ... 1287 | end 1288 | ]=] 1289 | e = [=[ 1290 | { `Localrec{ { `Id "f" }, { `Function{ { `Id "x", `Dots }, { `Return{ `Dots } } } } } } 1291 | ]=] 1292 | 1293 | r = parse(s) 1294 | assert(r == e) 1295 | 1296 | s = [=[ 1297 | local f = function (x, ...) 1298 | return ... 1299 | end 1300 | ]=] 1301 | e = [=[ 1302 | { `Local{ { `Id "f" }, { `Function{ { `Id "x", `Dots }, { `Return{ `Dots } } } } } } 1303 | ]=] 1304 | 1305 | r = parse(s) 1306 | assert(r == e) 1307 | 1308 | -- while 1309 | 1310 | s = [=[ 1311 | i = 0 1312 | while (i < 10) 1313 | do 1314 | i = i + 1 1315 | end 1316 | ]=] 1317 | e = [=[ 1318 | { `Set{ { `Id "i" }, { `Number "0" } }, `While{ `Paren{ `Op{ "lt", `Id "i", `Number "10" } }, { `Set{ { `Id "i" }, { `Op{ "add", `Id "i", `Number "1" } } } } } } 1319 | ]=] 1320 | 1321 | r = parse(s) 1322 | assert(r == e) 1323 | 1324 | -- syntax error 1325 | 1326 | -- anonymous functions 1327 | 1328 | s = [=[ 1329 | a = function (a,b,) end 1330 | ]=] 1331 | e = [=[ 1332 | test.lua:1:19: syntax error, expected a variable name or '...' after ',' 1333 | ]=] 1334 | 1335 | r = parse(s) 1336 | assert(r == e) 1337 | 1338 | s = [=[ 1339 | a = function (...,a) end 1340 | ]=] 1341 | e = [=[ 1342 | test.lua:1:18: syntax error, expected ')' to close the parameter list 1343 | ]=] 1344 | 1345 | r = parse(s) 1346 | assert(r == e) 1347 | 1348 | s = [=[ 1349 | local a = function (1) end 1350 | ]=] 1351 | e = [=[ 1352 | test.lua:1:21: syntax error, expected ')' to close the parameter list 1353 | ]=] 1354 | 1355 | r = parse(s) 1356 | assert(r == e) 1357 | 1358 | s = [=[ 1359 | local test = function ( a , b , c , ... ) 1360 | ]=] 1361 | e = [=[ 1362 | test.lua:2:1: syntax error, expected 'end' to close the function body 1363 | ]=] 1364 | 1365 | r = parse(s) 1366 | assert(r == e) 1367 | 1368 | -- arithmetic expressions 1369 | 1370 | s = [=[ 1371 | a = 3 / / 2 1372 | ]=] 1373 | e = [=[ 1374 | test.lua:1:9: syntax error, expected an expression after the multiplicative operator 1375 | ]=] 1376 | 1377 | r = parse(s) 1378 | assert(r == e) 1379 | 1380 | -- bitwise expressions 1381 | 1382 | s = [=[ 1383 | b = 1 && 1 1384 | ]=] 1385 | e = [=[ 1386 | test.lua:1:8: syntax error, expected an expression after '&' 1387 | ]=] 1388 | 1389 | r = parse(s) 1390 | assert(r == e) 1391 | 1392 | s = [=[ 1393 | b = 1 <> 0 1394 | ]=] 1395 | e = [=[ 1396 | test.lua:1:8: syntax error, expected an expression after the relational operator 1397 | ]=] 1398 | 1399 | r = parse(s) 1400 | assert(r == e) 1401 | 1402 | s = [=[ 1403 | b = 1 < < 0 1404 | ]=] 1405 | e = [=[ 1406 | test.lua:1:9: syntax error, expected an expression after the relational operator 1407 | ]=] 1408 | 1409 | r = parse(s) 1410 | assert(r == e) 1411 | 1412 | -- break 1413 | 1414 | s = [=[ 1415 | break 1416 | ]=] 1417 | e = [=[ 1418 | test.lua:1:1: syntax error, not inside a loop 1419 | ]=] 1420 | 1421 | r = parse(s) 1422 | assert(r == e) 1423 | 1424 | s = [=[ 1425 | function f (x) 1426 | if 1 then break end 1427 | end 1428 | ]=] 1429 | e = [=[ 1430 | test.lua:2:13: syntax error, not inside a loop 1431 | ]=] 1432 | 1433 | r = parse(s) 1434 | assert(r == e) 1435 | 1436 | s = [=[ 1437 | while 1 do 1438 | end 1439 | break 1440 | ]=] 1441 | e = [=[ 1442 | test.lua:3:1: syntax error, not inside a loop 1443 | ]=] 1444 | 1445 | r = parse(s) 1446 | assert(r == e) 1447 | 1448 | -- concatenation expressions 1449 | 1450 | s = [=[ 1451 | concat2 = 2^3..1 1452 | ]=] 1453 | e = [=[ 1454 | test.lua:1:15: syntax error, unexpected token, invalid start of statement 1455 | ]=] 1456 | 1457 | r = parse(s) 1458 | assert(r == e) 1459 | 1460 | s = [=[ 1461 | local s = "1 + 1 = " 1462 | print(s .. 1+1) 1463 | ]=] 1464 | e = [=[ 1465 | { `Local{ { `Id "s" }, { `String "1 + 1 = " } }, `Call{ `Id "print", `Op{ "concat", `Id "s", `Op{ "add", `Number "1", `Number "1" } } } } 1466 | ]=] 1467 | 1468 | r = parse(s) 1469 | assert(r == e) 1470 | 1471 | -- for generic 1472 | 1473 | s = [=[ 1474 | for k;v in pairs(t) do end 1475 | ]=] 1476 | e = [=[ 1477 | test.lua:1:6: syntax error, expected '=' or 'in' after the variable(s) 1478 | ]=] 1479 | 1480 | r = parse(s) 1481 | assert(r == e) 1482 | 1483 | s = [=[ 1484 | for k,v in pairs(t:any) do end 1485 | ]=] 1486 | e = [=[ 1487 | test.lua:1:23: syntax error, expected some arguments for the method call (or '()') 1488 | ]=] 1489 | 1490 | r = parse(s) 1491 | assert(r == e) 1492 | 1493 | -- for numeric 1494 | 1495 | s = [=[ 1496 | for i=1,10, do end 1497 | ]=] 1498 | e = [=[ 1499 | test.lua:1:13: syntax error, expected a step expression for the numeric range after ',' 1500 | ]=] 1501 | 1502 | r = parse(s) 1503 | assert(r == e) 1504 | 1505 | s = [=[ 1506 | for i=1,n:number do end 1507 | ]=] 1508 | e = [=[ 1509 | test.lua:1:18: syntax error, expected some arguments for the method call (or '()') 1510 | ]=] 1511 | 1512 | r = parse(s) 1513 | assert(r == e) 1514 | 1515 | -- global functions 1516 | 1517 | s = [=[ 1518 | function func(a,b,c,) end 1519 | ]=] 1520 | e = [=[ 1521 | test.lua:1:21: syntax error, expected a variable name or '...' after ',' 1522 | ]=] 1523 | 1524 | r = parse(s) 1525 | assert(r == e) 1526 | 1527 | s = [=[ 1528 | function func(...,a) end 1529 | ]=] 1530 | e = [=[ 1531 | test.lua:1:18: syntax error, expected ')' to close the parameter list 1532 | ]=] 1533 | 1534 | r = parse(s) 1535 | assert(r == e) 1536 | 1537 | s = [=[ 1538 | function a.b:c:d () end 1539 | ]=] 1540 | e = [=[ 1541 | test.lua:1:15: syntax error, expected '(' for the parameter list 1542 | ]=] 1543 | 1544 | r = parse(s) 1545 | assert(r == e) 1546 | 1547 | -- goto 1548 | 1549 | s = [=[ 1550 | :: label :: return 1551 | goto label 1552 | ]=] 1553 | e = [=[ 1554 | test.lua:2:1: syntax error, unexpected character(s), expected EOF 1555 | ]=] 1556 | 1557 | r = parse(s) 1558 | assert(r == e) 1559 | 1560 | s = [=[ 1561 | goto label 1562 | ]=] 1563 | e = [=[ 1564 | test.lua:1:1: syntax error, no visible label 'label' for 1565 | ]=] 1566 | 1567 | r = parse(s) 1568 | assert(r == e) 1569 | 1570 | s = [=[ 1571 | goto label 1572 | ::other_label:: 1573 | ]=] 1574 | e = [=[ 1575 | test.lua:1:1: syntax error, no visible label 'label' for 1576 | ]=] 1577 | 1578 | r = parse(s) 1579 | assert(r == e) 1580 | 1581 | s = [=[ 1582 | ::other_label:: 1583 | do do do goto label end end end 1584 | ]=] 1585 | e = [=[ 1586 | test.lua:2:10: syntax error, no visible label 'label' for 1587 | ]=] 1588 | 1589 | r = parse(s) 1590 | assert(r == e) 1591 | 1592 | -- if-else 1593 | 1594 | s = [=[ 1595 | if a then 1596 | ]=] 1597 | e = [=[ 1598 | test.lua:2:1: syntax error, expected 'end' to close the if statement 1599 | ]=] 1600 | 1601 | r = parse(s) 1602 | assert(r == e) 1603 | 1604 | s = [=[ 1605 | if a then else 1606 | ]=] 1607 | e = [=[ 1608 | test.lua:2:1: syntax error, expected 'end' to close the if statement 1609 | ]=] 1610 | 1611 | r = parse(s) 1612 | assert(r == e) 1613 | 1614 | s = [=[ 1615 | if a then 1616 | return a 1617 | elseif b then 1618 | return b 1619 | elseif 1620 | 1621 | end 1622 | ]=] 1623 | e = [=[ 1624 | test.lua:7:1: syntax error, expected a condition after 'elseif' 1625 | ]=] 1626 | 1627 | r = parse(s) 1628 | assert(r == e) 1629 | 1630 | s = [=[ 1631 | if a:any then else end 1632 | ]=] 1633 | e = [=[ 1634 | test.lua:1:10: syntax error, expected some arguments for the method call (or '()') 1635 | ]=] 1636 | 1637 | r = parse(s) 1638 | assert(r == e) 1639 | 1640 | -- labels 1641 | 1642 | s = [=[ 1643 | :: blah :: 1644 | :: not :: 1645 | ]=] 1646 | e = [=[ 1647 | test.lua:2:4: syntax error, expected a label name after '::' 1648 | ]=] 1649 | 1650 | r = parse(s) 1651 | assert(r == e) 1652 | 1653 | s = [=[ 1654 | ::label:: 1655 | ::other_label:: 1656 | ::label:: 1657 | ]=] 1658 | e = [=[ 1659 | test.lua:3:1: syntax error, label 'label' already defined at line 1 1660 | ]=] 1661 | 1662 | r = parse(s) 1663 | assert(r == e) 1664 | 1665 | -- locals 1666 | 1667 | s = [=[ 1668 | local a = 1669 | ]=] 1670 | e = [=[ 1671 | test.lua:2:1: syntax error, expected one or more expressions after '=' 1672 | ]=] 1673 | 1674 | r = parse(s) 1675 | assert(r == e) 1676 | 1677 | s = [=[ 1678 | local function t.a() end 1679 | ]=] 1680 | e = [=[ 1681 | test.lua:1:17: syntax error, expected '(' for the parameter list 1682 | ]=] 1683 | 1684 | r = parse(s) 1685 | assert(r == e) 1686 | 1687 | s = [=[ 1688 | local function test (a,) end 1689 | ]=] 1690 | e = [=[ 1691 | test.lua:1:24: syntax error, expected a variable name or '...' after ',' 1692 | ]=] 1693 | 1694 | r = parse(s) 1695 | assert(r == e) 1696 | 1697 | s = [=[ 1698 | local function test(...,a) end 1699 | ]=] 1700 | e = [=[ 1701 | test.lua:1:24: syntax error, expected ')' to close the parameter list 1702 | ]=] 1703 | 1704 | r = parse(s) 1705 | assert(r == e) 1706 | 1707 | s = [=[ 1708 | local function (a, b, c, ...) end 1709 | ]=] 1710 | e = [=[ 1711 | test.lua:1:16: syntax error, expected a function name after 'function' 1712 | ]=] 1713 | 1714 | r = parse(s) 1715 | assert(r == e) 1716 | 1717 | -- repeat 1718 | 1719 | s = [=[ 1720 | repeat 1721 | a,b,c = 1+1,2+2,3+3 1722 | break 1723 | ]=] 1724 | e = [=[ 1725 | test.lua:4:1: syntax error, expected 'until' at the end of the repeat loop 1726 | ]=] 1727 | 1728 | r = parse(s) 1729 | assert(r == e) 1730 | 1731 | -- return 1732 | 1733 | s = [=[ 1734 | return 1735 | return 1 1736 | return 1,1-2*3+4,"alo" 1737 | return; 1738 | return 1; 1739 | return 1,1-2*3+4,"alo"; 1740 | ]=] 1741 | e = [=[ 1742 | test.lua:2:1: syntax error, unexpected character(s), expected EOF 1743 | ]=] 1744 | 1745 | r = parse(s) 1746 | assert(r == e) 1747 | 1748 | -- tables 1749 | 1750 | s = [=[ 1751 | t = { , } 1752 | ]=] 1753 | e = [=[ 1754 | test.lua:1:7: syntax error, expected '}' to close the table constructor 1755 | ]=] 1756 | 1757 | r = parse(s) 1758 | assert(r == e) 1759 | 1760 | -- vararg 1761 | 1762 | s = [=[ 1763 | function f () 1764 | return ... 1765 | end 1766 | ]=] 1767 | e = [=[ 1768 | test.lua:2:10: syntax error, cannot use '...' outside a vararg function 1769 | ]=] 1770 | 1771 | r = parse(s) 1772 | assert(r == e) 1773 | 1774 | s = [=[ 1775 | function f () 1776 | function g (x, y) 1777 | return ...,...,... 1778 | end 1779 | end 1780 | ]=] 1781 | e = [=[ 1782 | test.lua:3:12: syntax error, cannot use '...' outside a vararg function 1783 | ]=] 1784 | 1785 | r = parse(s) 1786 | assert(r == e) 1787 | 1788 | s = [=[ 1789 | local function f (x) 1790 | return ... 1791 | end 1792 | ]=] 1793 | e = [=[ 1794 | test.lua:2:10: syntax error, cannot use '...' outside a vararg function 1795 | ]=] 1796 | 1797 | r = parse(s) 1798 | assert(r == e) 1799 | 1800 | s = [=[ 1801 | local f = function (x) 1802 | return ... 1803 | end 1804 | ]=] 1805 | e = [=[ 1806 | test.lua:2:10: syntax error, cannot use '...' outside a vararg function 1807 | ]=] 1808 | 1809 | r = parse(s) 1810 | assert(r == e) 1811 | 1812 | -- while 1813 | 1814 | s = [=[ 1815 | i = 0 1816 | while (i < 10) 1817 | i = i + 1 1818 | end 1819 | ]=] 1820 | e = [=[ 1821 | test.lua:3:3: syntax error, expected 'do' after the condition 1822 | ]=] 1823 | 1824 | r = parse(s) 1825 | assert(r == e) 1826 | 1827 | print("> testing more syntax errors...") 1828 | 1829 | -- ErrExtra 1830 | s = [=[ 1831 | return; print("hello") 1832 | ]=] 1833 | e = [=[ 1834 | test.lua:1:9: syntax error, unexpected character(s), expected EOF 1835 | ]=] 1836 | 1837 | r = parse(s) 1838 | assert(r == e) 1839 | 1840 | s = [=[ 1841 | while foo do if bar then baz() end end end 1842 | ]=] 1843 | e = [=[ 1844 | test.lua:1:40: syntax error, unexpected character(s), expected EOF 1845 | ]=] 1846 | 1847 | r = parse(s) 1848 | assert(r == e) 1849 | 1850 | s = [=[ 1851 | local func f() 1852 | g() 1853 | end 1854 | ]=] 1855 | e = [=[ 1856 | test.lua:3:1: syntax error, unexpected character(s), expected EOF 1857 | ]=] 1858 | 1859 | r = parse(s) 1860 | assert(r == e) 1861 | 1862 | s = [=[ 1863 | function qux() 1864 | if false then 1865 | -- do 1866 | return 0 1867 | end 1868 | end 1869 | return 1 1870 | end 1871 | print(qux()) 1872 | ]=] 1873 | e = [=[ 1874 | test.lua:8:1: syntax error, unexpected character(s), expected EOF 1875 | ]=] 1876 | 1877 | r = parse(s) 1878 | assert(r == e) 1879 | 1880 | -- ErrInvalidStat 1881 | s = [=[ 1882 | find_solution() ? print("yes") : print("no") 1883 | ]=] 1884 | e = [=[ 1885 | test.lua:1:17: syntax error, unexpected token, invalid start of statement 1886 | ]=] 1887 | 1888 | r = parse(s) 1889 | assert(r == e) 1890 | 1891 | s = [=[ 1892 | local i : int = 0 1893 | ]=] 1894 | e = [=[ 1895 | test.lua:1:9: syntax error, unexpected token, invalid start of statement 1896 | ]=] 1897 | 1898 | r = parse(s) 1899 | assert(r == e) 1900 | 1901 | s = [=[ 1902 | local a = 1, b = 2 1903 | ]=] 1904 | e = [=[ 1905 | test.lua:1:16: syntax error, unexpected token, invalid start of statement 1906 | ]=] 1907 | 1908 | s = [=[ 1909 | x = - 1910 | y = 2 1911 | ]=] 1912 | e = [=[ 1913 | test.lua:2:3: syntax error, unexpected token, invalid start of statement 1914 | ]=] 1915 | 1916 | r = parse(s) 1917 | assert(r == e) 1918 | 1919 | s = [=[ 1920 | obj::hello() 1921 | ]=] 1922 | e = [=[ 1923 | test.lua:1:1: syntax error, unexpected token, invalid start of statement 1924 | ]=] 1925 | 1926 | r = parse(s) 1927 | assert(r == e) 1928 | 1929 | s = [=[ 1930 | while foo() do 1931 | // not a lua comment 1932 | bar() 1933 | end 1934 | ]=] 1935 | e = [=[ 1936 | test.lua:2:3: syntax error, unexpected token, invalid start of statement 1937 | ]=] 1938 | 1939 | r = parse(s) 1940 | assert(r == e) 1941 | 1942 | s = [=[ 1943 | repeat: 1944 | action() 1945 | until condition 1946 | end 1947 | ]=] 1948 | e = [=[ 1949 | test.lua:1:7: syntax error, unexpected token, invalid start of statement 1950 | ]=] 1951 | 1952 | r = parse(s) 1953 | assert(r == e) 1954 | 1955 | s = [=[ 1956 | function f(x) 1957 | local result 1958 | ... -- TODO: compute for the next result 1959 | return result 1960 | end 1961 | ]=] 1962 | e = [=[ 1963 | test.lua:3:3: syntax error, unexpected token, invalid start of statement 1964 | ]=] 1965 | 1966 | r = parse(s) 1967 | assert(r == e) 1968 | 1969 | s = [=[ 1970 | x; 1971 | ]=] 1972 | e = [=[ 1973 | test.lua:1:1: syntax error, unexpected token, invalid start of statement 1974 | ]=] 1975 | 1976 | r = parse(s) 1977 | assert(r == e) 1978 | 1979 | s = [=[ 1980 | a, b, c 1981 | ]=] 1982 | e = [=[ 1983 | test.lua:1:1: syntax error, unexpected token, invalid start of statement 1984 | ]=] 1985 | 1986 | r = parse(s) 1987 | assert(r == e) 1988 | 1989 | s = [=[ 1990 | local x = 42 // the meaning of life 1991 | ]=] 1992 | e = [=[ 1993 | test.lua:1:21: syntax error, unexpected token, invalid start of statement 1994 | ]=] 1995 | 1996 | r = parse(s) 1997 | assert(r == e) 1998 | 1999 | s = [=[ 2000 | let x = 2 2001 | ]=] 2002 | e = [=[ 2003 | test.lua:1:1: syntax error, unexpected token, invalid start of statement 2004 | ]=] 2005 | 2006 | r = parse(s) 2007 | assert(r == e) 2008 | 2009 | s = [=[ 2010 | if p then 2011 | f() 2012 | elif q then 2013 | g() 2014 | end 2015 | ]=] 2016 | e = [=[ 2017 | test.lua:3:1: syntax error, unexpected token, invalid start of statement 2018 | ]=] 2019 | 2020 | r = parse(s) 2021 | assert(r == e) 2022 | 2023 | s = [=[ 2024 | function foo() 2025 | bar() 2026 | emd 2027 | ]=] 2028 | e = [=[ 2029 | test.lua:3:1: syntax error, unexpected token, invalid start of statement 2030 | ]=] 2031 | 2032 | r = parse(s) 2033 | assert(r == e) 2034 | 2035 | -- ErrEndIf 2036 | s = [=[ 2037 | if 1 > 2 then print("impossible") 2038 | ]=] 2039 | e = [=[ 2040 | test.lua:2:1: syntax error, expected 'end' to close the if statement 2041 | ]=] 2042 | 2043 | r = parse(s) 2044 | assert(r == e) 2045 | 2046 | s = [=[ 2047 | if 1 > 2 then return; print("impossible") end 2048 | ]=] 2049 | e = [=[ 2050 | test.lua:1:23: syntax error, expected 'end' to close the if statement 2051 | ]=] 2052 | 2053 | r = parse(s) 2054 | assert(r == e) 2055 | 2056 | s = [=[ 2057 | if condA then doThis() 2058 | else if condB then doThat() end 2059 | ]=] 2060 | e = [=[ 2061 | test.lua:3:1: syntax error, expected 'end' to close the if statement 2062 | ]=] 2063 | 2064 | r = parse(s) 2065 | assert(r == e) 2066 | 2067 | s = [=[ 2068 | if a then 2069 | b() 2070 | else 2071 | c() 2072 | else 2073 | d() 2074 | end 2075 | ]=] 2076 | e = [=[ 2077 | test.lua:5:1: syntax error, expected 'end' to close the if statement 2078 | ]=] 2079 | 2080 | r = parse(s) 2081 | assert(r == e) 2082 | 2083 | -- ErrExprIf 2084 | s = [=[ 2085 | if then print("that") end 2086 | ]=] 2087 | e = [=[ 2088 | test.lua:1:4: syntax error, expected a condition after 'if' 2089 | ]=] 2090 | 2091 | r = parse(s) 2092 | assert(r == e) 2093 | 2094 | s = [=[ 2095 | if !ok then error("fail") end 2096 | ]=] 2097 | e = [=[ 2098 | test.lua:1:4: syntax error, expected a condition after 'if' 2099 | ]=] 2100 | 2101 | r = parse(s) 2102 | assert(r == e) 2103 | 2104 | -- ErrThenIf 2105 | s = [=[ 2106 | if age < 18 2107 | print("too young!") 2108 | end 2109 | ]=] 2110 | e = [=[ 2111 | test.lua:2:3: syntax error, expected 'then' after the condition 2112 | ]=] 2113 | 2114 | r = parse(s) 2115 | assert(r == e) 2116 | 2117 | -- ErrExprEIf 2118 | s = [=[ 2119 | if age < 18 then print("too young!") 2120 | elseif then print("too old") end 2121 | ]=] 2122 | e = [=[ 2123 | test.lua:2:8: syntax error, expected a condition after 'elseif' 2124 | ]=] 2125 | 2126 | r = parse(s) 2127 | assert(r == e) 2128 | 2129 | -- ErrThenEIf 2130 | s = [=[ 2131 | if not result then error("fail") 2132 | elseif result > 0: 2133 | process(result) 2134 | end 2135 | ]=] 2136 | e = [=[ 2137 | test.lua:2:18: syntax error, expected 'then' after the condition 2138 | ]=] 2139 | 2140 | r = parse(s) 2141 | assert(r == e) 2142 | 2143 | -- ErrEndDo 2144 | s = [=[ 2145 | do something() 2146 | ]=] 2147 | e = [=[ 2148 | test.lua:2:1: syntax error, expected 'end' to close the do block 2149 | ]=] 2150 | 2151 | r = parse(s) 2152 | assert(r == e) 2153 | 2154 | s = [=[ 2155 | do 2156 | return arr[i] 2157 | i = i + 1 2158 | end 2159 | ]=] 2160 | e = [=[ 2161 | test.lua:3:3: syntax error, expected 'end' to close the do block 2162 | ]=] 2163 | 2164 | r = parse(s) 2165 | assert(r == e) 2166 | 2167 | -- ErrExprWhile 2168 | s = [=[ 2169 | while !done do done = work() end 2170 | ]=] 2171 | e = [=[ 2172 | test.lua:1:7: syntax error, expected a condition after 'while' 2173 | ]=] 2174 | 2175 | r = parse(s) 2176 | assert(r == e) 2177 | 2178 | s = [=[ 2179 | while do print("hello again!") end 2180 | ]=] 2181 | e = [=[ 2182 | test.lua:1:7: syntax error, expected a condition after 'while' 2183 | ]=] 2184 | 2185 | r = parse(s) 2186 | assert(r == e) 2187 | 2188 | -- ErrDoWhile 2189 | s = [=[ 2190 | while not done then work() end 2191 | ]=] 2192 | e = [=[ 2193 | test.lua:1:16: syntax error, expected 'do' after the condition 2194 | ]=] 2195 | 2196 | r = parse(s) 2197 | assert(r == e) 2198 | 2199 | s = [=[ 2200 | while not done 2201 | work() 2202 | end 2203 | ]=] 2204 | e = [=[ 2205 | test.lua:2:3: syntax error, expected 'do' after the condition 2206 | ]=] 2207 | 2208 | r = parse(s) 2209 | assert(r == e) 2210 | 2211 | -- ErrEndWhile 2212 | s = [=[ 2213 | while not found do i = i + 1 2214 | ]=] 2215 | e = [=[ 2216 | test.lua:2:1: syntax error, expected 'end' to close the while loop 2217 | ]=] 2218 | 2219 | r = parse(s) 2220 | assert(r == e) 2221 | 2222 | s = [=[ 2223 | while i < #arr do 2224 | if arr[i] == target then break 2225 | i = i +1 2226 | end 2227 | ]=] 2228 | e = [=[ 2229 | test.lua:5:1: syntax error, expected 'end' to close the while loop 2230 | ]=] 2231 | 2232 | r = parse(s) 2233 | assert(r == e) 2234 | 2235 | -- ErrUntilRep 2236 | s = [=[ 2237 | repeat play_song() 2238 | ]=] 2239 | e = [=[ 2240 | test.lua:2:1: syntax error, expected 'until' at the end of the repeat loop 2241 | ]=] 2242 | 2243 | r = parse(s) 2244 | assert(r == e) 2245 | 2246 | -- ErrExprRep 2247 | s = [=[ 2248 | repeat film() until end 2249 | ]=] 2250 | e = [=[ 2251 | test.lua:1:21: syntax error, expected a conditions after 'until' 2252 | ]=] 2253 | 2254 | r = parse(s) 2255 | assert(r == e) 2256 | 2257 | -- ErrForRange 2258 | s = [=[ 2259 | for (key, val) in obj do 2260 | print(key .. " -> " .. val) 2261 | end 2262 | ]=] 2263 | e = [=[ 2264 | test.lua:1:5: syntax error, expected a numeric or generic range after 'for' 2265 | ]=] 2266 | 2267 | r = parse(s) 2268 | assert(r == e) 2269 | 2270 | -- ErrEndFor 2271 | s = [=[ 2272 | for i = 1,10 do print(i) 2273 | ]=] 2274 | e = [=[ 2275 | test.lua:2:1: syntax error, expected 'end' to close the for loop 2276 | ]=] 2277 | 2278 | r = parse(s) 2279 | assert(r == e) 2280 | 2281 | -- ErrExprFor1 2282 | s = [=[ 2283 | for i = ,10 do print(i) end 2284 | ]=] 2285 | e = [=[ 2286 | test.lua:1:9: syntax error, expected a starting expression for the numeric range 2287 | ]=] 2288 | 2289 | r = parse(s) 2290 | assert(r == e) 2291 | 2292 | -- ErrCommaFor 2293 | s = [=[ 2294 | for i = 1 to 10 do print(i) end 2295 | ]=] 2296 | e = [=[ 2297 | test.lua:1:11: syntax error, expected ',' to split the start and end of the range 2298 | ]=] 2299 | 2300 | r = parse(s) 2301 | assert(r == e) 2302 | 2303 | -- ErrExprFor2 2304 | s = [=[ 2305 | for i = 1, do print(i) end 2306 | ]=] 2307 | e = [=[ 2308 | test.lua:1:12: syntax error, expected an ending expression for the numeric range 2309 | ]=] 2310 | 2311 | r = parse(s) 2312 | assert(r == e) 2313 | 2314 | -- ErrExprFor3 2315 | s = [=[ 2316 | for i = 1,10, do print(i) end 2317 | ]=] 2318 | e = [=[ 2319 | test.lua:1:15: syntax error, expected a step expression for the numeric range after ',' 2320 | ]=] 2321 | 2322 | r = parse(s) 2323 | assert(r == e) 2324 | 2325 | -- ErrInFor 2326 | s = [=[ 2327 | for arr do print(arr[i]) end 2328 | ]=] 2329 | e = [=[ 2330 | test.lua:1:9: syntax error, expected '=' or 'in' after the variable(s) 2331 | ]=] 2332 | 2333 | r = parse(s) 2334 | assert(r == e) 2335 | 2336 | s = [=[ 2337 | for nums := 1,10 do print(i) end 2338 | ]=] 2339 | e = [=[ 2340 | test.lua:1:10: syntax error, expected '=' or 'in' after the variable(s) 2341 | ]=] 2342 | 2343 | r = parse(s) 2344 | assert(r == e) 2345 | 2346 | -- ErrEListFor 2347 | s = [=[ 2348 | for i in ? do print(i) end 2349 | ]=] 2350 | e = [=[ 2351 | test.lua:1:10: syntax error, expected one or more expressions after 'in' 2352 | ]=] 2353 | 2354 | r = parse(s) 2355 | assert(r == e) 2356 | 2357 | -- ErrDoFor 2358 | s = [=[ 2359 | for i = 1,10 doo print(i) end 2360 | ]=] 2361 | e = [=[ 2362 | test.lua:1:14: syntax error, expected 'do' after the range of the for loop 2363 | ]=] 2364 | 2365 | r = parse(s) 2366 | assert(r == e) 2367 | 2368 | s = [=[ 2369 | for _, elem in ipairs(list) 2370 | print(elem) 2371 | end 2372 | ]=] 2373 | e = [=[ 2374 | test.lua:2:3: syntax error, expected 'do' after the range of the for loop 2375 | ]=] 2376 | 2377 | r = parse(s) 2378 | assert(r == e) 2379 | 2380 | -- ErrDefLocal 2381 | s = [=[ 2382 | local 2383 | ]=] 2384 | e = [=[ 2385 | test.lua:2:1: syntax error, expected a function definition or assignment after local 2386 | ]=] 2387 | 2388 | r = parse(s) 2389 | assert(r == e) 2390 | 2391 | s = [=[ 2392 | local; x = 2 2393 | ]=] 2394 | e = [=[ 2395 | test.lua:1:6: syntax error, expected a function definition or assignment after local 2396 | ]=] 2397 | 2398 | r = parse(s) 2399 | assert(r == e) 2400 | 2401 | s = [=[ 2402 | local *p = nil 2403 | ]=] 2404 | e = [=[ 2405 | test.lua:1:7: syntax error, expected a function definition or assignment after local 2406 | ]=] 2407 | 2408 | r = parse(s) 2409 | assert(r == e) 2410 | 2411 | -- ErrNameLFunc 2412 | s = [=[ 2413 | local function() return 0 end 2414 | ]=] 2415 | e = [=[ 2416 | test.lua:1:15: syntax error, expected a function name after 'function' 2417 | ]=] 2418 | 2419 | r = parse(s) 2420 | assert(r == e) 2421 | 2422 | s = [=[ 2423 | local function 3dprint(x, y, z) end 2424 | ]=] 2425 | e = [=[ 2426 | test.lua:1:16: syntax error, expected a function name after 'function' 2427 | ]=] 2428 | 2429 | r = parse(s) 2430 | assert(r == e) 2431 | 2432 | s = [=[ 2433 | local function repeat(f, ntimes) for i = 1,ntimes do f() end end 2434 | ]=] 2435 | e = [=[ 2436 | test.lua:1:16: syntax error, expected a function name after 'function' 2437 | ]=] 2438 | 2439 | r = parse(s) 2440 | assert(r == e) 2441 | 2442 | -- ErrEListLAssign 2443 | s = [=[ 2444 | local x = ? 2445 | ]=] 2446 | e = [=[ 2447 | test.lua:1:11: syntax error, expected one or more expressions after '=' 2448 | ]=] 2449 | 2450 | r = parse(s) 2451 | assert(r == e) 2452 | 2453 | -- ErrEListAssign 2454 | s = [=[ 2455 | x = ? 2456 | ]=] 2457 | e = [=[ 2458 | test.lua:1:5: syntax error, expected one or more expressions after '=' 2459 | ]=] 2460 | 2461 | r = parse(s) 2462 | assert(r == e) 2463 | 2464 | -- ErrFuncName 2465 | s = [=[ 2466 | function() return 0 end 2467 | ]=] 2468 | e = [=[ 2469 | test.lua:1:9: syntax error, expected a function name after 'function' 2470 | ]=] 2471 | 2472 | r = parse(s) 2473 | assert(r == e) 2474 | 2475 | s = [=[ 2476 | function 3dprint(x, y, z) end 2477 | ]=] 2478 | e = [=[ 2479 | test.lua:1:10: syntax error, expected a function name after 'function' 2480 | ]=] 2481 | 2482 | r = parse(s) 2483 | assert(r == e) 2484 | 2485 | s = [=[ 2486 | function repeat(f, ntimes) for i = 1,ntimes do f() end end 2487 | ]=] 2488 | e = [=[ 2489 | test.lua:1:10: syntax error, expected a function name after 'function' 2490 | ]=] 2491 | 2492 | r = parse(s) 2493 | assert(r == e) 2494 | 2495 | -- ErrNameFunc1 2496 | s = [=[ 2497 | function foo.() end 2498 | ]=] 2499 | e = [=[ 2500 | test.lua:1:14: syntax error, expected a function name after '.' 2501 | ]=] 2502 | 2503 | r = parse(s) 2504 | assert(r == e) 2505 | 2506 | s = [=[ 2507 | function foo.1() end 2508 | ]=] 2509 | e = [=[ 2510 | test.lua:1:14: syntax error, expected a function name after '.' 2511 | ]=] 2512 | 2513 | r = parse(s) 2514 | assert(r == e) 2515 | 2516 | -- ErrNameFunc2 2517 | s = [=[ 2518 | function foo:() end 2519 | ]=] 2520 | e = [=[ 2521 | test.lua:1:14: syntax error, expected a method name after ':' 2522 | ]=] 2523 | 2524 | r = parse(s) 2525 | assert(r == e) 2526 | 2527 | s = [=[ 2528 | function foo:1() end 2529 | ]=] 2530 | e = [=[ 2531 | test.lua:1:14: syntax error, expected a method name after ':' 2532 | ]=] 2533 | 2534 | r = parse(s) 2535 | assert(r == e) 2536 | 2537 | -- ErrOParenPList 2538 | s = [=[ 2539 | function foo 2540 | return bar 2541 | end 2542 | ]=] 2543 | e = [=[ 2544 | test.lua:2:3: syntax error, expected '(' for the parameter list 2545 | ]=] 2546 | 2547 | r = parse(s) 2548 | assert(r == e) 2549 | 2550 | s = [=[ 2551 | function foo?(bar) 2552 | return bar 2553 | end 2554 | ]=] 2555 | e = [=[ 2556 | test.lua:1:13: syntax error, expected '(' for the parameter list 2557 | ]=] 2558 | 2559 | r = parse(s) 2560 | assert(r == e) 2561 | 2562 | -- ErrCParenPList 2563 | s = [=[ 2564 | function foo(bar 2565 | return bar 2566 | end 2567 | ]=] 2568 | e = [=[ 2569 | test.lua:2:3: syntax error, expected ')' to close the parameter list 2570 | ]=] 2571 | 2572 | r = parse(s) 2573 | assert(r == e) 2574 | 2575 | s = [=[ 2576 | function foo(bar; baz) 2577 | return bar 2578 | end 2579 | ]=] 2580 | e = [=[ 2581 | test.lua:1:17: syntax error, expected ')' to close the parameter list 2582 | ]=] 2583 | 2584 | r = parse(s) 2585 | assert(r == e) 2586 | 2587 | s = [=[ 2588 | function foo(a, b, ...rest) end 2589 | ]=] 2590 | e = [=[ 2591 | test.lua:1:23: syntax error, expected ')' to close the parameter list 2592 | ]=] 2593 | 2594 | r = parse(s) 2595 | assert(r == e) 2596 | 2597 | -- ErrEndFunc 2598 | s = [=[ 2599 | function foo(bar) 2600 | return bar 2601 | ]=] 2602 | e = [=[ 2603 | test.lua:3:1: syntax error, expected 'end' to close the function body 2604 | ]=] 2605 | 2606 | r = parse(s) 2607 | assert(r == e) 2608 | 2609 | s = [=[ 2610 | function foo() do 2611 | bar() 2612 | end 2613 | ]=] 2614 | e = [=[ 2615 | test.lua:4:1: syntax error, expected 'end' to close the function body 2616 | ]=] 2617 | 2618 | r = parse(s) 2619 | assert(r == e) 2620 | 2621 | -- ErrParList 2622 | s = [=[ 2623 | function foo(bar, baz,) 2624 | return bar 2625 | end 2626 | ]=] 2627 | e = [=[ 2628 | test.lua:1:23: syntax error, expected a variable name or '...' after ',' 2629 | ]=] 2630 | 2631 | r = parse(s) 2632 | assert(r == e) 2633 | 2634 | -- ErrLabel 2635 | s = [=[ 2636 | ::1:: 2637 | ]=] 2638 | e = [=[ 2639 | test.lua:1:3: syntax error, expected a label name after '::' 2640 | ]=] 2641 | 2642 | r = parse(s) 2643 | assert(r == e) 2644 | 2645 | -- ErrCloseLabel 2646 | s = [=[ 2647 | ::loop 2648 | ]=] 2649 | e = [=[ 2650 | test.lua:2:1: syntax error, expected '::' after the label 2651 | ]=] 2652 | 2653 | r = parse(s) 2654 | assert(r == e) 2655 | 2656 | -- ErrGoto 2657 | s = [=[ 2658 | goto; 2659 | ]=] 2660 | e = [=[ 2661 | test.lua:1:5: syntax error, expected a label after 'goto' 2662 | ]=] 2663 | 2664 | r = parse(s) 2665 | assert(r == e) 2666 | 2667 | s = [=[ 2668 | goto 1 2669 | ]=] 2670 | e = [=[ 2671 | test.lua:1:6: syntax error, expected a label after 'goto' 2672 | ]=] 2673 | 2674 | r = parse(s) 2675 | assert(r == e) 2676 | 2677 | -- ErrRetList 2678 | s = [=[ 2679 | return a, b, 2680 | ]=] 2681 | e = [=[ 2682 | test.lua:2:1: syntax error, expected an expression after ',' in the return statement 2683 | ]=] 2684 | 2685 | r = parse(s) 2686 | assert(r == e) 2687 | 2688 | -- ErrVarList 2689 | s = [=[ 2690 | x, y, = 0, 0 2691 | ]=] 2692 | e = [=[ 2693 | test.lua:1:7: syntax error, expected a variable name after ',' 2694 | ]=] 2695 | 2696 | r = parse(s) 2697 | assert(r == e) 2698 | 2699 | -- ErrExprList 2700 | s = [=[ 2701 | x, y = 0, 0, 2702 | ]=] 2703 | e = [=[ 2704 | test.lua:2:1: syntax error, expected an expression after ',' 2705 | ]=] 2706 | 2707 | r = parse(s) 2708 | assert(r == e) 2709 | 2710 | -- ErrOrExpr 2711 | s = [=[ 2712 | foo(a or) 2713 | ]=] 2714 | e = [=[ 2715 | test.lua:1:9: syntax error, expected an expression after 'or' 2716 | ]=] 2717 | 2718 | r = parse(s) 2719 | assert(r == e) 2720 | 2721 | s = [=[ 2722 | x = a or $b 2723 | ]=] 2724 | e = [=[ 2725 | test.lua:1:10: syntax error, expected an expression after 'or' 2726 | ]=] 2727 | 2728 | r = parse(s) 2729 | assert(r == e) 2730 | 2731 | -- ErrAndExpr 2732 | s = [=[ 2733 | foo(a and) 2734 | ]=] 2735 | e = [=[ 2736 | test.lua:1:10: syntax error, expected an expression after 'and' 2737 | ]=] 2738 | 2739 | r = parse(s) 2740 | assert(r == e) 2741 | 2742 | s = [=[ 2743 | x = a and $b 2744 | ]=] 2745 | e = [=[ 2746 | test.lua:1:11: syntax error, expected an expression after 'and' 2747 | ]=] 2748 | 2749 | r = parse(s) 2750 | assert(r == e) 2751 | 2752 | -- ErrRelExpr 2753 | s = [=[ 2754 | foo(a <) 2755 | ]=] 2756 | e = [=[ 2757 | test.lua:1:8: syntax error, expected an expression after the relational operator 2758 | ]=] 2759 | 2760 | r = parse(s) 2761 | assert(r == e) 2762 | 2763 | s = [=[ 2764 | x = a < $b 2765 | ]=] 2766 | e = [=[ 2767 | test.lua:1:9: syntax error, expected an expression after the relational operator 2768 | ]=] 2769 | 2770 | r = parse(s) 2771 | assert(r == e) 2772 | 2773 | s = [=[ 2774 | foo(a <=) 2775 | ]=] 2776 | e = [=[ 2777 | test.lua:1:9: syntax error, expected an expression after the relational operator 2778 | ]=] 2779 | 2780 | r = parse(s) 2781 | assert(r == e) 2782 | 2783 | s = [=[ 2784 | x = a <= $b 2785 | ]=] 2786 | e = [=[ 2787 | test.lua:1:10: syntax error, expected an expression after the relational operator 2788 | ]=] 2789 | 2790 | r = parse(s) 2791 | assert(r == e) 2792 | 2793 | s = [=[ 2794 | foo(a >) 2795 | ]=] 2796 | e = [=[ 2797 | test.lua:1:8: syntax error, expected an expression after the relational operator 2798 | ]=] 2799 | 2800 | r = parse(s) 2801 | assert(r == e) 2802 | 2803 | s = [=[ 2804 | x = a > $b 2805 | ]=] 2806 | e = [=[ 2807 | test.lua:1:9: syntax error, expected an expression after the relational operator 2808 | ]=] 2809 | 2810 | r = parse(s) 2811 | assert(r == e) 2812 | 2813 | s = [=[ 2814 | foo(a >=) 2815 | ]=] 2816 | e = [=[ 2817 | test.lua:1:9: syntax error, expected an expression after the relational operator 2818 | ]=] 2819 | 2820 | r = parse(s) 2821 | assert(r == e) 2822 | 2823 | s = [=[ 2824 | x = a >= $b 2825 | ]=] 2826 | e = [=[ 2827 | test.lua:1:10: syntax error, expected an expression after the relational operator 2828 | ]=] 2829 | 2830 | r = parse(s) 2831 | assert(r == e) 2832 | 2833 | s = [=[ 2834 | foo(a ==) 2835 | ]=] 2836 | e = [=[ 2837 | test.lua:1:9: syntax error, expected an expression after the relational operator 2838 | ]=] 2839 | 2840 | r = parse(s) 2841 | assert(r == e) 2842 | 2843 | s = [=[ 2844 | x = a == $b 2845 | ]=] 2846 | e = [=[ 2847 | test.lua:1:10: syntax error, expected an expression after the relational operator 2848 | ]=] 2849 | 2850 | r = parse(s) 2851 | assert(r == e) 2852 | 2853 | s = [=[ 2854 | foo(a ~=) 2855 | ]=] 2856 | e = [=[ 2857 | test.lua:1:9: syntax error, expected an expression after the relational operator 2858 | ]=] 2859 | 2860 | r = parse(s) 2861 | assert(r == e) 2862 | 2863 | s = [=[ 2864 | x = a ~= $b 2865 | ]=] 2866 | e = [=[ 2867 | test.lua:1:10: syntax error, expected an expression after the relational operator 2868 | ]=] 2869 | 2870 | r = parse(s) 2871 | assert(r == e) 2872 | 2873 | -- ErrBOrExpr 2874 | s = [=[ 2875 | foo(a |) 2876 | ]=] 2877 | e = [=[ 2878 | test.lua:1:8: syntax error, expected an expression after '|' 2879 | ]=] 2880 | 2881 | r = parse(s) 2882 | assert(r == e) 2883 | 2884 | s = [=[ 2885 | x = a | $b 2886 | ]=] 2887 | e = [=[ 2888 | test.lua:1:9: syntax error, expected an expression after '|' 2889 | ]=] 2890 | 2891 | r = parse(s) 2892 | assert(r == e) 2893 | 2894 | -- ErrBXorExpr 2895 | s = [=[ 2896 | foo(a ~) 2897 | ]=] 2898 | e = [=[ 2899 | test.lua:1:8: syntax error, expected an expression after '~' 2900 | ]=] 2901 | 2902 | r = parse(s) 2903 | assert(r == e) 2904 | 2905 | s = [=[ 2906 | x = a ~ $b 2907 | ]=] 2908 | e = [=[ 2909 | test.lua:1:9: syntax error, expected an expression after '~' 2910 | ]=] 2911 | 2912 | r = parse(s) 2913 | assert(r == e) 2914 | 2915 | -- ErrBAndExpr 2916 | s = [=[ 2917 | foo(a &) 2918 | ]=] 2919 | e = [=[ 2920 | test.lua:1:8: syntax error, expected an expression after '&' 2921 | ]=] 2922 | 2923 | r = parse(s) 2924 | assert(r == e) 2925 | 2926 | s = [=[ 2927 | x = a & $b 2928 | ]=] 2929 | e = [=[ 2930 | test.lua:1:9: syntax error, expected an expression after '&' 2931 | ]=] 2932 | 2933 | r = parse(s) 2934 | assert(r == e) 2935 | 2936 | -- ErrShiftExpr 2937 | s = [=[ 2938 | foo(a >>) 2939 | ]=] 2940 | e = [=[ 2941 | test.lua:1:9: syntax error, expected an expression after the bit shift 2942 | ]=] 2943 | 2944 | r = parse(s) 2945 | assert(r == e) 2946 | 2947 | s = [=[ 2948 | x = a >> $b 2949 | ]=] 2950 | e = [=[ 2951 | test.lua:1:10: syntax error, expected an expression after the bit shift 2952 | ]=] 2953 | 2954 | r = parse(s) 2955 | assert(r == e) 2956 | 2957 | s = [=[ 2958 | foo(a <<) 2959 | ]=] 2960 | e = [=[ 2961 | test.lua:1:9: syntax error, expected an expression after the bit shift 2962 | ]=] 2963 | 2964 | r = parse(s) 2965 | assert(r == e) 2966 | 2967 | s = [=[ 2968 | x = a >> $b 2969 | ]=] 2970 | e = [=[ 2971 | test.lua:1:10: syntax error, expected an expression after the bit shift 2972 | ]=] 2973 | 2974 | r = parse(s) 2975 | assert(r == e) 2976 | 2977 | s = [=[ 2978 | x = a >>> b 2979 | ]=] 2980 | e = [=[ 2981 | test.lua:1:9: syntax error, expected an expression after the bit shift 2982 | ]=] 2983 | 2984 | r = parse(s) 2985 | assert(r == e) 2986 | 2987 | -- ErrConcatExpr 2988 | s = [=[ 2989 | foo(a ..) 2990 | ]=] 2991 | e = [=[ 2992 | test.lua:1:9: syntax error, expected an expression after '..' 2993 | ]=] 2994 | 2995 | r = parse(s) 2996 | assert(r == e) 2997 | 2998 | s = [=[ 2999 | x = a .. $b 3000 | ]=] 3001 | e = [=[ 3002 | test.lua:1:10: syntax error, expected an expression after '..' 3003 | ]=] 3004 | 3005 | r = parse(s) 3006 | assert(r == e) 3007 | 3008 | -- ErrAddExpr 3009 | s = [=[ 3010 | foo(a +, b) 3011 | ]=] 3012 | e = [=[ 3013 | test.lua:1:8: syntax error, expected an expression after the additive operator 3014 | ]=] 3015 | 3016 | r = parse(s) 3017 | assert(r == e) 3018 | 3019 | s = [=[ 3020 | x = a + $b 3021 | ]=] 3022 | e = [=[ 3023 | test.lua:1:9: syntax error, expected an expression after the additive operator 3024 | ]=] 3025 | 3026 | r = parse(s) 3027 | assert(r == e) 3028 | 3029 | s = [=[ 3030 | foo(a -, b) 3031 | ]=] 3032 | e = [=[ 3033 | test.lua:1:8: syntax error, expected an expression after the additive operator 3034 | ]=] 3035 | 3036 | r = parse(s) 3037 | assert(r == e) 3038 | 3039 | s = [=[ 3040 | x = a - $b 3041 | ]=] 3042 | e = [=[ 3043 | test.lua:1:9: syntax error, expected an expression after the additive operator 3044 | ]=] 3045 | 3046 | r = parse(s) 3047 | assert(r == e) 3048 | 3049 | s = [=[ 3050 | arr[i++] 3051 | ]=] 3052 | e = [=[ 3053 | test.lua:1:7: syntax error, expected an expression after the additive operator 3054 | ]=] 3055 | 3056 | r = parse(s) 3057 | assert(r == e) 3058 | 3059 | -- ErrMulExpr 3060 | s = [=[ 3061 | foo(b, a *) 3062 | ]=] 3063 | e = [=[ 3064 | test.lua:1:11: syntax error, expected an expression after the multiplicative operator 3065 | ]=] 3066 | 3067 | r = parse(s) 3068 | assert(r == e) 3069 | 3070 | s = [=[ 3071 | x = a * $b 3072 | ]=] 3073 | e = [=[ 3074 | test.lua:1:9: syntax error, expected an expression after the multiplicative operator 3075 | ]=] 3076 | 3077 | r = parse(s) 3078 | assert(r == e) 3079 | 3080 | s = [=[ 3081 | foo(b, a /) 3082 | ]=] 3083 | e = [=[ 3084 | test.lua:1:11: syntax error, expected an expression after the multiplicative operator 3085 | ]=] 3086 | 3087 | r = parse(s) 3088 | assert(r == e) 3089 | 3090 | s = [=[ 3091 | x = a / $b 3092 | ]=] 3093 | e = [=[ 3094 | test.lua:1:9: syntax error, expected an expression after the multiplicative operator 3095 | ]=] 3096 | 3097 | r = parse(s) 3098 | assert(r == e) 3099 | 3100 | s = [=[ 3101 | foo(b, a //) 3102 | ]=] 3103 | e = [=[ 3104 | test.lua:1:12: syntax error, expected an expression after the multiplicative operator 3105 | ]=] 3106 | 3107 | r = parse(s) 3108 | assert(r == e) 3109 | 3110 | s = [=[ 3111 | x = a // $b 3112 | ]=] 3113 | e = [=[ 3114 | test.lua:1:10: syntax error, expected an expression after the multiplicative operator 3115 | ]=] 3116 | 3117 | r = parse(s) 3118 | assert(r == e) 3119 | 3120 | s = [=[ 3121 | foo(b, a %) 3122 | ]=] 3123 | e = [=[ 3124 | test.lua:1:11: syntax error, expected an expression after the multiplicative operator 3125 | ]=] 3126 | 3127 | r = parse(s) 3128 | assert(r == e) 3129 | 3130 | s = [=[ 3131 | x = a % $b 3132 | ]=] 3133 | e = [=[ 3134 | test.lua:1:9: syntax error, expected an expression after the multiplicative operator 3135 | ]=] 3136 | 3137 | r = parse(s) 3138 | assert(r == e) 3139 | 3140 | -- ErrUnaryExpr 3141 | s = [=[ 3142 | x, y = a + not, b 3143 | ]=] 3144 | e = [=[ 3145 | test.lua:1:15: syntax error, expected an expression after the unary operator 3146 | ]=] 3147 | 3148 | r = parse(s) 3149 | assert(r == e) 3150 | 3151 | s = [=[ 3152 | x, y = a + -, b 3153 | ]=] 3154 | e = [=[ 3155 | test.lua:1:13: syntax error, expected an expression after the unary operator 3156 | ]=] 3157 | 3158 | r = parse(s) 3159 | assert(r == e) 3160 | 3161 | s = [=[ 3162 | x, y = a + #, b 3163 | ]=] 3164 | e = [=[ 3165 | test.lua:1:13: syntax error, expected an expression after the unary operator 3166 | ]=] 3167 | 3168 | r = parse(s) 3169 | assert(r == e) 3170 | 3171 | s = [=[ 3172 | x, y = a + ~, b 3173 | ]=] 3174 | e = [=[ 3175 | test.lua:1:13: syntax error, expected an expression after the unary operator 3176 | ]=] 3177 | 3178 | r = parse(s) 3179 | assert(r == e) 3180 | 3181 | -- ErrPowExpr 3182 | s = [=[ 3183 | foo(a ^) 3184 | ]=] 3185 | e = [=[ 3186 | test.lua:1:8: syntax error, expected an expression after '^' 3187 | ]=] 3188 | 3189 | r = parse(s) 3190 | assert(r == e) 3191 | 3192 | s = [=[ 3193 | x = a ^ $b 3194 | ]=] 3195 | e = [=[ 3196 | test.lua:1:9: syntax error, expected an expression after '^' 3197 | ]=] 3198 | 3199 | r = parse(s) 3200 | -- assert(r == e) 3201 | 3202 | -- ErrExprParen 3203 | s = [=[ 3204 | x = () 3205 | ]=] 3206 | e = [=[ 3207 | test.lua:1:6: syntax error, expected an expression after '(' 3208 | ]=] 3209 | 3210 | r = parse(s) 3211 | assert(r == e) 3212 | 3213 | s = [=[ 3214 | y = (???) 3215 | ]=] 3216 | e = [=[ 3217 | test.lua:1:6: syntax error, expected an expression after '(' 3218 | ]=] 3219 | 3220 | r = parse(s) 3221 | assert(r == e) 3222 | 3223 | -- ErrCParenExpr 3224 | s = [=[ 3225 | z = a*(b+c 3226 | ]=] 3227 | e = [=[ 3228 | test.lua:2:1: syntax error, expected ')' to close the expression 3229 | ]=] 3230 | 3231 | r = parse(s) 3232 | assert(r == e) 3233 | 3234 | s = [=[ 3235 | w = (0xBV) 3236 | ]=] 3237 | e = [=[ 3238 | test.lua:1:9: syntax error, expected ')' to close the expression 3239 | ]=] 3240 | 3241 | r = parse(s) 3242 | assert(r == e) 3243 | 3244 | s = [=[ 3245 | ans = 2^(m*(n-1) 3246 | ]=] 3247 | e = [=[ 3248 | test.lua:2:1: syntax error, expected ')' to close the expression 3249 | ]=] 3250 | 3251 | r = parse(s) 3252 | assert(r == e) 3253 | 3254 | -- ErrNameIndex 3255 | s = [=[ 3256 | f = t. 3257 | ]=] 3258 | e = [=[ 3259 | test.lua:2:1: syntax error, expected a field name after '.' 3260 | ]=] 3261 | 3262 | r = parse(s) 3263 | assert(r == e) 3264 | 3265 | s = [=[ 3266 | f = t.['f'] 3267 | ]=] 3268 | e = [=[ 3269 | test.lua:1:7: syntax error, expected a field name after '.' 3270 | ]=] 3271 | 3272 | r = parse(s) 3273 | assert(r == e) 3274 | 3275 | s = [=[ 3276 | x. 3277 | ]=] 3278 | e = [=[ 3279 | test.lua:2:1: syntax error, expected a field name after '.' 3280 | ]=] 3281 | 3282 | r = parse(s) 3283 | assert(r == e) 3284 | 3285 | -- ErrExprIndex 3286 | s = [=[ 3287 | f = t[] 3288 | ]=] 3289 | e = [=[ 3290 | test.lua:1:7: syntax error, expected an expression after '[' 3291 | ]=] 3292 | 3293 | r = parse(s) 3294 | assert(r == e) 3295 | 3296 | s = [=[ 3297 | f = t[?] 3298 | ]=] 3299 | e = [=[ 3300 | test.lua:1:7: syntax error, expected an expression after '[' 3301 | ]=] 3302 | 3303 | r = parse(s) 3304 | assert(r == e) 3305 | 3306 | -- ErrCBracketIndex 3307 | s = [=[ 3308 | f = t[x[y] 3309 | ]=] 3310 | e = [=[ 3311 | test.lua:2:1: syntax error, expected ']' to close the indexing expression 3312 | ]=] 3313 | 3314 | r = parse(s) 3315 | assert(r == e) 3316 | 3317 | s = [=[ 3318 | f = t[x,y] 3319 | ]=] 3320 | e = [=[ 3321 | test.lua:1:8: syntax error, expected ']' to close the indexing expression 3322 | ]=] 3323 | 3324 | r = parse(s) 3325 | assert(r == e) 3326 | 3327 | s = [=[ 3328 | arr[i--] 3329 | ]=] 3330 | e = [=[ 3331 | test.lua:2:1: syntax error, expected ']' to close the indexing expression 3332 | ]=] 3333 | 3334 | r = parse(s) 3335 | assert(r == e) 3336 | 3337 | -- ErrNameMeth 3338 | s = [=[ 3339 | x = obj: 3340 | ]=] 3341 | e = [=[ 3342 | test.lua:2:1: syntax error, expected a method name after ':' 3343 | ]=] 3344 | 3345 | r = parse(s) 3346 | assert(r == e) 3347 | 3348 | s = [=[ 3349 | x := 0 3350 | ]=] 3351 | e = [=[ 3352 | test.lua:1:4: syntax error, expected a method name after ':' 3353 | ]=] 3354 | 3355 | r = parse(s) 3356 | assert(r == e) 3357 | 3358 | -- ErrMethArgs 3359 | s = [=[ 3360 | cow:moo 3361 | ]=] 3362 | e = [=[ 3363 | test.lua:2:1: syntax error, expected some arguments for the method call (or '()') 3364 | ]=] 3365 | 3366 | r = parse(s) 3367 | assert(r == e) 3368 | 3369 | s = [=[ 3370 | dog:bark msg 3371 | ]=] 3372 | e = [=[ 3373 | test.lua:1:10: syntax error, expected some arguments for the method call (or '()') 3374 | ]=] 3375 | 3376 | r = parse(s) 3377 | assert(r == e) 3378 | 3379 | s = [=[ 3380 | duck:quack[4] 3381 | ]=] 3382 | e = [=[ 3383 | test.lua:1:11: syntax error, expected some arguments for the method call (or '()') 3384 | ]=] 3385 | 3386 | r = parse(s) 3387 | assert(r == e) 3388 | 3389 | s = [=[ 3390 | local t = { 3391 | x = X: 3392 | y = Y; 3393 | } 3394 | ]=] 3395 | e = [=[ 3396 | test.lua:3:5: syntax error, expected some arguments for the method call (or '()') 3397 | ]=] 3398 | 3399 | r = parse(s) 3400 | assert(r == e) 3401 | 3402 | -- ErrArgList 3403 | s = [=[ 3404 | foo(a, b, ) 3405 | ]=] 3406 | e = [=[ 3407 | test.lua:1:11: syntax error, expected an expression after ',' in the argument list 3408 | ]=] 3409 | 3410 | r = parse(s) 3411 | assert(r == e) 3412 | 3413 | s = [=[ 3414 | foo(a, b, ..) 3415 | ]=] 3416 | e = [=[ 3417 | test.lua:1:11: syntax error, expected an expression after ',' in the argument list 3418 | ]=] 3419 | 3420 | r = parse(s) 3421 | assert(r == e) 3422 | 3423 | -- ErrCParenArgs 3424 | s = [=[ 3425 | foo(a + (b - c) 3426 | ]=] 3427 | e = [=[ 3428 | test.lua:2:1: syntax error, expected ')' to close the argument list 3429 | ]=] 3430 | 3431 | r = parse(s) 3432 | assert(r == e) 3433 | 3434 | s = [=[ 3435 | foo(arg1 arg2) 3436 | ]=] 3437 | e = [=[ 3438 | test.lua:1:10: syntax error, expected ')' to close the argument list 3439 | ]=] 3440 | 3441 | r = parse(s) 3442 | assert(r == e) 3443 | 3444 | -- ErrCBraceTable 3445 | s = [=[ 3446 | nums = {1, 2, 3] 3447 | ]=] 3448 | e = [=[ 3449 | test.lua:1:16: syntax error, expected '}' to close the table constructor 3450 | ]=] 3451 | 3452 | r = parse(s) 3453 | assert(r == e) 3454 | 3455 | s = [=[ 3456 | nums = { 3457 | one = 1; 3458 | two = 2 3459 | three = 3; 3460 | four = 4 3461 | } 3462 | ]=] 3463 | e = [=[ 3464 | test.lua:4:3: syntax error, expected '}' to close the table constructor 3465 | ]=] 3466 | 3467 | r = parse(s) 3468 | assert(r == e) 3469 | 3470 | -- ErrEqField 3471 | s = [=[ 3472 | words2nums = { ['one'] -> 1 } 3473 | ]=] 3474 | e = [=[ 3475 | test.lua:1:24: syntax error, expected '=' after the table key 3476 | ]=] 3477 | 3478 | r = parse(s) 3479 | assert(r == e) 3480 | 3481 | -- ErrExprField 3482 | s = [=[ 3483 | words2nums = { ['one'] => 2 } 3484 | ]=] 3485 | e = [=[ 3486 | test.lua:1:25: syntax error, expected an expression after '=' 3487 | ]=] 3488 | 3489 | r = parse(s) 3490 | assert(r == e) 3491 | 3492 | -- ErrExprFKey 3493 | s = [=[ 3494 | table = { [] = value } 3495 | ]=] 3496 | e = [=[ 3497 | test.lua:1:12: syntax error, expected an expression after '[' for the table key 3498 | ]=] 3499 | 3500 | r = parse(s) 3501 | assert(r == e) 3502 | 3503 | -- ErrCBracketFKey 3504 | s = [=[ 3505 | table = { [key = value } 3506 | ]=] 3507 | e = [=[ 3508 | test.lua:1:16: syntax error, expected ']' to close the table key 3509 | ]=] 3510 | 3511 | r = parse(s) 3512 | assert(r == e) 3513 | 3514 | 3515 | -- ErrDigitHex 3516 | s = [=[ 3517 | print(0x) 3518 | ]=] 3519 | e = [=[ 3520 | test.lua:1:9: syntax error, expected one or more hexadecimal digits after '0x' 3521 | ]=] 3522 | 3523 | r = parse(s) 3524 | assert(r == e) 3525 | 3526 | s = [=[ 3527 | print(0xGG) 3528 | ]=] 3529 | e = [=[ 3530 | test.lua:1:9: syntax error, expected one or more hexadecimal digits after '0x' 3531 | ]=] 3532 | 3533 | r = parse(s) 3534 | assert(r == e) 3535 | 3536 | -- ErrDigitDeci 3537 | s = [=[ 3538 | print(1 + . 0625) 3539 | ]=] 3540 | e = [=[ 3541 | test.lua:1:12: syntax error, expected one or more digits after the decimal point 3542 | ]=] 3543 | 3544 | r = parse(s) 3545 | assert(r == e) 3546 | 3547 | s = [=[ 3548 | print(.) 3549 | ]=] 3550 | e = [=[ 3551 | test.lua:1:8: syntax error, expected one or more digits after the decimal point 3552 | ]=] 3553 | 3554 | r = parse(s) 3555 | assert(r == e) 3556 | 3557 | -- ErrDigitExpo 3558 | s = [=[ 3559 | print(1.0E) 3560 | ]=] 3561 | e = [=[ 3562 | test.lua:1:11: syntax error, expected one or more digits for the exponent 3563 | ]=] 3564 | 3565 | r = parse(s) 3566 | assert(r == e) 3567 | 3568 | s = [=[ 3569 | print(3E) 3570 | ]=] 3571 | e = [=[ 3572 | test.lua:1:9: syntax error, expected one or more digits for the exponent 3573 | ]=] 3574 | 3575 | r = parse(s) 3576 | assert(r == e) 3577 | 3578 | -- ErrQuote 3579 | s = [=[ 3580 | local message = "Hello 3581 | ]=] 3582 | e = [=[ 3583 | test.lua:2:1: syntax error, unclosed string 3584 | ]=] 3585 | 3586 | r = parse(s) 3587 | assert(r == e) 3588 | 3589 | s = [=[ 3590 | local message = "******* 3591 | Welcome 3592 | *******" 3593 | ]=] 3594 | e = [=[ 3595 | test.lua:2:1: syntax error, unclosed string 3596 | ]=] 3597 | 3598 | r = parse(s) 3599 | assert(r == e) 3600 | 3601 | s = [=[ 3602 | local message = 'Hello 3603 | ]=] 3604 | e = [=[ 3605 | test.lua:2:1: syntax error, unclosed string 3606 | ]=] 3607 | 3608 | r = parse(s) 3609 | assert(r == e) 3610 | 3611 | s = [=[ 3612 | local message = '******* 3613 | Welcome 3614 | *******' 3615 | ]=] 3616 | e = [=[ 3617 | test.lua:2:1: syntax error, unclosed string 3618 | ]=] 3619 | 3620 | r = parse(s) 3621 | assert(r == e) 3622 | 3623 | -- ErrHexEsc 3624 | s = [=[ 3625 | print("\x") 3626 | ]=] 3627 | e = [=[ 3628 | test.lua:1:10: syntax error, expected exactly two hexadecimal digits after '\x' 3629 | ]=] 3630 | 3631 | r = parse(s) 3632 | assert(r == e) 3633 | 3634 | s = [=[ 3635 | print("\xF") 3636 | ]=] 3637 | e = [=[ 3638 | test.lua:1:10: syntax error, expected exactly two hexadecimal digits after '\x' 3639 | ]=] 3640 | 3641 | r = parse(s) 3642 | assert(r == e) 3643 | 3644 | s = [=[ 3645 | print("\xG") 3646 | ]=] 3647 | e = [=[ 3648 | test.lua:1:10: syntax error, expected exactly two hexadecimal digits after '\x' 3649 | ]=] 3650 | 3651 | r = parse(s) 3652 | assert(r == e) 3653 | 3654 | -- ErrOBraceUEsc 3655 | s = [=[ 3656 | print("\u3D") 3657 | ]=] 3658 | e = [=[ 3659 | test.lua:1:10: syntax error, expected '{' after '\u' 3660 | ]=] 3661 | 3662 | r = parse(s) 3663 | assert(r == e) 3664 | 3665 | -- ErrDigitUEsc 3666 | s = [=[ 3667 | print("\u{}") 3668 | ]=] 3669 | e = [=[ 3670 | test.lua:1:11: syntax error, expected one or more hexadecimal digits for the UTF-8 code point 3671 | ]=] 3672 | 3673 | r = parse(s) 3674 | assert(r == e) 3675 | 3676 | s = [=[ 3677 | print("\u{XD}") 3678 | ]=] 3679 | e = [=[ 3680 | test.lua:1:11: syntax error, expected one or more hexadecimal digits for the UTF-8 code point 3681 | ]=] 3682 | 3683 | r = parse(s) 3684 | assert(r == e) 3685 | 3686 | -- ErrCBraceUEsc 3687 | s = [=[ 3688 | print("\u{0x3D}") 3689 | ]=] 3690 | e = [=[ 3691 | test.lua:1:12: syntax error, expected '}' after the code point 3692 | ]=] 3693 | 3694 | r = parse(s) 3695 | assert(r == e) 3696 | 3697 | s = [=[ 3698 | print("\u{FFFF Hi") 3699 | ]=] 3700 | e = [=[ 3701 | test.lua:1:15: syntax error, expected '}' after the code point 3702 | ]=] 3703 | 3704 | r = parse(s) 3705 | assert(r == e) 3706 | 3707 | -- ErrEscSeq 3708 | s = [=[ 3709 | print("\m") 3710 | ]=] 3711 | e = [=[ 3712 | test.lua:1:9: syntax error, invalid escape sequence 3713 | ]=] 3714 | 3715 | r = parse(s) 3716 | assert(r == e) 3717 | 3718 | -- ErrCloseLStr 3719 | s = [===[ 3720 | local message = [==[ 3721 | ******* 3722 | WELCOME 3723 | ******* 3724 | ]=] 3725 | ]===] 3726 | e = [=[ 3727 | test.lua:6:1: syntax error, unclosed long string 3728 | ]=] 3729 | 3730 | r = parse(s) 3731 | assert(r == e) 3732 | 3733 | print("> testing issues...") 3734 | 3735 | -- issue #12 3736 | s = [===[ 3737 | gl_f_ct = 0 3738 | 3739 | function f() 3740 | if gl_f_ct <= 0 then 3741 | gl_f_ct=1 3742 | return 1000 3743 | end 3744 | return -1000 3745 | end 3746 | 3747 | print( f("1st call") > f("2nd call") ) 3748 | gl_f_ct = 0 3749 | print( f("1st call") < f("2nd call") ) 3750 | ]===] 3751 | e = [=[ 3752 | { `Set{ { `Id "gl_f_ct" }, { `Number "0" } }, `Set{ { `Id "f" }, { `Function{ { }, { `If{ `Op{ "le", `Id "gl_f_ct", `Number "0" }, { `Set{ { `Id "gl_f_ct" }, { `Number "1" } }, `Return{ `Number "1000" } } }, `Return{ `Op{ "unm", `Number "1000" } } } } } }, `Call{ `Id "print", `Op{ "gt", `Call{ `Id "f", `String "1st call" }, `Call{ `Id "f", `String "2nd call" } } }, `Set{ { `Id "gl_f_ct" }, { `Number "0" } }, `Call{ `Id "print", `Op{ "lt", `Call{ `Id "f", `String "1st call" }, `Call{ `Id "f", `String "2nd call" } } } } 3753 | ]=] 3754 | 3755 | -- table indentation 3756 | 3757 | s = [===[ 3758 | return {{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}} 3759 | ]===] 3760 | e = [=[ 3761 | { `Return{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table } } } } } } } } } } } } } } } } } 3762 | ]=] 3763 | 3764 | r = parse(s) 3765 | assert(r == e) 3766 | 3767 | s = [===[ 3768 | return {{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}} 3769 | ]===] 3770 | e = [=[ 3771 | { `Return{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table{ `Table } } } } } } } } } } } } } } } } } } 3772 | ]=] 3773 | 3774 | r = parse(s) 3775 | assert(r == e) 3776 | 3777 | r = parse(s) 3778 | assert(r == e) 3779 | 3780 | print("OK") 3781 | --------------------------------------------------------------------------------