Author: pmichaud
Date: Thu Feb 9 23:09:08 2006
New Revision: 11495
Modified:
trunk/compilers/pge/PGE/OPTable.pir
trunk/compilers/pge/PGE/P6Rule.pir
trunk/lib/Parrot/Test/PGE.pm
trunk/t/compilers/pge/p6rules/builtins.t
trunk/t/compilers/pge/p6rules/cclass.t
trunk/t/compilers/pge/p6rules/metachars.t
Log:
* Improved parse error handling in operator precedence parser
* Updated Test/PGE.pm to report invalid rules
Modified: trunk/compilers/pge/PGE/OPTable.pir
==============================================================================
--- trunk/compilers/pge/PGE/OPTable.pir (original)
+++ trunk/compilers/pge/PGE/OPTable.pir Thu Feb 9 23:09:08 2006
@@ -286,6 +286,7 @@ representing the result of the parse.
unless tok goto expect_term_empty
bsr tok_match
if oper goto found_term
+ if key == "" goto null_term
expect_term_empty:
unless termempty goto null_term
tok = termempty
@@ -294,14 +295,19 @@ representing the result of the parse.
bsr tok_match
if oper goto found_term
null_term:
- unless tokstack goto term_error
+ unless tokstack goto missing_term
top = tokstack[-1]
$S0 = top["opts"]
$I0 = index $S0, "nullterm"
- if $I0 < 0 goto term_error
- oper = newfrom(mob, wspos, "PGE::Match")
+ if $I0 < 0 goto missing_term
+ (oper, $S0, $P0, $P1) = newfrom(mob, wspos, "PGE::Match")
+ $P1 = wspos
push termstack, oper
goto expect_oper
+ missing_term:
+ $P0 = newfrom(mob, wspos, "PGE::Match")
+ push termstack, $P0
+ goto end
found_term:
tokcat = tok["syncat"]
pos = oper.to()
@@ -380,13 +386,19 @@ representing the result of the parse.
arity = $P0["arity"]
$P0 = pop operstack
reduce_args:
- if arity < 1 goto reduce_end
- dec arity
+ if arity < 1 goto reduce_saveterm
$P1 = pop termstack
+ unless $P1 goto reduce_backtrack
+ dec arity
$P0[arity] = $P1
goto reduce_args
- reduce_end:
+ reduce_backtrack:
+ pos = $P0.from()
+ if arity > 1 goto reduce_end
+ $P0 = $P1
+ reduce_saveterm:
push termstack, $P0
+ reduce_end:
ret
tok_match:
@@ -413,20 +425,15 @@ representing the result of the parse.
bsr reduce
goto end
end_1:
+ $I0 = elements termstack
+ if $I0 < 1 goto end_2
$P0 = pop termstack
+ unless $P0 goto end_2
mob["expr"] = $P0
mpos = pos
.return (mob)
-
- term_error:
- $P0 = new .Exception
- $S0 = "Missing term at offset "
- $S1 = wspos
- $S0 .= $S1
- $S0 .= "\n"
- $P0["_message"] = $S0
- throw $P0
- mpos = -1
+ end_2:
+ mpos = -1
.return (mob)
ternary_error:
Modified: trunk/compilers/pge/PGE/P6Rule.pir
==============================================================================
--- trunk/compilers/pge/PGE/P6Rule.pir (original)
+++ trunk/compilers/pge/PGE/P6Rule.pir Thu Feb 9 23:09:08 2006
@@ -610,6 +610,8 @@
.local pmc sub
.local pmc pad
+ null code
+ null sub
if has_name goto p6rule_1
name = "_pge_rule"
if has_gram goto p6rule_1
@@ -621,6 +623,9 @@
$P0 = find_global "PGE::Rule", "p6rule"
exp = $P0(exp)
+ unless exp goto end
+ $S0 = exp
+ if $S0 != pattern goto end
pad = new .Hash
$P0 = new .Hash
pad["reps"] = $P0
@@ -630,6 +635,7 @@
$P0 = exp["expr"]
$P0 = $P0.p6analyze(pad)
exp["expr"] = $P0
+ if_null $P0, end
$P0 = new .String
$P0 = "\n.namespace [ \""
Modified: trunk/lib/Parrot/Test/PGE.pm
==============================================================================
--- trunk/lib/Parrot/Test/PGE.pm (original)
+++ trunk/lib/Parrot/Test/PGE.pm Thu Feb 9 23:09:08 2006
@@ -201,15 +201,19 @@ sub _generate_pir_for {
target = $unicode"$target"
pattern = "$pattern"
(rulesub, code, exp) = p6rule_compile(pattern)
+ if_null rulesub, rule_fail
match = rulesub(target)
unless match goto match_fail
match_success:
print "matched"
$captures
- goto match_end
+ goto end
match_fail:
print "failed"
- match_end:
+ goto end
+ rule_fail:
+ print "rule error"
+ end:
.end\n);
}
Modified: trunk/t/compilers/pge/p6rules/builtins.t
==============================================================================
--- trunk/t/compilers/pge/p6rules/builtins.t (original)
+++ trunk/t/compilers/pge/p6rules/builtins.t Thu Feb 9 23:09:08 2006
@@ -188,7 +188,7 @@ p6rule_is ('az', '<+alpha>+', 'metasynt
## null pattern is illegal
-p6rule_like($str, '', '/Missing term at offset.*/',
+p6rule_like($str, '', '/rule error/',
'null pattern ()');
Modified: trunk/t/compilers/pge/p6rules/cclass.t
==============================================================================
--- trunk/t/compilers/pge/p6rules/cclass.t (original)
+++ trunk/t/compilers/pge/p6rules/cclass.t Thu Feb 9 23:09:08 2006
@@ -94,7 +94,7 @@ p6rule_is ('---x--', '<-[+\-]>?', 'nega
p6rule_is ('------', '<-[+\-]>?', 'negated optional escaped hyphen in range');
# 'greater than' and 'less than' need no escapes
-p6rule_is ('><', '^><[<]>', 'lt character class');
+p6rule_like('><', '^><[<]>', '/rule error/', 'lt character class');
p6rule_is ('><', '^<[>]><', 'gt character class',
todo => 'parse error not yet implemented');
p6rule_is ('><', '^<[><]>**{2}', 'gt, lt character class');
Modified: trunk/t/compilers/pge/p6rules/metachars.t
==============================================================================
--- trunk/t/compilers/pge/p6rules/metachars.t (original)
+++ trunk/t/compilers/pge/p6rules/metachars.t Thu Feb 9 23:09:08 2006
@@ -120,7 +120,7 @@ p6rule_is ("bcd", '<[a..d]>+ | <[b..e]>
p6rule_is ("bcd", '^ <[a..d]>+ | <[b..e]>+ $', 'alternation (|)');
p6rule_is ("bcd", '<[a..c]>+ | <[b..e]>+', 'alternation (|)');
p6rule_is ("bcd", '<[a..d]>+ | <[c..e]>+', 'alternation (|)');
-p6rule_like("bcd", 'b|', '/Missing term/', 'alternation (|) - null right arg
illegal');
+p6rule_like("bcd", 'b|', '/rule error/', 'alternation (|) - null right arg
illegal');
p6rule_like("bcd", '|b', '/Missing term/', 'alternation (|) - null left arg
illegal', todo => 'not yet implemented');
p6rule_like("bcd", '|', '/Missing term/', 'alternation (|) - null both args
illegal', todo => 'not yet implemented');
p6rule_is ("|", '\|', 'alternation (|) - literal must be escaped');
@@ -133,7 +133,7 @@ p6rule_is ("bcd", '<[a..d]>+ & <[b..e]>
p6rule_is ("bcd", '^ <[a..d]>+ & <[b..e]>+ $', 'conjunction (&)');
p6rule_is ("bcd", '<[a..c]>+ & <[b..e]>+', 'conjunction (&)');
p6rule_is ("bcd", '<[a..d]>+ & <[c..e]>+', 'conjunction (&)');
-p6rule_like("bcd", 'b&', '/Missing term/', 'conjunction (&) - null right arg
illegal');
+p6rule_like("bcd", 'b&', '/rule error/', 'conjunction (&) - null right arg
illegal');
p6rule_like("bcd", '&b', '/Missing term/', 'conjunction (&) - null left arg
illegal', todo => 'not yet implemented');
p6rule_like("bcd", '&', '/Missing term/', 'conjunction (&) - null both args
illegal', todo => 'not yet implemented');
p6rule_is ("&", '\&', 'conjunction (&) - literal must be escaped');