aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUndecidable Robot <undecidabot@gmail.com>2016-08-18 12:00:47 +0800
committerUndecidable Robot <undecidabot@gmail.com>2016-08-18 12:00:47 +0800
commitef26e7c4b777ebe9c9c3844bcc818de811369fff (patch)
tree917926c063a8e713fcbfa138f53c722929131576
parent28a44f01cb7a75068b75a99c0badb3abdaf7047a (diff)
downloadlpeglabel-ef26e7c4b777ebe9c9c3844bcc818de811369fff.tar.gz
lpeglabel-ef26e7c4b777ebe9c9c3844bcc818de811369fff.tar.bz2
lpeglabel-ef26e7c4b777ebe9c9c3844bcc818de811369fff.zip
Removing error recovery (moving it out to a different branch)
-rw-r--r--relabel.lua91
-rw-r--r--testrelabelparser.lua174
2 files changed, 28 insertions, 237 deletions
diff --git a/relabel.lua b/relabel.lua
index ff2e486..7fe8645 100644
--- a/relabel.lua
+++ b/relabel.lua
@@ -82,15 +82,9 @@ for i, err in ipairs(errinfo) do
82 labels[err[1]] = i 82 labels[err[1]] = i
83end 83end
84 84
85local syntaxerrs = {}
86
87local function expect (pattern, labelname) 85local function expect (pattern, labelname)
88 local label = labels[labelname] 86 local label = labels[labelname]
89 local record = function (input, pos) 87 return pattern + m.T(label)
90 tinsert(syntaxerrs, { label = label, pos = pos })
91 return true
92 end
93 return pattern + m.Cmt("", record) * m.T(label)
94end 88end
95 89
96 90
@@ -236,72 +230,20 @@ local function labchoice (...)
236 return p 230 return p
237end 231end
238 232
239-- error recovery
240local skip = m.P { "Skip",
241 Skip = (-m.P"/" * -m.P(name * arrow) * m.V"Ignored")^0 * m.Cc(dummy);
242 Ignored = m.V"Group" + any;
243 Group = "(" * (-m.P")" * m.V"Ignored")^0 * ")"
244 + "{" * (-m.P"}" * m.V"Ignored")^0 * "}"
245 + "[" * (-m.P"]" * m.V"Ignored")^0 * "]"
246 + "'" * (-m.P"'" * m.V"Ignored")^0 * "'"
247 + '"' * (-m.P'"' * m.V"Ignored")^0 * '"';
248}
249
250local ignore = m.Cmt(any, function (input, pos)
251 return syntaxerrs[#syntaxerrs].pos, dummy
252end)
253
254local pointAtStart = m.Cmt(any, function (input, pos)
255 -- like ignore but makes the last syntax error point at the start
256 local ret = syntaxerrs[#syntaxerrs].pos
257 syntaxerrs[#syntaxerrs].pos = pos-1
258 return ret, dummy
259end)
260
261
262local function labify (labelnames)
263 for i, l in ipairs(labelnames) do
264 labelnames[i] = labels[l]
265 end
266 return labelnames
267end
268
269local labelset1 = labify {
270 "ExpPatt2", "ExpPatt3",
271 "ExpPatt4", "ExpPatt5", "ExpPatt6", "ExpPatt7",
272 "ExpPatt8", "ExpPattOrClose",
273 "ExpNum", "ExpCap",
274 "ExpName1", "ExpName2", "ExpName3",
275 "ExpNameOrLab", "ExpItem",
276 "MisClose6", "MisClose7"
277}
278
279local labelset2 = labify {
280 "MisClose1", "MisClose2", "MisClose3", "MisClose4", "MisClose5"
281}
282
283local labelset3 = labify {
284 "ExpPatt1", "ExpLab1", "ExpLab2", "MisClose7"
285}
286
287local exp = m.P{ "Exp", 233local exp = m.P{ "Exp",
288 Exp = S * ( m.V"Grammar" 234 Exp = S * ( m.V"Grammar"
289 + (m.V"RecovSeq" * (S * "/" * m.Lc((m.Ct(m.V"Labels") + m.Cc(nil)) 235 + (m.V"Seq" * (S * "/" * (m.Ct(m.V"Labels") + m.Cc(nil))
290 * expect(S * m.V"RecovSeq", 236 * expect(S * m.V"Seq", "ExpPatt1")
291 "ExpPatt1"),
292 m.Cc(nil) * skip,
293 unpack(labelset3))
294 )^0 237 )^0
295 ) / labchoice); 238 ) / labchoice);
296 Labels = m.P"{" * expect(S * m.V"Label", "ExpLab1") 239 Labels = m.P"{" * expect(S * m.V"Label", "ExpLab1")
297 * (S * "," * expect(S * m.V"Label", "ExpLab2"))^0 240 * (S * "," * expect(S * m.V"Label", "ExpLab2"))^0
298 * expect(S * "}", "MisClose7"); 241 * expect(S * "}", "MisClose7");
299 RecovSeq = m.Lc(m.V"Seq", skip, unpack(labelset1));
300 Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix" * (S * m.V"Prefix")^0, mt.__mul); 242 Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix" * (S * m.V"Prefix")^0, mt.__mul);
301 Prefix = "&" * expect(S * m.V"Prefix", "ExpPatt2") / mt.__len 243 Prefix = "&" * expect(S * m.V"Prefix", "ExpPatt2") / mt.__len
302 + "!" * expect(S * m.V"Prefix", "ExpPatt3") / mt.__unm 244 + "!" * expect(S * m.V"Prefix", "ExpPatt3") / mt.__unm
303 + m.V"Suffix"; 245 + m.V"Suffix";
304 Suffix = m.Cf(m.V"RecovPrimary" * 246 Suffix = m.Cf(m.V"Primary" *
305 ( S * ( m.P"+" * m.Cc(1, mt.__pow) 247 ( S * ( m.P"+" * m.Cc(1, mt.__pow)
306 + m.P"*" * m.Cc(0, mt.__pow) 248 + m.P"*" * m.Cc(0, mt.__pow)
307 + m.P"?" * m.Cc(-1, mt.__pow) 249 + m.P"?" * m.Cc(-1, mt.__pow)
@@ -318,11 +260,9 @@ local exp = m.P{ "Exp",
318 "ExpName1") 260 "ExpName1")
319 ) 261 )
320 )^0, function (a,b,f) return f(a,b) end ); 262 )^0, function (a,b,f) return f(a,b) end );
321 RecovPrimary = m.Lc(m.V"Primary", ignore, unpack(labelset2));
322 Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") 263 Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1")
323 + m.Lc(String / mm.P, pointAtStart, 264 + String / mm.P
324 labels["MisTerm1"], labels["MisTerm2"]) 265 + Class
325 + m.Lc(Class, pointAtStart, labels["MisClose8"])
326 + defined 266 + defined
327 + "%" * expect(m.V"Labels", "ExpNameOrLab") / mm.T 267 + "%" * expect(m.V"Labels", "ExpNameOrLab") / mm.T
328 + "{:" * (name * ":" + m.Cc(nil)) * expect(m.V"Exp", "ExpPatt5") 268 + "{:" * (name * ":" + m.Cc(nil)) * expect(m.V"Exp", "ExpPatt5")
@@ -374,23 +314,20 @@ local function compile (p, defs)
374 if mm.type(p) == "pattern" then return p end -- already compiled 314 if mm.type(p) == "pattern" then return p end -- already compiled
375 p = p .. " " -- for better reporting of column numbers in errors when at EOF 315 p = p .. " " -- for better reporting of column numbers in errors when at EOF
376 local ok, cp, label, suffix = pcall(function() return pattern:match(p, 1, defs) end) 316 local ok, cp, label, suffix = pcall(function() return pattern:match(p, 1, defs) end)
377 if not ok and #syntaxerrs == 0 then 317 if not ok and cp then
378 if type(cp) == "string" then 318 if type(cp) == "string" then
379 cp = cp:gsub("^[^:]+:[^:]+: ", "") 319 cp = cp:gsub("^[^:]+:[^:]+: ", "")
380 end 320 end
381 error(cp, 3) 321 error(cp, 3)
382 end 322 end
383 if #syntaxerrs > 0 then 323 if not cp then
384 local lines = splitlines(p) 324 local lines = splitlines(p)
385 local errors = {} 325 local line, col = lineno(p, #p - #suffix + 1)
386 for i, err in ipairs(syntaxerrs) do 326 local err = {}
387 local line, col = lineno(p, err.pos) 327 tinsert(err, "L" .. line .. ":C" .. col .. ": " .. errmsgs[label])
388 tinsert(errors, "L" .. line .. ":C" .. col .. ": " .. errmsgs[err.label]) 328 tinsert(err, lines[line])
389 tinsert(errors, lines[line]) 329 tinsert(err, rep(" ", col-1) .. "^")
390 tinsert(errors, rep(" ", col-1) .. "^") 330 error("syntax error(s) in pattern\n" .. concat(err, "\n"), 3)
391 end
392 syntaxerrs = {}
393 error("syntax error(s) in pattern\n" .. concat(errors, "\n"), 3)
394 end 331 end
395 return cp 332 return cp
396end 333end
diff --git a/testrelabelparser.lua b/testrelabelparser.lua
index 1c5bb9f..46e01ee 100644
--- a/testrelabelparser.lua
+++ b/testrelabelparser.lua
@@ -199,9 +199,6 @@ testerror([[{ {~ } ~}]], [[
199L1:C5: expected a pattern after '{~' 199L1:C5: expected a pattern after '{~'
200{ {~ } ~} 200{ {~ } ~}
201 ^ 201 ^
202L1:C10: missing closing '}'
203{ {~ } ~}
204 ^
205]]) 202]])
206 203
207testerror([[{~ ^_^ ~}]], [[ 204testerror([[{~ ^_^ ~}]], [[
@@ -421,9 +418,6 @@ testerror([[{: group: 'p' :}]], [[
421L1:C9: missing closing ':}' 418L1:C9: missing closing ':}'
422{: group: 'p' :} 419{: group: 'p' :}
423 ^ 420 ^
424L1:C9: unexpected characters after the pattern
425{: group: 'p' :}
426 ^
427]]) 421]])
428 422
429testerror([[S <- {: 'p' T <- 'q']], [[ 423testerror([[S <- {: 'p' T <- 'q']], [[
@@ -447,9 +441,6 @@ testerror([['p' {| 'q' / 'r' }]], [[
447L1:C17: missing closing '|}' 441L1:C17: missing closing '|}'
448'p' {| 'q' / 'r' } 442'p' {| 'q' / 'r' }
449 ^ 443 ^
450L1:C18: unexpected characters after the pattern
451'p' {| 'q' / 'r' }
452 ^
453]]) 444]])
454 445
455-- testing MisClose5 446-- testing MisClose5
@@ -485,186 +476,49 @@ L1:C12: missing closing '}'
485-- testing MisClose8 476-- testing MisClose8
486 477
487testerror([[[]], [[ 478testerror([[[]], [[
488L1:C1: missing closing ']' 479L1:C2: missing closing ']'
489[ 480[
490^ 481 ^
491]]) 482]])
492 483
493testerror([[[^]], [[ 484testerror([[[^]], [[
494L1:C1: missing closing ']' 485L1:C3: missing closing ']'
495[^ 486[^
496^ 487 ^
497]]) 488]])
498 489
499testerror([[[] ]], [[ 490testerror([[[] ]], [[
500L1:C1: missing closing ']' 491L1:C4: missing closing ']'
501[] 492[]
502^ 493 ^
503]]) 494]])
504 495
505testerror([[[^] ]], [[ 496testerror([[[^] ]], [[
506L1:C1: missing closing ']' 497L1:C6: missing closing ']'
507[^] 498[^]
508^ 499 ^
509]]) 500]])
510 501
511testerror([[[_-___-_|]], [[ 502testerror([[[_-___-_|]], [[
512L1:C1: missing closing ']' 503L1:C10: missing closing ']'
513[_-___-_| 504[_-___-_|
514^ 505 ^
515]]) 506]])
516 507
517-- testing MisTerm1 508-- testing MisTerm1
518 509
519testerror([['That is the question...]], [[ 510testerror([['That is the question...]], [[
520L1:C1: missing terminating single quote 511L1:C25: missing terminating single quote
521'That is the question... 512'That is the question...
522^ 513 ^
523]]) 514]])
524 515
525-- testing MisTerm2 516-- testing MisTerm2
526 517
527testerror([[Q <- "To be or not to be...]], [[ 518testerror([[Q <- "To be or not to be...]], [[
528L1:C6: missing terminating double quote 519L1:C28: missing terminating double quote
529Q <- "To be or not to be... 520Q <- "To be or not to be...
530 ^ 521 ^
531]])
532
533-- testing error recovery, more complex grammars (multiline),
534-- and pointer positions in error recovery
535
536testerror([[&'p'/&/!/'p'^'q']], [[
537L1:C7: expected a pattern after '&'
538&'p'/&/!/'p'^'q'
539 ^
540L1:C9: expected a pattern after '!'
541&'p'/&/!/'p'^'q'
542 ^
543L1:C14: expected a number after '^', '+' or '-' (no space)
544&'p'/&/!/'p'^'q'
545 ^
546]])
547
548testerror([[
549 A <- 'a' (B 'b'
550 B <- 'x' / !
551 C <- 'c'
552]], [[
553L1:C18: missing closing ')'
554 A <- 'a' (B 'b'
555 ^
556L2:C15: expected a pattern after '!'
557 B <- 'x' / !
558 ^
559]])
560
561testerror([['a' / &@ ('c' / 'd')]], [[
562L1:C8: expected a pattern after '&'
563'a' / &@ ('c' / 'd')
564 ^
565]])
566
567testerror([['x' / & / 'y']], [[
568L1:C8: expected a pattern after '&'
569'x' / & / 'y'
570 ^
571]])
572
573testerror([[&/'p'/!/'q']], [[
574L1:C2: expected a pattern after '&'
575&/'p'/!/'q'
576 ^
577L1:C8: expected a pattern after '!'
578&/'p'/!/'q'
579 ^
580]])
581
582testerror([['p'//'q']], [[
583L1:C5: expected a pattern after '/' or the label(s)
584'p'//'q'
585 ^
586]])
587
588testerror([[
589 S <- 'forgot to close / T
590 T <- 'T' & / 't'
591]], [[
592L1:C8: missing terminating single quote
593 S <- 'forgot to close / T
594 ^
595L2:C13: expected a pattern after '&'
596 T <- 'T' & / 't'
597 ^
598]])
599
600testerror([[
601 S <- [a-z / T
602 T <- 'x' / & / 'y'
603]], [[
604L1:C8: missing closing ']'
605 S <- [a-z / T
606 ^
607L2:C15: expected a pattern after '&'
608 T <- 'x' / & / 'y'
609 ^
610]])
611
612testerror([[
613 S <- ('p' -- comment
614]], [[
615L1:C12: missing closing ')'
616 S <- ('p' -- comment
617 ^
618]])
619
620-- an unfortunate second error exists because we don't know
621-- what's part of the quotation
622testerror([[
623 X <- ('p / Q (R
624 / S))
625 Q <- 'q'
626 R <- 'r'
627 S <- 's'
628]], [[
629L1:C9: missing terminating single quote
630 X <- ('p / Q (R
631 ^
632L2:C9: unexpected characters after the pattern
633 / S))
634 ^
635]])
636
637testerror([[
638 A <- 'A' /{'lab'} B / !
639
640 B <- %{1, 2 3} 'b' / '6' & / 'B'
641
642 C <- A^B
643]], [[
644L1:C14: expected at least one label after '{'
645 A <- 'A' /{'lab'} B / !
646 ^
647L1:C26: expected a pattern after '!'
648 A <- 'A' /{'lab'} B / !
649 ^
650L3:C15: missing closing '}'
651 B <- %{1, 2 3} 'b' / '6' & / 'B'
652 ^
653L3:C29: expected a pattern after '&'
654 B <- %{1, 2 3} 'b' / '6' & / 'B'
655 ^
656L5:C10: expected a number after '^', '+' or '-' (no space)
657 C <- A^B
658 ^
659]])
660
661testerror([['p'/{1/'q'/&]], [[
662L1:C7: missing closing '}'
663'p'/{1/'q'/&
664 ^
665L1:C13: expected a pattern after '&'
666'p'/{1/'q'/&
667 ^
668]]) 522]])
669 523
670-- testing non-syntax errors 524-- testing non-syntax errors