AJF-26: Bracketing matters in throws patterns
Reported by Pavel:> The ‘throws’ pattern is a very special case, in
Submitted on 7 June 2006 at 14:27
> that bracketing actually can carry meaning. Consider these two pointcuts:
>
> call(* (..) throws !Ex)
> call( *(..) throws (!Ex))
>
> They mean different things in AspectJ: The former means ‘a call to any
> method that does not throw Ex’, the latter ‘a call to any method that
> throws an exception other than Ex’. Thus, the two need to have
> different abstract syntax, otherwise it is impossible to tell them
> apart. Would it be possible to do something like this?
Issue Log
AJF-26, martin:
Sure, this is possible. Is this the only place where the
brackets matter? And, do they matter only at the top-level of the
throws pattern?There are two solutions: make brackets explicit everywhere in the AST
(yuk) or make brackets explicit in the AST only in this location
(requires some hackery, but is possible). I would prefer the second
solution to not pollute the AST everywhere.
AJF-26, martin:
Pavel wrote: As I understand it, it is the only place where brackets matter, and it
is indeed only the top-level bracketing that matters. So I would also
suggest sticking to the second solution you mentioned.
AJF-26, martin:
Ok, this problem is now solved by introducing two new cases:context-free syntax
“throws” {ExceptionPattern “,”}+ -> ThrowsPattern {cons(“ThrowsPattern”)}"(" ClassNamePattern ")" -> ExceptionPattern {cons("ExceptionCondition")} ClassNamePattern -> ExceptionPattern {cons("ThrowsCondition")}
context-free priorities
ClassNamePattern -> ExceptionPattern
> “(” ClassNamePattern “)” -> ClassNamePatternThe constructor names illustrate the semantics of the two cases: in
the first case it is a condition on the specific condition. In the
second case, it is a condition on the entire throws clause.The obscure priority solves the ambiguity between the two cases, since
the second production actually also allows brackets at the top
level. The priority forbids this directly under the production of a
ClassNamePattern to an ExceptionPattern.$ echo ‘call(* *(..) throws !Ex)’ | sglri -p aspectj-testing.tbl -s PointcutExpr | pp-aterm
Call(
MethodPattern(
AnnoPattern([])
, ModPattern([])
, RefTypePattern(NamePattern(“*”))
, MemberName(“*”)
, [FormalWildcard]
, Some(ThrowsPattern([ThrowsCondition(NotComp(SimpleNamePattern(NamePattern(“Ex”))))]))
)
)$ echo ‘call(* *(..) throws (!Ex))’ | sglri -p aspectj-testing.tbl -s PointcutExpr | pp-aterm
Call(
MethodPattern(
AnnoPattern([])
, ModPattern([])
, RefTypePattern(NamePattern(“*”))
, MemberName(“*”)
, [FormalWildcard]
, Some(ThrowsPattern([ExceptionCondition(NotComp(SimpleNamePattern(NamePattern(“Ex”))))]))
)
)$ echo ‘call(* *(..) throws Exc1 && (!Ex))’ | sglri -p aspectj-testing.tbl -s PointcutExpr | pp-aterm
Call(
MethodPattern(
AnnoPattern([])
, ModPattern([])
, RefTypePattern(NamePattern(“*”))
, MemberName(“*”)
, [FormalWildcard]
, Some(
ThrowsPattern(
[ThrowsCondition(
AndComp(SimpleNamePattern(NamePattern(“Exc1”)), NotComp(SimpleNamePattern(NamePattern(“Ex”))))
)]
)
)
)
)
AJF-26, martin:
There was a typo in the previous comment. The fixed version is:The constructor names illustrate the semantics of the two cases: in the first case it is a condition on the specific exception. In the second case, it is a condition on the entire throws clause.
Log in to post comments