JavaRush /Java Blogu /Random-AZ /Java-da müntəzəm ifadələr, 5-ci hissə

Java-da müntəzəm ifadələr, 5-ci hissə

Qrupda dərc edilmişdir
Diqqətinizə Ceff Friesen tərəfindən javaworld veb-saytı üçün yazılmış Java-da müntəzəm ifadələrə dair qısa bələdçinin tərcüməsini təqdim edirik. Oxumaq asanlığı üçün məqaləni bir neçə hissəyə ayırdıq. Bu hissə son hissədir. Java-da müntəzəm ifadələr, 5-ci hissə - 1Java-da müntəzəm ifadələr, 1-ci hissə Java-da müntəzəm ifadələr, 2-ci hissə Java-da müntəzəm ifadələr, 3-cü hissə Java-da müntəzəm ifadələr, 4-cü hissə

Leksik təhlil üçün müntəzəm ifadələrdən istifadə

Normal ifadələrin daha faydalı tətbiqi leksik təhlilin aparılması üçün təkrar istifadə edilə bilən kodlar kitabxanasıdır, hər hansı kompilyator və ya assemblerin əsas komponentidir. Bu halda, simvolların giriş axını tokenlərin çıxış axınında qruplaşdırılır - ümumi məna daşıyan simvol ardıcıllığının adları. Məsələn, giriş axınında c, o, u, n, t, e, , simvollarının ardıcıllığı ilə qarşılaşaraq leksik analizator işarəni (identifikator) çıxara bilər. Tokenə uyğun gələn simvolların ardıcıllığına leksemə deyilir. rID
Markerlər və leksemlər haqqında ətraflı
ID kimi tokenlər bir çox simvol ardıcıllığına uyğun gələ bilər. Belə tokenlər olduqda, tokenə uyğun gələn faktiki token həm də tərtibçi, assembler və ya leksik təhlil tələb edən digər köməkçi proqrama lazımdır. PLUSYalnız simvola uyğun gələn token kimi bir xüsusi simvol ardıcıllığını təmsil edən tokenlər üçün +faktiki işarə tələb olunmur, çünki o, tokendən müəyyən edilə bilər.
Daimi ifadələr dövlət əsaslı leksik analizatorlardan qat-qat səmərəlidir, əl ilə yazılmalı və ümumiyyətlə təkrar istifadə oluna bilməz. Müntəzəm ifadə əsaslı leksik analizatora misal JLex , Java dili üçün leksik generatordur və giriş məlumat axınını tokenlərə bölmək qaydalarını müəyyən etmək üçün müntəzəm ifadələrdən istifadə edir. Başqa bir nümunə Lexandır.

Lexanla tanış olmaq

Lexan leksik analiz üçün təkrar istifadə edilə bilən Java kitabxanasıdır. O , Cogito Learning veb-saytında Java-da Parser Yazmaq bloq yazısı seriyasındakı kodlara əsaslanır . Kitabxana bu məqalənin yüklənə bilən koduna daxil olan paketdə olan aşağıdakı siniflərdən ibarətdir :ca.javajeff.lexan
  • Lexan: leksik analizator;
  • LexanException: sinif konstruktorunda atılan istisnaLexan;
  • LexException: leksik təhlil zamanı səhv sintaksis aşkar edildikdə atılan istisna;
  • Token: müntəzəm ifadə atributlu ad;
  • TokLex: token/token cütü.
Konstruktor Lexan(java.lang.Class tokensClass)yeni leksik analizator yaradır. java.lang.ClassBu tip sabit sinifə uyğun olan sinif obyekti şəklində bir arqument tələb edir static Token. Reflection API-dən istifadə edərək konstruktor bütün sabitləri Tokendəyərlər massivində oxuyur Token[]. Sabitlər yoxdursa Token, istisna atılır LexanException. Java-da müntəzəm ifadələr, 5-2-ci hissəSinif Lexanhəmçinin aşağıdakı iki metodu təqdim edir:
  • Metod bu lekserin siyahısını qaytarır ;List getTokLexes() Token
  • Метод void lex(String str)daxil sətirinin leksik təhlilini [nəticə yerləşdirilmiş] növ dəyərlərinin siyahısına aparır TokLex. Massiv nümunələrindən heç birinə uyğun gəlməyən simvolla rastlaşsanız Token[], istisna atılır LexException.
Sinfin LexanExceptionheç bir metodu yoxdur; istisna mesajını qaytarmaq üçün irsi üsuldan istifadə edir getMessage(). Bunun əksinə olaraq, sinif LexExceptionaşağıdakı üsulları təqdim edir:
  • Metod int getBadCharIndex()marker nümunələrindən heç birinə uyğun gəlməyən simvolun mövqeyini qaytarır.
  • Metod String getText()istisna yaradılarkən təhlil edilmiş mətni qaytarır.
Sinif markerin adını qaytarmaq üçün Tokenmetodu ləğv edir . O, həmçinin işarənin müntəzəm ifadə atributunu qaytaran toString()bir metod təqdim edir . String getPattern()Sinif öz işarəsini qaytaran TokLexbir metod təqdim edir . O, həmçinin işarəsini qaytaran Token getToken()bir metod təqdim edir .String getLexeme()

Lexan kitabxanasının nümayişi

Kitabxananın necə işlədiyini nümayiş etdirmək üçün Lexanərizə yazdım LexanDemo. LexanDemoO , BinTokens, MathTokensvə siniflərindən ibarətdir NoTokens. Tətbiq üçün mənbə kodu LexanDemoSiyahı 2-də göstərilir. Siyahı 2. Lexan kitabxanasının fəaliyyətdə nümayişi
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();
   }
}
Siyahı 2-dəki metod Lexan-dan istifadə edərək leksik təhlili nümayiş etdirmək üçün main()köməkçi proqramı çağırır lex(). Bu metoda edilən hər bir çağırış obyektdəki işarələrin sinfindən Classvə təhlil ediləcək sətirdən ötürülür. Metod lex()əvvəlcə obyekti sinif konstruktoruna Lexanötürərək sinif obyektini yaradır . Və sonra həmin sətirdə sinif metodunu çağırır . Leksik təhlil uğurlu olarsa, obyektlərin siyahısını qaytarmaq üçün sinif metodu çağırılır . Bu obyektlərin hər biri üçün işarəni qaytarmaq üçün onun sinif metodu və işarəni qaytarmaq üçün onun sinif metodu çağırılır. Hər iki dəyər standart çıxışa çap olunur. Əgər leksik təhlil uğursuz olarsa, istisnalardan biri və ya atılır və müvafiq olaraq idarə olunur . Qısalıq üçün gəlin yalnız bu tətbiqi təşkil edən sinfi nəzərdən keçirək . Siyahı 3 onun mənbə kodunu göstərir. Siyahı 3. Kiçik bir riyazi dil üçün işarələr toplusunun təsviriClassLexanlex()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_]*");
}
Siyahı 3 göstərir ki, sinif MathTokenstipli sabitlərin ardıcıllığını təsvir edir Token. Onların hər birinə bir obyektin dəyəri təyin edilir Token. Bu obyektin konstruktoru həmin markerlə əlaqəli bütün simvol sətirlərini təsvir edən müntəzəm ifadə ilə birlikdə markerin adı olan sətir alır. Aydınlıq üçün markerin sətir adının sabitin adı ilə eyni olması arzu edilir, lakin bu tələb olunmur. Markerlər siyahısında Java-da müntəzəm ifadələr, 5-3-cü hissəsabitin mövqeyi vacibdir. TokenSiyahıda yuxarıda yerləşən sabitlər Tokenaşağıda yerləşənlərdən üstündür. Məsələn, qarşılaşdıqda , Lexan əvəzinə sinnişanı seçir . Token tokendən əvvəl olsaydı , seçilərdi. FUNCIDIDFUNC

LexanDemo proqramının tərtib edilməsi və işə salınması

lexan.zipBu məqalənin endirilə bilən koduna Lexan paylanmasının bütün fayllarını ehtiva edən arxiv daxildir . demosBu arxivi çıxarın və kök kataloqunun alt kataloquna keçin lexan. Windows istifadə edirsinizsə, demo proqram mənbə kodu fayllarını tərtib etmək üçün aşağıdakı əmri işlədin:
javac -cp ..\library\lexan.jar *.java
Kompilyasiya uğurlu olarsa, demo tətbiqini işə salmaq üçün aşağıdakı əmri işlədin:
java -cp ..\library\lexan.jar;. LexanDemo
Aşağıdakı nəticələri görməlisiniz:
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
Mesaj, sinfin normal ifadə kimi dəyəri olan sabiti elan etməməsi Неожиданный символ во входном тексте: 20səbəbindən bir istisnanın atılması nəticəsində baş verir . Qeyd edək ki, istisna işləyicisi mətnin leksik təhlilindən əldə edilən uyğun olmayan simvolun mövqeyini çıxarır. Çatışmayan token mesajı, sinifdə heç bir sabit elan edilmədiyi üçün atılan istisnanın nəticəsidir . LexanExceptionBinTokensToken2LexExceptionNoTokensToken

Pərdə arxasında

Lexanmühərriki kimi Lexan sinfindən istifadə edir. Siyahı 4-də bu sinfin tətbiqinə nəzər salın və müntəzəm ifadələrin mühərriki təkrar istifadə edilə bilən hala gətirməsinə töhfəsini qeyd edin. Siyahı 4. Normal ifadələr əsasında leksik analizator arxitekturasının yaradılması
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);
      }
   }
}
Metod kodu Cogito Learning veb-saytında "Java-da Ayrışdırıcının Yazılması: Token Generatoru"lex() bloq yazısında verilmiş koda əsaslanır . Lexan-ın kodu tərtib etmək üçün Regex API-dən necə istifadə etdiyini öyrənmək üçün bu yazını oxuyun. Java-da müntəzəm ifadələr, 5-4-cü hissə

Nəticə

Daimi ifadələr istənilən tərtibatçı üçün faydalı ola biləcək faydalı bir vasitədir. Java proqramlaşdırma dilinin Regex API onları proqramlarda və kitabxanalarda istifadəni asanlaşdırır. java.util.regexArtıq müntəzəm ifadələr və bu API haqqında əsas anlayışınız olduğuna görə, müntəzəm ifadələr və əlavə Regex API metodları haqqında daha çox öyrənmək üçün SDK sənədlərinə nəzər salın .
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION