JavaRush /Java blogi /Random-UZ /Java tilidagi oddiy iboralar, 5-qism

Java tilidagi oddiy iboralar, 5-qism

Guruhda nashr etilgan
Sizning e'tiboringizga Jeff Friesen tomonidan javaworld veb-sayti uchun yozilgan Java tilidagi muntazam iboralar bo'yicha qisqacha qo'llanmaning tarjimasini taqdim etamiz. O'qish qulayligi uchun biz maqolani bir necha qismga ajratdik. Bu qism oxirgi qismdir. Java tilidagi oddiy iboralar, 5-1-qismJava tilidagi oddiy ifodalar, 1-qism Java tilidagi oddiy iboralar, 2-qism Java tilidagi oddiy iboralar, 3-qism Java tilidagi oddiy ifodalar, 4-qism

Leksik tahlil uchun muntazam iboralardan foydalanish

Muntazam iboralarning yanada foydali qo'llanilishi har qanday kompilyator yoki assemblerning asosiy komponenti bo'lgan leksik tahlilni amalga oshirish uchun qayta foydalanish mumkin bo'lgan kodlar kutubxonasidir. Bunday holda, belgilarning kirish oqimi tokenlarning chiqish oqimiga guruhlanadi - umumiy ma'noga ega bo'lgan belgilar ketma-ketligi nomlari. Masalan, kirish oqimida ,,,,,,,, belgilar ketma-ketligiga duch kelgan holda, leksik analizator token c( identifikator o) chiqarishi mumkin . Tokenga mos keladigan belgilar ketma-ketligi leksema deyiladi. unterID
Belgilar va leksemalar haqida batafsil
ID kabi tokenlar ko'plab belgilar ketma-ketligiga mos kelishi mumkin. Bunday tokenlarda tokenga mos keladigan haqiqiy token kompilyator, assembler yoki leksik tahlilni talab qiluvchi boshqa yordamchi dasturga ham kerak bo‘ladi. Bitta belgi ketma-ketligini ifodalovchi tokenlar uchun, masalan, PLUSfaqat belgiga mos keladigan token +, haqiqiy token talab qilinmaydi, chunki uni tokendan aniqlash mumkin.
Muntazam iboralar qo'lda yozilishi kerak bo'lgan va odatda qayta ishlatib bo'lmaydigan holatga asoslangan leksik analizatorlarga qaraganda ancha samaralidir. Muntazam ifodalarga asoslangan leksik analizatorga misol JLex , Java tili uchun leksik generator bo'lib, u kirish ma'lumotlar oqimini tokenlarga ajratish qoidalarini aniqlash uchun muntazam iboralardan foydalanadi. Yana bir misol Lexan.

Lexan bilan tanishish

Lexan - bu leksik tahlil uchun qayta foydalanish mumkin bo'lgan Java kutubxonasi. U Cogito Learning veb- saytidagi Java-da Parser yozish blog postlari seriyasidagi kodga asoslangan . Kutubxona ushbu maqola uchun yuklab olinadigan kodga kiritilgan paketdagi quyidagi sinflardan iborat :ca.javajeff.lexan
  • Lexan: leksik analizator;
  • LexanException: sinf konstruktorida chiqarilgan istisnoLexan;
  • LexException: leksik tahlil paytida noto'g'ri sintaksis aniqlansa, istisno tashlanadi;
  • Token: muntazam ifoda atributiga ega nom;
  • TokLex: token/token juftligi.
Konstruktor Lexan(java.lang.Class tokensClass)yangi leksik analizator yaratadi. java.lang.ClassTuri doimiy sinfga mos keladigan sinf ob'ekti ko'rinishidagi bitta argumentni talab qiladi static Token. Reflection API-dan foydalanib, konstruktor barcha konstantalarni Tokenqiymatlar qatoriga o'qiydi Token[]. Agar Tokendoimiylar bo'lmasa, istisno chiqariladi LexanException. Java tilidagi oddiy iboralar, 5-2-qismSinf Lexanshuningdek quyidagi ikkita usulni taqdim etadi:
  • Usul ushbu lekserning ro'yxatini qaytaradi ;List getTokLexes() Token
  • Метод void lex(String str)turdagi qiymatlar ro'yxatiga [natija joylashtirilgan] kirish qatorining leksik tahlilini amalga oshiradi TokLex. Agar massiv naqshlaridan birortasiga mos kelmaydigan belgi topilsa Token[], istisno tashlanadi LexException.
Sinfda LexanExceptionusullar yo'q; u istisno xabarini qaytarish uchun meros qilib olingan usuldan foydalanadi getMessage(). Bundan farqli o'laroq, sinf LexExceptionquyidagi usullarni taqdim etadi:
  • Usul int getBadCharIndex()marker naqshlarining birortasiga mos kelmaydigan belgi o'rnini qaytaradi.
  • Usul String getText()istisno yaratilganda tahlil qilingan matnni qaytaradi.
Sinf marker nomini qaytarish Tokenusulini bekor qiladi . Shuningdek, u tokenning muntazam ifoda atributini qaytaradigan toString()usulni taqdim etadi . String getPattern()Sinf o'z tokenini qaytaradigan TokLexusulni taqdim etadi . Shuningdek, u o'z tokenini qaytaradigan Token getToken()usulni taqdim etadi .String getLexeme()

Lexan kutubxonasi namoyishi

Kutubxona qanday ishlashini ko'rsatish uchun Lexanmen ariza yozdim LexanDemo. U LexanDemo, BinTokensva sinflaridan iborat . Ilovaning manba kodi 2-listingda ko'rsatilgan. Listing 2. Lexan kutubxonasining amaldagi namoyishiMathTokensNoTokensLexanDemo
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()Listing 2dagi usul lex()Lexan yordamida leksik tahlilni namoyish qilish uchun yordamchi dasturni chaqiradi. Ushbu usulga har bir qo'ng'iroq ob'ektdagi tokenlar sinfidan Classva tahlil qilinadigan satrdan o'tadi. Usul birinchi navbatda ob'ektni sinf konstruktoriga o'tkazish orqali lex()sinf ob'ektini yaratadi . Va keyin u ushbu satrda sinf usulini chaqiradi . Agar leksik tahlil muvaffaqiyatli bo'lsa, ob'ektlar ro'yxatini qaytarish uchun sinf usuli chaqiriladi . Ushbu ob'ektlarning har biri uchun tokenni qaytarish uchun uning sinf usuli va tokenni qaytarish uchun uning sinf usuli chaqiriladi. Ikkala qiymat ham standart chiqishga chop etiladi. Agar leksik tahlil muvaffaqiyatsiz bo'lsa, istisnolardan biri yoki tashlanadi va shunga mos ravishda ishlov beriladi . Qisqartirish uchun keling, faqat ushbu ilovani tashkil etuvchi sinfni ko'rib chiqaylik . Ro'yxat 3 uning manba kodini ko'rsatadi. Listing 3. Kichik matematik til uchun tokenlar to'plamining tavsifiLexanClassLexanlex()LexanTokLexgetTokLexes()LexangetToken()TokLexgetLexeme()LexanExceptionLexExceptionMathTokens
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_]*");
}
Ro'yxat 3 sinf turi MathTokensdoimiylar ketma-ketligini tasvirlaydi, deb ko'rsatadi Token. Ularning har biriga ob'ektning qiymati beriladi Token. Ushbu ob'ektning konstruktori ushbu marker bilan bog'langan barcha belgilar qatorlarini tavsiflovchi muntazam ifoda bilan birga marker nomi bo'lgan qatorni oladi. Aniqlik uchun markerning satr nomi doimiy nomi bilan bir xil bo'lishi ma'qul, ammo bu shart emas. Java tilidagi oddiy iboralar, 5-3-qismKonstantaning Tokenmarkerlar ro'yxatidagi o'rni muhim ahamiyatga ega. Ro'yxatda yuqorida joylashgan doimiylar quyida Tokenjoylashganlarga nisbatan ustunlik qiladi. Masalan, ga duch kelganda , Lexan o'rniga sintokenni tanlaydi . Agar token tokendan oldin bo'lsa , u tanlangan bo'lardi. FUNCIDIDFUNC

LexanDemo ilovasini kompilyatsiya qilish va ishga tushirish

lexan.zipUshbu maqolaning yuklab olinadigan kodi Lexan tarqatishning barcha fayllarini o'z ichiga olgan arxivni o'z ichiga oladi . demosUshbu arxivni oching va ildiz katalogining pastki katalogiga o'ting lexan. Agar siz Windows dan foydalanayotgan bo'lsangiz, demo dastur manba kodlari fayllarini kompilyatsiya qilish uchun quyidagi buyruqni bajaring:
javac -cp ..\library\lexan.jar *.java
Agar kompilyatsiya muvaffaqiyatli bo'lsa, demo ilovasini ishga tushirish uchun quyidagi buyruqni bajaring:
java -cp ..\library\lexan.jar;. LexanDemo
Siz quyidagi natijalarni ko'rishingiz kerak:
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
Xabar sinf doimiy ifoda sifatida qiymatga ega bo'lgan doimiyni e'lon qilmaganligi sababli Неожиданный символ во входном тексте: 20istisno qilinganligi natijasida yuzaga keladi . E'tibor bering, istisno ishlov beruvchisi matnning leksik tahlilidan olingan nomaqbul belgining pozitsiyasini chiqaradi. Tokens etishmayotgan xabar, sinfda hech qanday konstanta e'lon qilinmagani uchun istisno qilinganligining natijasidir . LexanExceptionBinTokensToken2LexExceptionNoTokensToken

Sahna ortida

Lexandvigateli sifatida Lexan sinfidan foydalanadi. 4-listda ushbu sinfning amalga oshirilishini ko'rib chiqing va muntazam iboralarning dvigatelni qayta ishlatishga qo'shgan hissasiga e'tibor bering. Listing 4. Muntazam iboralar asosida leksik analizator arxitekturasini yaratish
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);
      }
   }
}
Usul kodi Cogito Learning veb-saytidagi "Java'da tahlil qiluvchini yozish: Token generatori"lex() blog postida keltirilgan kodga asoslangan . Lexan kodni kompilyatsiya qilish uchun Regex API-dan qanday foydalanishi haqida ko'proq bilish uchun ushbu postni o'qing. Java tilidagi oddiy iboralar, 5-4-qism

Xulosa

Muntazam ifodalar har qanday ishlab chiquvchi uchun foydali bo'lishi mumkin bo'lgan foydali vositadir. Java dasturlash tilining Regex API ularni ilovalar va kutubxonalarda ishlatishni osonlashtiradi. java.util.regexEndi siz oddiy iboralar va ushbu API haqida asosiy tushunchaga ega bo'lganingizdan so'ng, oddiy iboralar va qo'shimcha Regex API usullari haqida ko'proq ma'lumot olish uchun SDK hujjatlarini ko'rib chiqing .
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION