JavaRush /Java блогы /Random-KK /Java тіліндегі тұрақты өрнектер, 5-бөлім

Java тіліндегі тұрақты өрнектер, 5-бөлім

Топта жарияланған
Сіздердің назарларыңызға Джефф Фризеннің javaworld веб-сайты үшін жазған Java тіліндегі тұрақты тіркестерге арналған қысқаша нұсқаулықтың аудармасын ұсынамыз. Оқуға ыңғайлы болу үшін мақаланы бірнеше бөлікке бөлдік. Бұл бөлім соңғы. Java тіліндегі тұрақты өрнектер, 5 - 1 бөлімJava тіліндегі тұрақты өрнектер, 1 бөлім Java тіліндегі тұрақты өрнектер, 2 бөлім Java тіліндегі тұрақты өрнектер, 3 бөлім Java тіліндегі тұрақты өрнектер, 4 бөлім

Лексикалық талдау үшін тұрақты тіркестерді қолдану

Тұрақты өрнектердің одан да пайдалы қолданбасы кез келген компилятордың немесе ассемблердің негізгі құрамдас бөлігі болып табылатын лексикалық талдауды орындауға арналған қайта пайдалануға болатын codeтардың кітапханасы болып табылады. Бұл жағдайда таңбалардың кіріс ағыны таңбалауыштардың шығыс ағынына топтастырылады - жалпы мағынасы бар таңбалар тізбегінің атаулары. Мысалы, кіріс ағынында c, o, u, n, t, e, , таңбаларының тізбегін кездестіріп , лексикалық анализатор таңбалауышты (идентификатор) шығара алады. Желтоқсанға сәйкес келетін таңбалар тізбегі лексема деп аталады. rID
Маркерлер мен лексемалар туралы толығырақ
Идентификатор сияқты токендер көптеген таңбалар тізбегіне сәйкес келуі мүмкін. Мұндай таңбалауыштар жағдайында таңбалауышқа сәйкес келетін нақты таңбалауыш компиляторға, ассемблерге немесе лексикалық талдауды қажет ететін басқа утorтаға да қажет. Таңбалардың бір нақты тізбегін көрсететін таңбалауыштар үшін, мысалы PLUSтек таңбаға сәйкес келетін таңбалауыш +, нақты таңбалауыш талап етілмейді, себебі оны таңбалауыштан анықтауға болады.
Тұрақты тіркестер қолмен жазылуы керек және әдетте қайта пайдалануға болмайтын күйге негізделген лексикалық анализаторларға қарағанда әлдеқайда тиімді. Тұрақты өрнекке негізделген лексикалық анализатордың мысалы JLex , кіріс деректер ағынын таңбалауыштарға бөлу ережелерін анықтау үшін тұрақты өрнектерді пайдаланатын Java тіліне арналған лексикалық генератор. Тағы бір мысал - Лексан.

Лексанмен танысу

Lexan - лексикалық талдау үшін қайта пайдалануға болатын Java кітапханасы. Ол Cogito Learning веб-сайтындағы Java тілінде талдаушы жазу блог жазбалар сериясының codeына негізделген . Кітапхана осы мақаланың жүктеп алынатын codeында қамтылған бумадағы келесі сыныптардан тұрады :ca.javajeff.lexan
  • Lexan: лексикалық анализатор;
  • LexanException: сынып конструкторында шығарылған ерекшелікLexan;
  • LexException: лексикалық талдау кезінде қате синтаксис анықталса, ерекшелік тасталады;
  • Token: тұрақты өрнек атрибуты бар атау;
  • TokLex: таңбалауыш/токен жұбы.
Конструктор Lexan(java.lang.Class tokensClass)жаңа лексикалық анализатор жасайды. java.lang.ClassОл тұрақты класс түріне сәйкес келетін класс нысаны түріндегі бір аргументті талап етеді static Token. Reflection API көмегімен конструктор барлық тұрақты мәндерді Tokenмәндер жиымында оқиды Token[]. Егер Tokenтұрақты мәндер болмаса, ерекше жағдай шығарылады LexanException. Java тіліндегі тұрақты өрнектер, 5 - 2 бөлімКласс Lexanсонымен қатар келесі екі әдісті ұсынады:
  • Әдіс осы лексердің тізімін қайтарады ;List getTokLexes() Token
  • Метод void lex(String str)түріндегі мәндер тізіміне енгізу жолына [нәтиже орналастырылған] лексикалық талдау жасайды 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. Қолданбаның бастапқы codeы LexanDemo2-тізімде көрсетілген. Листинг 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-тізбедегі әдіс lex()Lexan көмегімен лексикалық талдауды көрсету үшін қызметтік бағдарламаны шақырады. Бұл әдіске әрбір шақыру нысандағы таңбалауыштар класын Classжәне талданатын жолды береді. Әдіс алдымен an objectіні класс конструкторына беру арқылы lex()сынып an objectісін жасайды . Содан кейін ол осы жолда сынып әдісін шақырады. Егер лексикалық талдау сәтті болса, нысандар тізімін қайтару үшін класс әдісі шақырылады . Осы нысандардың әрқайсысы үшін таңбалауышты қайтару үшін оның класс әдісі және таңбалауышты қайтару үшін оның класс әдісі шақырылады. Екі мән де стандартты шығысқа басып шығарылады. Егер лексикалық талдау сәтсіз болса, ерекше жағдайлардың бірі немесе лақтырылады және сәйкесінше өңделеді . Қысқалық үшін осы қолданбаны құрайтын сыныпты ғана қарастырайық . Листинг 3 оның бастапқы codeын көрсетеді. Листинг 3. Шағын математикалық тілге арналған таңбалауыштар жиынтығының сипаттамасыLexanClassLexanlex()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_]*");
}
3-тізімде класс MathTokensтүріндегі тұрақтылар тізбегін сипаттайтынын көрсетеді Token. Олардың әрқайсысына an objectінің мәні тағайындалады Token. Осы нысанның конструкторы осы маркермен байланыстырылған барлық таңбалар жолдарын сипаттайтын тұрақты өрнекпен бірге маркердің аты болып табылатын жолды алады. Түсінікті болу үшін маркердің жол атауы тұрақтының атымен бірдей болғаны жөн, бірақ бұл талап етілмейді. Маркерлер тізіміндегі Java тіліндегі тұрақты өрнектер, 5 - 3 бөлімтұрақтының орны маңызды. TokenТізімде жоғары орналасқан тұрақтылар Tokenтөменде орналасқандардан басым болады. Мысалы, кездескен кезде Лексан орнына sinтаңбалауышты таңдайды . Егер таңбалауыш таңбалауыштан бұрын болса , ол таңдалған болар еді. FUNCIDIDFUNC

LexanDemo қолданбасын құрастыру және іске қосу

lexan.zipОсы мақаланың жүктеп алынатын codeы Lexan таратуының барлық файлдарын қамтитын мұрағатты қамтиды . demosБұл мұрағатты қаптамадан шығарып, түбірлік каталогтың ішкі каталогына өтіңіз lexan. Егер сіз Windows жүйесін пайдаланып жатсаңыз, демонстрациялық қолданбаның бастапқы code файлдарын құрастыру үшін келесі пәрменді орындаңыз:
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шығарылған ерекше жағдайдың нәтижесінде пайда болады . Ерекшелік өңдеушісі мәтіннің лексикалық талдауынан алынған сәйкес емес таңбаның орнын шығаратынын ескеріңіз. Токендердің жетіспейтіндігі туралы хабарлама сыныпта тұрақты мәндер жарияланбағандықтан, лақтырылған ерекше жағдайдың нәтижесі болып табылады . LexanExceptionBinTokensToken2LexExceptionNoTokensToken

Сахна артында

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);
      }
   }
}
Әдіс codeы Cogito Learning веб-сайтындағы «Java тілінде талдаушыны жазу: таңбалауыш генераторы»lex() блогында берілген codeқа негізделген . Lexan codeты құрастыру үшін Regex API қалай пайдаланатыны туралы көбірек білу үшін осы жазбаны оқыңыз. Java тіліндегі тұрақты өрнектер, 5 - 4 бөлім

Қорытынды

Тұрақты өрнектер кез келген әзірлеушіге пайдалы болуы мүмкін пайдалы құрал болып табылады. Java бағдарламалау тілінің Regex API интерфейсі оларды қолданбалар мен кітапханаларда пайдалануды жеңілдетеді. java.util.regexЕнді сізде тұрақты өрнектер және осы API туралы негізгі түсінік бар, тұрақты өрнектер және қосымша Regex API әдістері туралы көбірек білу үшін SDK құжаттамасын қараңыз .
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION