0

我使用 JavaCC 确实模拟了一小部分 SQL 语法,但在定义密码时遇到了问题。

我正在为一个写语法规则

CREATE USER user_name IDENTIFIED BY a_password

声明,我被卡住了。由于密码可以与任何东西匹配asdkj*!@#,或!@%^%ASDjnkj_ASDJLJK@#&。请注意,在 Oracle 中,输入不带单引号 ( ') 的密码是完全合法的。如果引号是强制性的,我可以很容易地解决这个问题,但不幸的是它们不是。

我尝试了很多方法来为这个密码定义一个令牌/语法规则,但它没有像我预期的那样工作,我尝试过的最新规则是:

TOKEN : {
< S_PASSWORD: ( < DIGIT > | < LETTER > |< S_PASSCHAR >)+ >
|  <#S_PASSCHAR : "!"|"@"|"#"|"$"|"%"|"^"|"&"|"*" > 
|  <#LETTER: ["a"-"z", "A"-"Z", "_"]>
|  <#DIGIT: ["0" - "9"]>
}

但是因为< S_PASSWORD >可以匹配任何东西,所以我之前定义的任何其他标记都将与之匹配,并且我总是会收到这样的 JavaCC 警告:

警告:“#”不能匹配为第 33515 行第 13 列的字符串文字标记。它将匹配为 < S_PASSWORD >。

我的朋友也有类似的建议,但他们也没有奏效。有人可以帮我弄这个吗?

4

1 回答 1

1

假设有一些词法方法来判断密码的开始和结束位置,您可以使用词法状态。例如,如果序列 IDENTIFIED BY 后面只有空格,然后是密码,则您创建一个状态机,以便 IDENTIFIED 从 DEFAULT 转换为 S0。在 S0 中,空格被跳过并通过 BY 转换到 S1。在 S1 中,空格被跳过,密码字符序列是 PASSWORD 令牌;PASSWORD 令牌转换回 DEFAULT。当然,这仅在 IDENTIFIED BY 只能后跟密码时才有效。同样在 S0 中,您需要能够处理所有正常的东西,因此您的大多数令牌规则都应适用于 S0 和 DEFAULT 状态,但要过渡到 DEFAULT。有关词汇状态的更多信息,请参阅常见问题解答。

如果 BY 后面只跟密码,那就更容易了,因为你不需要 S0。


编辑

以下是一些示例规则。如果关键字 BY 后面只跟密码,则只需要两种状态

TOKEN : { <BY : "BY"> : S1>
<S1> TOKEN : { <PASSWORD : ( <PASSWORDCHAR> )+ } : DEFAULT }
<DEFAULT, S1> : SKIP { " " } // Stays in the same state.

如果你可以使用 IDENTIFIED 后跟 BY 那么你需要三个状态

<DEFAULT, S0> TOKEN : { <CREATE : "CREATE"> : DEFAULT } // And similar for most token rules.
<DEFAULT, S0> TOKEN : { <IDENTIFIED : "IDENTIFIED"> : S1 }
<S0> TOKEN : { <BY : "BY"> : S1> // BYs that follow IDENTIFIED
<DEFAULT> TOKEN : { <BY : "BY"> : DEFAULT } BYs that don't follow IDENTIFIED.
<S1> TOKEN : { <PASSWORD : ( <PASSWORDCHAR> )+ } : DEFAULT }
<DEFAULT, S0, S1> : SKIP { " " } // Stays in the same state.
于 2013-04-27T18:56:39.570 回答