Должен ли лексер различать строковые токены разных типов? - PullRequest
0 голосов
/ 05 декабря 2018

Я пишу нефритовый язык, который перейдет в HTML.Вот как выглядит определение тега:

section #mainWrapper .container

это переносится на:

<section id="mainWrapper" class="container">

Должен ли лексер различать класс и идентификатор или он должен только выплевывать специальные символы с именами?

Другими словами, должен ли массив токенов выглядеть следующим образом:

[
    {type: 'tag', value: 'section'},
    {type: 'id', value: 'mainWrapper'},
    {type: 'class', value: 'container'}
]

, а затем парсер просто собирает их в дерево

или лексер должен быть очень примитивными возвращать только совпадающие строки, а затем синтаксический анализатор позаботится о их различении?:

[
    {type: 'name', value: 'section'},
    {type: 'name', value: '#mainWrapper'},
    {type: 'name', value: '.container'}
]

1 Ответ

0 голосов
/ 05 декабря 2018

Как показывает практика, токенизаторы не должны анализировать, а синтаксический анализатор не должен токенизировать.

В этом конкретном случае мне кажется маловероятным, чтобы каждое неукрашенное использование токена, подобного имени, - такогокак section - обязательно будет tag.Скорее всего, section является тегом из-за его синтаксического контекста.Если токенизатор пытается пометить его как tag, то он отслеживает синтаксический контекст, что означает, что он выполняет синтаксический анализ.

Сигилы . и # менее четкие.Вы можете считать их односимвольными токенами (за синтаксисом которых будет следовать имя) или вы можете считать их первым символом строки специального типа.Некоторые вещи, которые могут повлиять на вас так или иначе:

  • Можно ли отделить символ от следующего имени пробелом?(# mainWrapper).Если это так, возможно, сигил является токеном.

  • Отличается ли лексическая форма класса или идентификатора от имени?Подумайте, например, об использовании специальных символов.Если вы не можете точно распознать объект, не зная, какой символ (если он есть) предшествовал ему, тогда его лучше рассматривать как один токен.

  • Существуют ли другие способы представления class имен.Например, как вы представляете несколько классов?Некоторые возможности в моей голове:

    #classA #classB
    #(classA classB)
    #"classA classB"
    class = "classA classB"
    

    Если какой-либо из вариантов, кроме первого, действителен, вам, вероятно, следует просто сделать # токеном.Но правильная обработка строк в кавычках может создать другие проблемы.В частности, для этого может потребоваться повторная идентификация содержимого строкового литерала, что будет нарушением эвристики, которую парсеры не должны маркировать.К счастью, это не абсолютные правила;иногда необходима повторная компоновка.Но сведите его к минимуму.

Разделение на лексический и синтаксический анализ не должно быть смирительной рубашкой.Это метод организации кода, предназначенный для облегчения написания, понимания, отладки и документирования отдельных частей.Часто (но не всегда) случается, что разделение облегчает пользователям вашего языка понимание синтаксиса, что также важно.Но это не подходит для каждой задачи анализа, и точная граница является гибкой (но не пористой: вы можете поместить границу там, где она наиболее удобна, но как только она будет размещена, не пытайтесь протолкнуть вещи через трещины.)

Если вы обнаружите, что такое разделение задач слишком сложно для вашего проекта, вам следует либо пересмотреть свой языковой дизайн, либо попробовать анализ без сканирования.

...