Мо ба таваҷҷуҳи шумо тарҷумаи дастури мухтасарро оид ба ибораҳои муқаррарӣ дар Java пешкаш мекунем, ки аз ҷониби Ҷефф Фризен барои вебсайти javaworld навишта шудааст. Барои осонии хондан, мо мақоларо ба чанд қисм тақсим кардем. Ин қисми ниҳоӣ аст. Ифодаҳои муқаррарӣ дар Java, Қисми 1 Ифодаҳои муқаррарӣ дар Java, Қисми 2 Ифодаҳои муқаррарӣ дар Java, Қисми 3 Ифодаҳои муқаррарӣ дар Java, Қисми 4
Ибораҳои муқаррарӣ нисбат ба таҳлилгарони лексикии давлатӣ, ки бояд дастӣ навишта шаванд ва умуман дубора истифода намешаванд, хеле самараноктаранд. Намунаи таҳлилгари лексикии ба ифодаи муқаррарӣ асосёфта JLex аст , генератори лексикии забони Java мебошад, ки ифодаҳои муқаррариро барои муайян кардани қоидаҳо барои тақсим кардани ҷараёни додаҳои воридотӣ ба аломатҳо истифода мебарад. Мисоли дигар Лексан аст.
Истифодаи ибораҳои муқаррарӣ барои таҳлor лексикӣ
Истифодаи боз ҳам муфидтари ифодаҳои муқаррарӣ китобхонаи codeи такрористеъмолшаванда барои анҷом додани таҳлor лексикӣ, ҷузъи асосии ҳама гуна компилятор ё ассемблер мебошад. Дар ин ҳолат ҷараёни вуруди аломатҳо ба ҷараёни баромади аломатҳо - номҳои пайдарпайии аломатҳое, ки маънои умумӣ доранд, гурӯҳбандӣ карда мешаванд. Масалан, дар ҷараёни вуруд ба пайдарпайии аломатҳоиc
, o
, , u
, , n
, , , t
, , , , e
, r
, , , , , , , , пешпо хӯрда, таҳлилгари лексикӣ метавонад токен ID
(идентификатор) барорад. Пайдарҳамии аломатҳои ба аломат мувофиқро лексема меноманд.
Бештар дар бораи маркерҳо ва лексемаҳо |
---|
Токенҳо ба монанди ID метавонанд пайдарпайии бисёр аломатҳоро мувофиқат кунанд. Дар мавриди ин гуна аломатҳо, аломати воқеии мувофиқи токен низ ба компилятор, ассемблер ё утorтаи дигаре лозим аст, ки таҳлor лексикиро талаб мекунад. Барои нишонаҳо, ки як пайдарпаии мушаххаси аломатҳоро намояндагӣ мекунанд, ба монанди аломати PLUS танҳо ба аломат мувофиқ + , аломати воқеӣ талаб карда намешавад, зеро он метавонад бо нишона [бегона] муайян карда шавад. |
Бо Лексан шинос шудан
Lexan китобхонаи Java-и такрорӣ барои таҳлor лексикӣ мебошад. Он ба codeи силсилаи постҳои блоги Навиштани таҳлилгар дар Java дар вебсайти Cogito Learning асос ёфтааст . Китобхона аз синфҳои зерин иборат аст, ки дар бастаиca.javajeff.lexan
рамзи зеркашишавандаи ин мақола дохил карда шудаанд:
Lexan
: таҳлилгари лексикӣ;LexException
: истисно партофта мешавад, агар синтаксиси нодуруст ҳангоми таҳлor лексикӣ ошкор шавад;Token
: ном бо атрибути ифодаи муқаррарӣ;TokLex
: ҷуфти нишона / нишона.
LexanException
: истисно партофташуда дар созандаи синфLexan;
Lexan(java.lang.Class tokensClass)
анализатори нави лексикиро месозад. Он як далелро дар шакли an objectи синфӣ, java.lang.Class
ки ба навъи синфи доимии мувофиқ аст , талаб мекунад static Token
. Бо истифода аз Reflection API, созанда ҳамаи константаҳоро Token
ба массиви арзишҳо мехонад Token[]
. Агар Token
доимӣ вуҷуд надошта бошад, истисно партофта мешавад LexanException
. Синф Lexan
инчунин ду усули зеринро пешниҳод мекунад:
- Усул рӯйхати ин лексерро бармегардонад;
List
getTokLexes() Token
Метод void lex(String str)
Таҳлor лексикии сатри вурудро [бо натиҷаи ҷойгиршуда] дар рӯйхати арзишҳои навъиTokLex
. Агар аломате дучор шавад, ки ба ягон намунаи массив мувофиқат накунадToken[]
, истисно партофта мешавадLexException
.
LexanException
усул надорад; он усули меросиро барои баргардонидани паёми истисно истифода мебарад getMessage()
. Баръакси ин, синф LexException
усулҳои зеринро пешниҳод мекунад:
- Усул
int getBadCharIndex()
мавқеъи аломатеро бармегардонад, ки ба ягон намунаи нишонгузор мувофиқат намекунад. - Усул
String getText()
матнеро, ки ҳангоми тавлиди истисно таҳлил шуда буд, бармегардонад.
Token
усули toString()
баргардонидани номи маркерро бекор мекунад. Он инчунин усулеро пешниҳод мекунад String getPattern()
, ки атрибути ифодаи муқаррарии нишонаро бармегардонад. Синф TokLex
усулеро пешниҳод мекунад Token getToken()
, ки аломати худро бармегардонад. Он инчунин усулеро пешниҳод мекунад String getLexeme()
, ки нишонаи худро бармегардонад.
Намоиш аз китобхонаи Лексан
Барои нишон додани он, ки китобхона чӣ гуна кор мекунад,Lexan
ман ариза навиштам LexanDemo
. Он аз синфҳои LexanDemo
, BinTokens
, MathTokens
ва NoTokens
. Рамзи сарчашмаи барнома LexanDemo
дар Рӯйхати 2 нишон дода шудааст. Рӯйхати 2. Намоиши китобхонаи Lexan дар амал
import ca.javajeff.lexan.Lexan;
import ca.javajeff.lexan.LexanException;
import ca.javajeff.lexan.LexException;
import ca.javajeff.lexan.TokLex;
public final class LexanDemo
{
public static void main(String[] args)
{
lex(MathTokens.class, " sin(x) * (1 + var_12) ");
lex(BinTokens.class, " 1 0 1 0 1");
lex(BinTokens.class, "110");
lex(BinTokens.class, "1 20");
lex(NoTokens.class, "");
}
private static void lex(Class tokensClass, String text)
{
try
{
Lexan lexan = new Lexan(tokensClass);
lexan.lex(text);
for (TokLex tokLex: lexan.getTokLexes())
System.out.printf("%s: %s%n", tokLex.getToken(),
tokLex.getLexeme());
}
catch (LexanException le)
{
System.err.println(le.getMessage());
}
catch (LexException le)
{
System.err.println(le.getText());
for (int i = 0; i < le.getBadCharIndex(); i++)
System.err.print("-");
System.err.println("^");
System.err.println(le.getMessage());
}
System.out.println();
}
}
Усули main()
дар Рӯйхати 2 як утorтаро lex()
барои нишон додани таҳлor лексикӣ бо истифода аз Lexan даъват мекунад. Ҳар як занг ба ин усул ба синфи нишонаҳо дар an object Class
ва сатр барои таҳлил дода мешавад. Усули lex()
аввал an objectи синфро Lexan
тавассути интиқол додани an object Class
ба созандаи синф эҷод мекунад Lexan
. Ва он гоҳ он усули lex()
синфро Lexan
дар ин сатр даъват мекунад. Агар таҳлor лексикӣ муваффақ бошад, усули синф барои баргардонидани рӯйхати an objectҳо TokLex
даъват карда мешавад . Барои ҳар яке аз ин an objectҳо усули синфии он барои баргардонидани нишона ва усули синфи он барои баргардонидани нишон даъват карда мешавад. Ҳарду арзишҳо ба баромади стандартӣ чоп карда мешаванд. Агар таҳлor лексикӣ ноком шавад, яке аз истисноҳо ё партофта мешавад ва мувофиқи он кор карда мешавад . Барои мухтасар, биёед танҳо синферо, ки ин барномаро ташкил медиҳад, баррасӣ кунем . Рӯйхати 3 рамзи сарчашмаи онро нишон медиҳад. Листинг 3. Тавсифи маҷмӯи аломатҳо барои забони хурди математикӣgetTokLexes()
Lexan
getToken()
TokLex
getLexeme()
LexanException
LexException
MathTokens
import ca.javajeff.lexan.Token;
public final class MathTokens
{
public final static Token FUNC = new Token("FUNC", "sin|cos|exp|ln|sqrt");
public final static Token LPAREN = new Token("LPAREN", "\\(");
public final static Token RPAREN = new Token("RPAREN", "\\)");
public final static Token PLUSMIN = new Token("PLUSMIN", "[+-]");
public final static Token TIMESDIV = new Token("TIMESDIV", "[*/]");
public final static Token CARET = new Token("CARET", "\\^");
public final static Token INTEGER = new Token("INTEGER", "[0-9]+");
public final static Token ID = new Token("ID", "[a-zA-Z][a-zA-Z0-9_]*");
}
Рӯйхати 3 нишон медиҳад, ки синф MathTokens
пайдарпайии доимии навъи Token
. Ба ҳар яки онҳо арзиши an object дода мешавад Token
. Созандаи ин an object сатрро мегирад, ки номи маркер аст ва дар якҷоягӣ бо ифодаи муқаррарӣ, ки ҳамаи сатрҳои аломатҳои марбут ба ин маркерро тавсиф мекунад. Барои возењ шудан, матлуб аст, ки номи сатри маркер бо номи доимї якхела бошад, аммо ин шарт нест. Мавқеи доимӣ Token
дар рӯйхати маркерҳо муҳим аст. Собитҳое, ки дар рӯйхат болотар ҷойгир шудаанд, Token
нисбат ба онҳое, ки дар поён ҷойгиранд, бартарӣ доранд. Масалан, ҳангоми дучор шудан , Лексан ба ҷои , sin
аломатро интихоб мекунад . Агар маркер пеш аз маркер мебуд , он интихоб мешуд. FUNC
ID
ID
FUNC
Тартиб додан ва иҷро кардани барномаи LexanDemo
Рамзи зеркашишавандаи ин мақола бойгониеро дар бар мегирадlexan.zip
, ки дорои ҳамаи файлҳои тақсимоти Lexan мебошад. Ин бойгониро кушоед ва ба зеркаталоги demos
директорияи реша равед lexan
. Агар шумо Windows-ро истифода баред, фармони зеринро иҷро кунед, то файлҳои рамзи ибтидоии барномаро тартиб диҳед:
javac -cp ..\library\lexan.jar *.java
Агар компиляция бомуваффақият бошад, фармони зеринро иҷро кунед, то барномаи намоиширо иҷро кунед:
java -cp ..\library\lexan.jar;. LexanDemo
Шумо бояд натиҷаҳои зеринро бинед:
FUNC: sin
LPAREN: (
ID: x
RPAREN: )
TIMESDIV: *
LPAREN: (
INTEGER: 1
PLUSMIN: +
ID: var_12
RPAREN: )
ONE: 1
ZERO: 0
ONE: 1
ZERO: 0
ONE: 1
ONE: 1
ONE: 1
ZERO: 0
1 20
--^
Неожиданный символ во входном тексте: 20
Паём Неожиданный символ во входном тексте: 20
дар натиҷаи партофта шудани истисно LexanException
аз сабаби он, ки синф як доимиро бо арзиш ҳамчун ифодаи муқаррарӣ BinTokens
эълон намекунад . Дар хотир доред, ки коркардкунандаи истисно мавқеи аломати номуносибро, ки аз таҳлor лексикии матн гирифта шудааст, мебарорад. Паёми гумшудаи нишонаҳо натиҷаи партофта шудани истисно аст, зеро дар синф ягон доимӣ эълон нашудааст . Token
2
LexException
NoTokens
Token
Дар паси парда
Lexan
синфи Lexan-ро ҳамчун муҳаррики худ истифода мебарад. Татбиқи ин синфро дар Рӯйхати 4 дида бароед ва саҳми ибораҳои муқаррариро дар истифодаи дубораи муҳаррик қайд кунед. Листинг 4. Сохтани меъмории анализатори лексики дар асоси иборахои мукаррари
package ca.javajeff.lexan;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
/**
* Лексический анализатор. Этот класс можно использовать для
* преобразования входного потока символов в выходной поток маркеров.
*
* @Author Джефф Фризен
*/
public final class Lexan
{
private List tokLexes;
private Token[] values;
/**
* Инициализируем лексический анализатор набором an objectов Token.
*
* @параметры tokensClass – an object Class класса, содержащего
* набор an objectов Token
*
* @генерирует исключение LexanException в случае невозможности
* формирования an object Lexan, возможно, из-за отсутствия an objectов
* Token в классе
*/
public Lexan(Class tokensClass) throws LexanException
{
try
{
tokLexes = new ArrayList<>();
List _values = new ArrayList<>();
Field[] fields = tokensClass.getDeclaredFields();
for (Field field: fields)
if (field.getType().getName().equals("ca.javajeff.lexan.Token"))
_values.add((Token) field.get(null));
values = _values.toArray(new Token[0]);
if (values.length == 0)
throw new LexanException("маркеры отсутствуют");
}
catch (IllegalAccessException iae)
{
throw new LexanException(iae.getMessage());
}
/**
* Получаем список TokLex'ов этого лексического анализатора.
*
* @возвращает список TokLex'ов
*/
public List getTokLexes()
{
return tokLexes;
}
/** * Выполняет лексический анализ входной строки [с помещением * результата] в список TokLex'ов. * * @параметры str – строка, подвергаемая лексическому анализу * * @генерирует исключение LexException: во входных данных обнаружен * неожиданный символ */
public void lex(String str) throws LexException
{
String s = new String(str).trim(); // удалить ведущие пробелы
int index = (str.length() - s.length());
tokLexes.clear();
while (!s.equals(""))
{
boolean match = false;
for (int i = 0; i < values.length; i++)
{
Token token = values[i];
Matcher m = token.getPattern().matcher(s);
if (m.find())
{
match = true;
tokLexes.add(new TokLex(token, m.group().trim()));
String t = s;
s = m.replaceFirst("").trim(); // удалить ведущие пробелы
index += (t.length() - s.length());
break;
}
}
if (!match)
throw new LexException("Неожиданный символ во входном тексте: "
+ s, str, index);
}
}
}
Рамзи усул lex()
ба codeе асос ёфтааст, ки дар пости блоги "Навиштани таҳлилгар дар Java: Генератори аломат" дар вебсайти Cogito Learning оварда шудааст. Барои гирифтани маълумоти бештар дар бораи он, ки Lexan Regex API-ро барои тартиб додани code истифода мебарад, ин мақоларо хонед.
Хулоса
Ифодаҳои муқаррарӣ як воситаи муфид мебошанд, ки метавонанд барои ҳар як таҳиякунанда муфид бошанд. API-и Regex аз забони барномасозии Java истифодаи онҳоро дар барномаҳо ва китобхонаҳо осон мекунад. Акнун, ки шумо аллакай фаҳмиши асосии ифодаҳои муқаррарӣ ва ин API-ро доред, ба ҳуҷҷатҳои SDK нигаред,java.util.regex
то дар бораи ифодаҳои муқаррарӣ ва усулҳои иловагии Regex API маълумоти бештар гиред.
GO TO FULL VERSION