我正在为过滤器查询解析器编写一个antlr4语法(类似于Github问题查询)。理论上,查询应该如下:
tag:abc AND user:john
但是,我在解析像:
这样的问题时遇到了问题tag:tag
第一个标签应该表示我们按标签过滤而第二个标签只是文本。
我的语法看起来像这样:
parse
: expression? EOF
;
expression
: expression operator expression
| WHITESPACE* selector WHITESPACE*
;
selector:
SELECTOR ':' value=TEXT;
operator
: AND | OR | WHITESPACE
;
SELECTOR : TAG | USER;
AND : 'AND';
OR : 'OR';
TAG : 'tag' ;
USER : 'user' ;
WHITESPACE : (' ' | '\t') ;
TEXT_CHAR : ~[ :];
TEXT : TEXT_CHAR+;
答案 0 :(得分:0)
将TAG
和USER
分开:
selector: key=TAG COLON value=TEXT
| key=USER COLON value=TEXT
;
每当选择器规则匹配时,相应的SelectorContext#key
字段将包含实际匹配的TAG
或USER
令牌。
答案 1 :(得分:0)
您可以使用以下代码代替选择器:
<html>
<head>
<title>Space shooter</title>
<style>
* {
margin:0;
}
canvas {
background: url("http://www.ufointernationalproject.com/wp-content/uploads/2017/03/space-03.jpg");
}
</style>
</head>
<body>
<canvas id="canvas" width="1350" height="630"></canvas>
<script>
var ctx = document.getElementById("canvas").getContext("2d"),
lastShot = Date.now(),
fireRate = 120,
bullets = [],
enemies = [],
enemySpeed = 1.5,
bulletSpeed = 20,
player = {
x: 600,
y: 250,
leftPressed: false,
rightPressed: false,
upPressed: false,
downPressed: false,
spacePressed: false,
speed: 5
};
var playerImage = new Image();
playerImage.src = "https://3.bp.blogspot.com/-jGC08Dy0zg8/U405cNq1-MI/AAAAAAAABqU/38d5rmV1S8Y/s1600/redfighter0006.png";
var enemyImage = new Image();
enemyImage.src = "https://a.fsdn.com/con/app/proj/partartspace/screenshots/Spaceship14.png/1";
function spawnEnemes() {
enemies.push({
x:Math.floor(Math.random() * 1250) + 1,
y:-100
})
}
setInterval(spawnEnemes, 500);
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(playerImage, player.x,player.y, 100, 100);
if (player.leftPressed) {
player.x -= player.speed;
}
if (player.rightPressed) {
player.x += player.speed;
}
if (player.upPressed) {
player.y -= player.speed;
}
if (player.downPressed) {
player.y += player.speed;
}
if (player.spacePressed && Date.now() - lastShot > fireRate) {
bullets.push({
x: player.x+50,
y: player.y
});
lastShot = Date.now();
}
bullets.forEach(function(bullet){
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, 5, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
bullet.y -= bulletSpeed;
});
enemies.forEach(function(enemy){
ctx.drawImage(enemyImage, enemy.x, enemy.y, 100,100);
enemy.y += enemySpeed;
});
for (var enemy = 0; enemy < enemies.length; enemy ++){
if(player.x < enemies[enemy].x + 80 &&
player.x + 80 > enemies[enemy].x &&
player.y < enemies[enemy].y + 65 &&
player.y + 100 > enemies[enemy].y)
{
document.location.reload();
}
for (var bullet = 0; bullet < bullets.length; bullet ++) {
if(bullets[bullet].y < enemies[enemy].y + 70 &&
bullets[bullet].y > enemies[enemy].y &&
bullets[bullet].x < enemies[enemy].x + 100 &&
bullets[bullet].x > enemies[enemy].x)
{
bullets.splice(bullet, 1);
enemies.splice(enemy, 1);
}
}
}
requestAnimationFrame(draw);
}
draw();
document.body.addEventListener("keydown", function(e) {
if (e.keyCode === 37) {
player.leftPressed = true;
}
else if (e.keyCode === 39) {
player.rightPressed = true;
}
else if (e.keyCode === 38) {
player.upPressed = true;
}
else if (e.keyCode === 40) {
player.downPressed = true;
}
else if (e.keyCode === 32) {
player.spacePressed = true;
}
});
document.body.addEventListener("keyup", function(e) {
if (e.keyCode === 37) {
player.leftPressed = false;
}
else if (e.keyCode === 39) {
player.rightPressed = false;
}
else if (e.keyCode === 38) {
player.upPressed = false;
}
else if (e.keyCode === 40) {
player.downPressed = false;
}
else if (e.keyCode === 32) {
player.spacePressed = false;
}
});
</script>
</body>
</html>