我想找到所有没有break语句的case语句。我使用clang-query构建匹配器。我的匹配器在某些测试用例中失败。
我写的简单匹配器为
match caseStmt(除非(有(breakStmt())))
它与以下测试用例一起使用
#include<stdlib.h>
int main(){
int x;
switch(x){
case 1:
break;
case 2:
default:
x++;
}
return 0;
}
int main()
{
int x = 1, y = 2;
// Outer Switch
switch (x) {
// If x == 1
case 1:
// Nested Switch
switch (y) {
// If y == 2
case 2:
//break;
// If y == 3
case 3:
break;
}
break;
// If x == 4
case 4:
break;
// If x == 5
case 5:
break;
default:
break;
}
return 0;
}
配合使用
#include <iostream>
using namespace std;
int main()
{
int x = 1, y = 2;
// Outer Switch
switch (x) {
// If x == 1
case 1:
// Nested Switch
switch (y) {
// If y == 2
case 2:
cout << "Choice is 2";
//break;
// If y == 3
case 3:
cout << "Choice is 3";
break;
}
//break;
// If x == 4
case 4:
cout << "Choice is 4";
break;
// If x == 5
case 5:
cout << "Choice is 5";
break;
default:
cout << "Choice is other than 1, 2 3, 4, or 5";
break;
}
return 0;
}
在上面的案例中,它显示了带有break语句的case语句以及没有break语句的case语句。
我在做什么错?请帮助:)我正在关注 http://releases.llvm.org/8.0.0/tools/clang/docs/LibASTMatchersTutorial.html
答案 0 :(得分:1)
不幸的是,这是行不通的:-(
case
从技术上讲是label
,而label
的子元素只有一个。如果您打印出AST,则会看到case
和break
语句处于同一级别:
| |-CaseStmt 0x5618732e1e30 <line:29:3, line:30:9>
| | |-IntegerLiteral 0x5618732e1e10 <line:29:8> 'int' 4
| | |-<<<NULL>>>
| | `-CallExpr 0x5618732e1f00 <line:30:5, col:9> 'void'
| | `-ImplicitCastExpr 0x5618732e1ee8 <col:5> 'void (*)()' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x5618732e1ec0 <col:5> 'void ()' lvalue Function 0x5618732e16d0 'foo' 'void ()'
| |-BreakStmt 0x5618732e1f28 <line:31:5>
| |-CaseStmt 0x5618732e1f50 <line:34:3, line:35:9>
| | |-IntegerLiteral 0x5618732e1f30 <line:34:8> 'int' 5
| | |-<<<NULL>>>
| | `-CallExpr 0x5618732e2020 <line:35:5, col:9> 'void'
| | `-ImplicitCastExpr 0x5618732e2008 <col:5> 'void (*)()' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x5618732e1fe0 <col:5> 'void ()' lvalue Function 0x5618732e16d0 'foo' 'void ()'
| |-BreakStmt 0x5618732e2048 <line:36:5>
在这里您可以看到CallExpr
是CaseStmt
的子级,而BreakStmt
不是。
注意:为了使示例更简单,我将std::cout << "..."
替换为foo()
。
您将必须编写一个很多的更复杂的匹配器,该匹配器可为cases
和后面的break
之间没有cases
语句的/**
* Creates an {@link AWTEventListener} that will call the given listener if
* the {@link MouseEvent} occurred inside the given component, one of its
* children or the children's children etc. (recursive).
*
* @param component
* the component the {@link MouseEvent} has to occur inside
* @param listener
* the listener to be called if that is the case
*/
public static void addRecursiveMouseListener(final Component component, final MouseListener listener) {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if(event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
if(mouseEvent.getComponent().isShowing() && component.isShowing()){
if (containsScreenLocation(component, mouseEvent.getLocationOnScreen())) {
if(event.getID() == MouseEvent.MOUSE_PRESSED) {
listener.mousePressed(mouseEvent);
}
if(event.getID() == MouseEvent.MOUSE_RELEASED) {
listener.mouseReleased(mouseEvent);
}
if(event.getID() == MouseEvent.MOUSE_ENTERED) {
listener.mouseEntered(mouseEvent);
}
if(event.getID() == MouseEvent.MOUSE_EXITED) {
listener.mouseExited(mouseEvent);
}
if(event.getID() == MouseEvent.MOUSE_CLICKED){
listener.mouseClicked(mouseEvent);
}
}
}
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
}
/**
* Checks if the given location (relative to the screen) is inside the given component
* @param component the component to check with
* @param screenLocation the location, relative to the screen
* @return true if it is inside the component, false otherwise
*/
public static boolean containsScreenLocation(Component component, Point screenLocation){
Point compLocation = component.getLocationOnScreen();
Dimension compSize = component.getSize();
int relativeX = screenLocation.x - compLocation.x;
int relativeY = screenLocation.y - compLocation.y;
return (relativeX >= 0 && relativeX < compSize.width && relativeY >= 0 && relativeY < compSize.height);
}
获取
我希望这还是有帮助的。