diff options
author | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-05 16:50:33 -0300 |
---|---|---|
committer | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-05 16:50:33 -0300 |
commit | 030df9b4a4f4dc3a2cc5775e032f83e92d3c0097 (patch) | |
tree | d150ffdf74711a479e8bef584c1099e5c2fa408a | |
parent | 54443578aaef5d2198ab772c7f5f53b330f80a7d (diff) | |
download | lpeglabel-030df9b4a4f4dc3a2cc5775e032f83e92d3c0097.tar.gz lpeglabel-030df9b4a4f4dc3a2cc5775e032f83e92d3c0097.tar.bz2 lpeglabel-030df9b4a4f4dc3a2cc5775e032f83e92d3c0097.zip |
Adding p^name as syntactic sugar for p / T(name) in relabel
-rw-r--r-- | relabel.lua | 12 | ||||
-rw-r--r-- | testlabel.lua | 213 |
2 files changed, 223 insertions, 2 deletions
diff --git a/relabel.lua b/relabel.lua index 87269be..642b0fe 100644 --- a/relabel.lua +++ b/relabel.lua | |||
@@ -241,6 +241,13 @@ local function choicerec (...) | |||
241 | return p | 241 | return p |
242 | end | 242 | end |
243 | 243 | ||
244 | local function getlab (f) | ||
245 | if not tlabels[f] then | ||
246 | error("undefined label: " .. f) | ||
247 | end | ||
248 | return mm.T(tlabels[f]) | ||
249 | end | ||
250 | |||
244 | local exp = m.P{ "Exp", | 251 | local exp = m.P{ "Exp", |
245 | Exp = S * ( m.V"Grammar" | 252 | Exp = S * ( m.V"Grammar" |
246 | + (m.V"Seq" * (S * ((m.C(m.P"//" + "/") * m.Ct(m.V"Labels")) + (m.C"/" * m.Cc(false))) | 253 | + (m.V"Seq" * (S * ((m.C(m.P"//" + "/") * m.Ct(m.V"Labels")) + (m.C"/" * m.Cc(false))) |
@@ -260,6 +267,7 @@ local exp = m.P{ "Exp", | |||
260 | + m.P"?" * m.Cc(-1, mt.__pow) | 267 | + m.P"?" * m.Cc(-1, mt.__pow) |
261 | + "^" * expect( m.Cg(num * m.Cc(mult)) | 268 | + "^" * expect( m.Cg(num * m.Cc(mult)) |
262 | + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow) | 269 | + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow) |
270 | + name * m.Cc"lab" | ||
263 | ), | 271 | ), |
264 | "ExpNum") | 272 | "ExpNum") |
265 | + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) | 273 | + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) |
@@ -270,7 +278,7 @@ local exp = m.P{ "Exp", | |||
270 | + "=>" * expect(S * m.Cg(Def / getdef * m.Cc(m.Cmt)), | 278 | + "=>" * expect(S * m.Cg(Def / getdef * m.Cc(m.Cmt)), |
271 | "ExpName1") | 279 | "ExpName1") |
272 | ) | 280 | ) |
273 | )^0, function (a,b,f) return f(a,b) end ); | 281 | )^0, function (a,b,f) if f == "lab" then return a + getlab(b) else return f(a,b) end end ); |
274 | Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") | 282 | Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") |
275 | + String / mm.P | 283 | + String / mm.P |
276 | + Class | 284 | + Class |
@@ -293,7 +301,7 @@ local exp = m.P{ "Exp", | |||
293 | + m.P"." * m.Cc(any) | 301 | + m.P"." * m.Cc(any) |
294 | + (name * -arrow + "<" * expect(name, "ExpName3") | 302 | + (name * -arrow + "<" * expect(name, "ExpName3") |
295 | * expect(">", "MisClose6")) * m.Cb("G") / NT; | 303 | * expect(">", "MisClose6")) * m.Cb("G") / NT; |
296 | Label = num + name / function (f) return tlabels[f] end; | 304 | Label = num + name / function (f) return getlab(f) end; |
297 | Definition = name * arrow * expect(m.V"Exp", "ExpPatt8"); | 305 | Definition = name * arrow * expect(m.V"Exp", "ExpPatt8"); |
298 | Grammar = m.Cg(m.Cc(true), "G") | 306 | Grammar = m.Cg(m.Cc(true), "G") |
299 | * m.Cf(m.V"Definition" / firstdef * (S * m.Cg(m.V"Definition"))^0, | 307 | * m.Cf(m.V"Definition" / firstdef * (S * m.Cg(m.V"Definition"))^0, |
diff --git a/testlabel.lua b/testlabel.lua index 2d9233a..d3d95b1 100644 --- a/testlabel.lua +++ b/testlabel.lua | |||
@@ -1267,4 +1267,217 @@ assert(eval("1+") == 4) | |||
1267 | --> syntax error: expected a term after the operator (at index 3) | 1267 | --> syntax error: expected a term after the operator (at index 3) |
1268 | 1268 | ||
1269 | 1269 | ||
1270 | -- tests related to the use of '^' in relabel to throw labels | ||
1271 | local errinfo = { | ||
1272 | { 'cmdSeq', "Missing ';' in CmdSeq"}, | ||
1273 | { 'ifExp', "Error in expresion of 'if'"}, | ||
1274 | { 'ifThen', "Error matching 'then' keyword"}, | ||
1275 | { 'ifThenCmdSeq', "Error matching CmdSeq of 'then' branch"}, | ||
1276 | { 'ifElseCmdSeq', "Error matching CmdSeq of 'else' branch"}, | ||
1277 | { 'ifEnd', "Error matching 'end' keyword of 'if'"}, | ||
1278 | { 'repeatCmdSeq', "Error matching CmdSeq of 'repeat'"}, | ||
1279 | { 'repeatUntil', "Error matching 'until' keyword"}, | ||
1280 | { 'repeatExp', "Error matching expression of 'until'"}, | ||
1281 | { 'assignOp', "Error matching ':='"}, | ||
1282 | { 'assignExp', "Error matching expression of assignment"}, | ||
1283 | { 'readName', "Error matching 'NAME' after 'read'"}, | ||
1284 | { 'writeExp', "Error matching expression after 'write'"}, | ||
1285 | { 'simpleExp', "Error matching 'SimpleExp'"}, | ||
1286 | { 'term', "Error matching 'Term'"}, | ||
1287 | { 'factor', "Error matching 'Factor'"}, | ||
1288 | { 'openParExp', "Error matching expression after '('"}, | ||
1289 | { 'closePar', "Error matching ')'"}, | ||
1290 | { 'undefined', "Undefined Error" } | ||
1291 | } | ||
1292 | |||
1293 | |||
1294 | local errmsgs = {} | ||
1295 | local labels = {} | ||
1296 | |||
1297 | for i, err in ipairs(errinfo) do | ||
1298 | errmsgs[i] = err[2] | ||
1299 | labels[err[1]] = i | ||
1300 | end | ||
1301 | |||
1302 | re.setlabels(labels) | ||
1303 | |||
1304 | g = re.compile([[ | ||
1305 | Tiny <- CmdSeq | ||
1306 | CmdSeq <- (Cmd SEMICOLON^cmdSeq) (Cmd SEMICOLON^cmdSeq)* | ||
1307 | Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd | ||
1308 | IfCmd <- IF Exp^ifExp THEN^ifThen CmdSeq^ifThenCmdSeq (ELSE CmdSeq^ifElseCmdSeq / '') END^ifEnd | ||
1309 | RepeatCmd <- REPEAT CmdSeq^repeatCmdSeq UNTIL^repeatUntil Exp^repeatExp | ||
1310 | AssignCmd <- NAME ASSIGNMENT^assignOp Exp^assignExp | ||
1311 | ReadCmd <- READ NAME^readName | ||
1312 | WriteCmd <- WRITE Exp^writeExp | ||
1313 | Exp <- SimpleExp ((LESS / EQUAL) SimpleExp^simpleExp / '') | ||
1314 | SimpleExp <- Term ((ADD / SUB) Term^term)* | ||
1315 | Term <- Factor ((MUL / DIV) Factor^factor)* | ||
1316 | Factor <- OPENPAR Exp^openParExp CLOSEPAR^closePar / NUMBER / NAME | ||
1317 | ADD <- Sp '+' | ||
1318 | ASSIGNMENT <- Sp ':=' | ||
1319 | CLOSEPAR <- Sp ')' | ||
1320 | DIV <- Sp '/' | ||
1321 | IF <- Sp 'if' | ||
1322 | ELSE <- Sp 'else' | ||
1323 | END <- Sp 'end' | ||
1324 | EQUAL <- Sp '=' | ||
1325 | LESS <- Sp '<' | ||
1326 | MUL <- Sp '*' | ||
1327 | NAME <- !RESERVED Sp [a-z]+ | ||
1328 | NUMBER <- Sp [0-9]+ | ||
1329 | OPENPAR <- Sp '(' | ||
1330 | READ <- Sp 'read' | ||
1331 | REPEAT <- Sp 'repeat' | ||
1332 | SEMICOLON <- Sp ';' | ||
1333 | SUB <- Sp '-' | ||
1334 | THEN <- Sp 'then' | ||
1335 | UNTIL <- Sp 'until' | ||
1336 | WRITE <- Sp 'write' | ||
1337 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ | ||
1338 | Sp <- (%s / %nl)* | ||
1339 | ]], terror) | ||
1340 | |||
1341 | s = [[ | ||
1342 | n := 5;]] | ||
1343 | assert(g:match(s) == #s + 1) | ||
1344 | |||
1345 | s = [[ | ||
1346 | n := 5; | ||
1347 | f := 1; | ||
1348 | repeat | ||
1349 | f := f * n; | ||
1350 | n := n - 1; | ||
1351 | until (n < 1); | ||
1352 | write f;]] | ||
1353 | assert(g:match(s) == #s + 1) | ||
1354 | |||
1355 | -- a ';' is missing in 'read a' | ||
1356 | s = [[ | ||
1357 | read a]] | ||
1358 | assert(table.pack(g:match(s))[2] == labels['cmdSeq']) | ||
1359 | |||
1360 | |||
1361 | -- a ';' is missing in 'n := n - 1' | ||
1362 | s = [[ | ||
1363 | n := 5; | ||
1364 | f := 1; | ||
1365 | repeat | ||
1366 | f := f * n; | ||
1367 | n := n - 1 | ||
1368 | until (n < 1); | ||
1369 | write f;]] | ||
1370 | assert(table.pack(g:match(s))[2] == labels['cmdSeq']) | ||
1371 | |||
1372 | |||
1373 | -- IF expression | ||
1374 | s = [[ | ||
1375 | if a then a := a + 1; end;]] | ||
1376 | assert(g:match(s) == #s + 1) | ||
1377 | |||
1378 | -- IF expression | ||
1379 | s = [[ | ||
1380 | if a then a := a + 1; else write 2; end;]] | ||
1381 | assert(g:match(s) == #s + 1) | ||
1382 | |||
1383 | -- Error in expression of 'if'. 'A' is not a valida name | ||
1384 | s = [[ | ||
1385 | if A then a := a + 1; else write 2; end;]] | ||
1386 | assert(table.pack(g:match(s))[2] == labels['ifExp']) | ||
1387 | |||
1388 | -- Error matching the 'then' keyword | ||
1389 | s = [[ | ||
1390 | if a a := a + 1; else write 2; end;]] | ||
1391 | assert(table.pack(g:match(s))[2] == labels['ifThen']) | ||
1392 | |||
1393 | -- Error matching the CmdSeq inside of 'then' branch | ||
1394 | s = [[ | ||
1395 | if a then 3 := 2; else write 2; end;]] | ||
1396 | assert(table.pack(g:match(s))[2] == labels['ifThenCmdSeq']) | ||
1397 | |||
1398 | -- Error matching the CmdSeq inside of 'else' branch | ||
1399 | s = [[ | ||
1400 | if a then b := 2; else A := 2; end;]] | ||
1401 | assert(table.pack(g:match(s))[2] == labels['ifElseCmdSeq']) | ||
1402 | |||
1403 | -- Error matching 'end' of 'if' | ||
1404 | s = [[ | ||
1405 | if a then b := 2; else a := 2; 77;]] | ||
1406 | assert(table.pack(g:match(s))[2] == labels['ifEnd']) | ||
1407 | |||
1408 | -- Error matching the CmdSeq of 'repeat' | ||
1409 | s = [[repeat | ||
1410 | F := f * n; | ||
1411 | n := n - 1; | ||
1412 | until (n < 1);]] | ||
1413 | assert(table.pack(g:match(s))[2] == labels['repeatCmdSeq']) | ||
1414 | |||
1415 | -- Error matching 'until' | ||
1416 | s = [[repeat | ||
1417 | f := f * n; | ||
1418 | n := n - 1; | ||
1419 | 88 (n < 1);]] | ||
1420 | assert(table.pack(g:match(s))[2] == labels['repeatUntil']) | ||
1421 | |||
1422 | -- Error matching expression of 'until' | ||
1423 | s = [[repeat | ||
1424 | f := f * n; | ||
1425 | n := n - 1; | ||
1426 | until ; (n < 1);]] | ||
1427 | assert(table.pack(g:match(s))[2] == labels['repeatExp']) | ||
1428 | |||
1429 | -- Error matching ':=' | ||
1430 | s = [[ | ||
1431 | f = f * n;]] | ||
1432 | assert(table.pack(g:match(s))[2] == labels['assignOp']) | ||
1433 | |||
1434 | -- Error matching expression of assignment | ||
1435 | s = [[ | ||
1436 | f := A * n;]] | ||
1437 | assert(table.pack(g:match(s))[2] == labels['assignExp']) | ||
1438 | |||
1439 | -- Error matching 'name' | ||
1440 | s = [[ | ||
1441 | read 2;]] | ||
1442 | assert(table.pack(g:match(s))[2] == labels['readName']) | ||
1443 | |||
1444 | -- Error matching expression after 'write' | ||
1445 | s = [[ | ||
1446 | write [a] := 2;]] | ||
1447 | assert(table.pack(g:match(s))[2] == labels['writeExp']) | ||
1448 | |||
1449 | -- Error matching 'SimpleExp' | ||
1450 | s = [[ | ||
1451 | a := a < A;]] | ||
1452 | assert(table.pack(g:match(s))[2] == labels['simpleExp']) | ||
1453 | |||
1454 | -- Error matching 'Term' | ||
1455 | s = [[ | ||
1456 | a := a + A;]] | ||
1457 | assert(table.pack(g:match(s))[2] == labels['term']) | ||
1458 | |||
1459 | -- Error matching 'Factor' | ||
1460 | s = [[ | ||
1461 | a := a * A;]] | ||
1462 | assert(table.pack(g:match(s))[2] == labels['factor']) | ||
1463 | |||
1464 | -- Error matching expression after '(' | ||
1465 | s = [[ | ||
1466 | a := (A);]] | ||
1467 | assert(table.pack(g:match(s))[2] == labels['openParExp']) | ||
1468 | |||
1469 | -- Error matching ')' | ||
1470 | s = [[ | ||
1471 | a := (a];]] | ||
1472 | assert(table.pack(g:match(s))[2] == labels['closePar']) | ||
1473 | |||
1474 | -- Error undefined | ||
1475 | s = [[ | ||
1476 | A := a;]] | ||
1477 | assert(table.pack(g:match(s))[2] == 0) | ||
1478 | |||
1479 | |||
1480 | |||
1481 | |||
1482 | |||
1270 | print("OK") | 1483 | print("OK") |