我有一个项目,使用 JFLEX 为一种虚构的语言编写一个词法分析器。它是一种语法简单的语言,包括字符串和字符整数和浮点数等简单变量。但是我对字符有问题。我创建了一个类似于 STRING 的状态,名为 CHAR,它使用单引号。不幸的是,像"hello"这样的初始化是可以接受的。那么有没有办法创建一个自定义函数来计算字符数并在字符变量大小等于 1 时打印字符变量,否则会引发异常?我搜索了很多,但找不到答案。这是我到目前为止的代码:
import static java.lang.System.out;
%%
%class Lexer
%unicode
%public
%final
%integer
%line
%column
%{
// user custom code
StringBuffer sb = new StringBuffer();
%}
LineTerminator = r|n|rn
WhiteSpace = {LineTerminator} | [ tf]
Comment = "/*" [^*] ~"*/" | "/*" "*"+ "/"
Identifier = [:jletter:] [:jletterdigit:]*
IntegerLiteral = 0 | [1-9][0-9]*
Exponent= [eE][+-]?[0-9]+
Float1= [0-9]+ . [0-9]+ {Exponent}?
Float2= . [0-9]+ {Exponent}?
Float3= [0-9]+ . {Exponent}?
Float4= [0-9]+ {Exponent}
FloatLiteral = {Float1} | {Float2} | {Float3} | {Float4}
%state STRING, CHAR
%%
/* reserved keywords */
<YYINITIAL>"float" { out.println("FLOAT"); }
<YYINITIAL>"int" { out.println("INTEGER"); }
<YYINITIAL>"char" { out.println("CHAR"); }
<YYINITIAL>"break" { out.println("BREAK"); }
<YYINITIAL>"print" { out.println("PRINT"); }
<YYINITIAL>"while" { out.println("WHILE"); }
<YYINITIAL>"if" { out.println("IF"); }
<YYINITIAL>"else" { out.println("ELSE"); }
<YYINITIAL>"void" { out.println("VOID"); }
<YYINITIAL>"return" { out.println("RETURN"); }
<YYINITIAL>"continue" { out.println("CONTINUE");}
<YYINITIAL>"new" { out.println("NEW"); }
<YYINITIAL>"delete" { out.println("DELETE"); }
<YYINITIAL>"(" { out.println( "LEFT ARENTHESIS" ); }
<YYINITIAL>")" { out.println( "RIGHT PARENTHESIS" ); }
<YYINITIAL>"{" { out.println( "LEFT CURLY BRACKET" ); }
<YYINITIAL>"}" { out.println( "RIGHT CURLY BRACKET" ); }
<YYINITIAL>"[" { out.println( "LEFT SQ" ); }
<YYINITIAL>"]" { out.println( "RIGHT SQ" ); }
<YYINITIAL>";" { out.println( "SEMICOLON" ); }
<YYINITIAL>"," { out.println( "COMMA" ); }
<YYINITIAL> {
/* identifiers */
{Identifier} { out.println("id:" + yytext()); }
/* literals */
{IntegerLiteral} { out.println("integer:" + yytext()); }
{FloatLiteral} { out.println("float:" + yytext()); }
" { sb.setLength(0); yybegin(STRING); }
' { sb.setLength(0); yybegin(CHAR); }
/* operators */
"=" { out.println("ASSIGN"); }
"+" { out.println("PLUS"); }
";" { out.println("SEMICOLON"); }
">" { out.println("GREATER THAN"); }
"<" { out.println("LESS THAN"); }
"!=" { out.println("NOT EQUAL TO"); }
"<=" { out.println("LESS OR EQUAL THAN"); }
">=" { out.println("GREATER OR EQUAL THAN"); }
"−" { out.println("SUBTRACTION"); }
"*" { out.println("MULTIPLICATION"); }
"/" { out.println("DIVISION"); }
"%" { out.println("PERCENT"); }
"==" { out.println("EQUALS"); }
"&&" { out.println("AND"); }
"||" { out.println("OR"); }
/* comments */
{Comment} { /* ignore */ }
/* whitespace */
{WhiteSpace} { /* ignore */ }
}
<STRING> {
" { yybegin(YYINITIAL);
out.println("string:" + sb.toString()); }
[^nr"\]+ { sb.append(yytext()); }
\t { sb.append('t'); }
\n { sb.append('n'); }
\r { sb.append('r'); }
\" { sb.append('"'); }
\ { sb.append('\'); }
}
<CHAR> {
' { yybegin(YYINITIAL);
out.println("char:" + sb.toString()); }
[^nr '\]+ { sb.append(yytext()); }
\t { sb.append('t'); }
\n { sb.append('n'); }
\0 { sb.append(' '); }
\r { sb.append('r'); }
\' { sb.append('''); }
\ { sb.append('\'); }
}
/* error fallback */
[^] { throw new RuntimeException((yyline+1) + ":" + (yycolumn+1) + ": illegal character <"+ yytext()+">"); }
经过五月的尝试,我找到了一个对我来说可以接受的解决方案,我只是在 CHAR 状态中替换了这段代码:
' { yybegin(YYINITIAL);
out.println("char:" + sb.toString()); }
与以下内容:
' {
if(sb.length() > 1 ){
yybegin(YYINITIAL);
throw new RuntimeException("you can not instatiate a char variable with more than one charactersn");
}else{
yybegin(YYINITIAL);
out.println("char:" + sb.toString());
}
希望这能帮助有类似问题的人