У меня есть проект по написанию лексера с использованием JFLEX для выдуманного языка. Это язык с простым синтаксисом, включая простые переменные, такие как строки и символы, целые числа и числа с плавающей запятой. Однако у меня проблема с персонажами. Я создал состояние, похожее на STRING, с именем CHAR, в котором используются одинарные кавычки. К сожалению, такие инициализации, как «привет», допустимы. Итак, есть ли способ создать пользовательскую функцию для подсчета количества символов и печати символьной переменной, если ее размер равен 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|\r\n
WhiteSpace = {LineTerminator} | [ \t\f]
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()); }
[^\n\r\"\\]+ { 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()); }
[^\n\r\0\'\\]+ { sb.append(yytext()); }
\\t { sb.append('\t'); }
\\n { sb.append('\n'); }
\\0 { sb.append('\0'); }
\\r { sb.append('\r'); }
\\\' { sb.append('\''); }
\\ { sb.append('\\'); }
}
/* error fallback */
[^] { throw new RuntimeException((yyline+1) + ":" + (yycolumn+1) + ": illegal character <"+ yytext()+">"); }