我正在使用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 >
可以匹配ANYTHING,我之前定义的任何其他令牌都将与之匹配,并且我总是得到这样的JavaCC警告:
警告:“#”无法在第33515行第13列与字符串文字标记匹配。它将匹配为&lt; S_PASSWORD&gt;。
我的朋友也有类似的建议,但他们也没有用。 有人可以帮我这个吗?
答案 0 :(得分: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.