Compiler construction 在JavaCC中,如何降低正则表达式的优先级?
让我用一个具体的例子来澄清我的问题: 首先,我有一个令牌:Compiler construction 在JavaCC中,如何降低正则表达式的优先级?,compiler-construction,javacc,Compiler Construction,Javacc,让我用一个具体的例子来澄清我的问题: 首先,我有一个令牌: <T_SELECT:"SELECT"> 我的问题是: JavaCC不再使用SELECT然后使用TABLE1,而是将SELECT TABLE1作为 显然,我希望它会非常消耗SELECT,因为我已经定义了一个名为 我该怎么做才能让JavaCC使用我定义的确切字符串而不是正则表达式呢?这几乎肯定不是您想要做的,因为它会将selection转换为selection ~[”,“]将匹配除逗号以外的任何字符,包括空格和换行符。这也不可
<T_SELECT:"SELECT">
我的问题是:
JavaCC不再使用SELECT
然后使用TABLE1
,而是将SELECT TABLE1
作为
显然,我希望它会非常消耗SELECT
,因为我已经定义了一个名为
我该怎么做才能让JavaCC使用我定义的确切字符串而不是正则表达式呢?这几乎肯定不是您想要做的,因为它会将
selection
转换为select
ion
~[”,“]
将匹配除逗号以外的任何字符,包括空格和换行符。这也不可能是正确的,因为表名不以(或包含)空格字符开头
您需要匹配并忽略空白,并将名称限制为合法的名称字符。这几乎肯定不是您想要做的,因为它会将
选择
变成选择
离子
~[”,“]
将匹配除逗号以外的任何字符,包括空格和换行符。这也不可能是正确的,因为表名不以(或包含)空格字符开头
您需要匹配并忽略空白,并将名称限制为合法的名称字符。我假设您只有这些词汇规则
TOKEN { <T_SELECT:"SELECT"> }
TOKEN { <T_TABLE_NAME:~[","]> }
TOKEN { <T_COMMA: "," > }
该序列将按如下方式进行词法分析
State Token Produced
------------------------------
DEFAULT T_SELECT("SELECT")
S_TABLE_NAME T_TABLE_NAME( " ABC" )
S_TABLE_NAME T_COMMA( "," )
S_TABLE_NAME T_TABLE_NAME( " DEF" )
S_TABLE_NAME T_NEWLINE( "\n" )
DEFAULT EOF.
- 首先找到一个T_SELECT
- 然后是7个表名标记
- 然后是一个EOF令牌
void select() : {} {
<T_SELECT>
<T_TABLE_NAME>
(<T_COMMA> <T_TABLE_NAME>)*
} ,
void select() : {} {
<T_SELECT>
<T_TABLE_NAME>
(<T_COMMA> <T_TABLE_NAME>)*
<EOF> // I added an <EOF>
} ,
现在会发生什么?再次假设输入字符串是
"SELECT TABLE1" ,
有一个长度为6的前缀与规则匹配
<T_SELECT:"SELECT">
没有办法关闭最大数量规则。你赢不了这场比赛。你必须作弊
作弊的方法就是淘汰对手。将
T_TABLE_NAME
规则移动到不同的词法状态
您希望在lexer看到SELECT关键字后切换状态
写下你的lexer规则如下:
TOKEN : { <T_SELECT: "SELECT"> : S_TABLE_NAME }
<S_TABLE_NAME> TOKEN :
{ <T_TABLE_NAME:(~[",","\n","\r"])*> : S_TABLE_NAME
| <T_COMMA: "," } : S_TABLE_NAME
| <T_NEWLINE: ("\n" | "\n\r" | "\r") : DEFAULT }
它将被简化如下
State Token Produced
------------------------------
DEFAULT T_SELECT("SELECT")
S_TABLE_NAME T_TABLE_NAME( " ABC" )
S_TABLE_NAME T_COMMA( "," )
S_TABLE_NAME T_TABLE_NAME( " DEF" )
S_TABLE_NAME T_NEWLINE( "\n" )
DEFAULT EOF.
它将无错误地解析。我假设您仅有的词汇规则是
TOKEN { <T_SELECT:"SELECT"> }
TOKEN { <T_TABLE_NAME:~[","]> }
TOKEN { <T_COMMA: "," > }
该序列将按如下方式进行词法分析
State Token Produced
------------------------------
DEFAULT T_SELECT("SELECT")
S_TABLE_NAME T_TABLE_NAME( " ABC" )
S_TABLE_NAME T_COMMA( "," )
S_TABLE_NAME T_TABLE_NAME( " DEF" )
S_TABLE_NAME T_NEWLINE( "\n" )
DEFAULT EOF.
- 首先找到一个T_SELECT
- 然后是7个表名标记
- 然后是一个EOF令牌
void select() : {} {
<T_SELECT>
<T_TABLE_NAME>
(<T_COMMA> <T_TABLE_NAME>)*
} ,
void select() : {} {
<T_SELECT>
<T_TABLE_NAME>
(<T_COMMA> <T_TABLE_NAME>)*
<EOF> // I added an <EOF>
} ,
现在会发生什么?再次假设输入字符串是
"SELECT TABLE1" ,
有一个长度为6的前缀与规则匹配
<T_SELECT:"SELECT">
没有办法关闭最大数量规则。你赢不了这场比赛。你必须作弊
作弊的方法就是淘汰对手。将
T_TABLE_NAME
规则移动到不同的词法状态
您希望在lexer看到SELECT关键字后切换状态
写下你的lexer规则如下:
TOKEN : { <T_SELECT: "SELECT"> : S_TABLE_NAME }
<S_TABLE_NAME> TOKEN :
{ <T_TABLE_NAME:(~[",","\n","\r"])*> : S_TABLE_NAME
| <T_COMMA: "," } : S_TABLE_NAME
| <T_NEWLINE: ("\n" | "\n\r" | "\r") : DEFAULT }
它将被简化如下
State Token Produced
------------------------------
DEFAULT T_SELECT("SELECT")
S_TABLE_NAME T_TABLE_NAME( " ABC" )
S_TABLE_NAME T_COMMA( "," )
S_TABLE_NAME T_TABLE_NAME( " DEF" )
S_TABLE_NAME T_NEWLINE( "\n" )
DEFAULT EOF.
它将无错误地进行分析。您的语法中是否应该允许使用带未转义/未引号空格的表名?是的,在我们的语法中,不带引号的空格是允许的。您是否希望表名只能有一个字符长?在示例中,“TABLE1”是7个字符长。但是正则表达式
~[”,“]
将只匹配一个字符长的字符串。有关详细信息,请参阅我的答案。您的语法中是否允许使用带有未加引号/未加引号的空格的表名?是的,在我们的语法中,允许使用未加引号的空格。是否希望表名只能有一个字符长?在示例中,“TABLE1”是7个字符长。但是正则表达式~[”,“]
将只匹配一个字符长的字符串。有关详细信息,请参阅我的答案。在我们的sytax中,允许在表名中包含空格。我们已经为自己的系统定义了一种查询语言。@qinqjinlyc即使一个表名由几个单词组成,在select
和my table
之间的空格似乎不太可能是名称的一部分。(如果有人在代码之后放置了两个空格,选择?)通常,允许多单词名称的语言将它们看作是单词列表,而不是空格的字串,因此<代码>我的表和<代码>我的表< /代码>是相同的名称。允许关键字进入下一个符号(我的选择
示例)更不常见。你是说select
,i
,o
,n
,n
?@theodore:用逗号来分隔标记就是select
,ion
。虽然我假设OP忘记了一个重复运算符,但在我们的sytax中,它允许在表名中包含空格。我们已经为自己的系统定义了一种查询语言。@qinqjinlyc即使一个表名由几个单词组成,在select
和my table
之间的空格似乎不太可能是名称的一部分。(如果有人在代码之后放置了两个空格,选择?)通常,允许多单词名称的语言将它们看作是单词列表,而不是空格的字串,因此<代码>我的表和<代码>我的表< /代码>是相同的名称。允许关键字进入下一个符号(我的选择
示例)更不常见。你是说select
,i
,o
,n
,n
?@theodore:用逗号来分隔标记就是select
,ion
。虽然我认为OP确实忘记了一个重复操作符。嗨@Norvell,我试过你的建议,它可以解析“selectabc,def”。然而,在我们的语法中,表后面可能有“from”,比如“selectabc,def from”。然后,“from”将被视为“def”的一部分。然而,“from”是关键词,你原来的帖子说“表名是任意长度的字符串
State Token Produced
------------------------------
DEFAULT T_SELECT("SELECT")
S_TABLE_NAME T_TABLE_NAME( " ABC" )
S_TABLE_NAME T_COMMA( "," )
S_TABLE_NAME T_TABLE_NAME( " DEF" )
S_TABLE_NAME T_NEWLINE( "\n" )
DEFAULT EOF.