Почему C ++ не может быть проанализирован с помощью анализатора LR (1)?

С Swift 3 и i0S 10 самый простой способ взаимодействия с номерами телефонов, URL-адресами или адресами в UITextView - использовать UIDataDetectorTypes . В приведенном ниже коде показано, как отображать номер телефона в UITextView, чтобы пользователь мог взаимодействовать с ним.

import UIKit

class ViewController: UIViewController {

    // Link this outlet to a UITextView in your Storyboard
    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        textView.text = "+33687654321"
        textView.isUserInteractionEnabled = true // default: true
        textView.isEditable = false // default: true
        textView.isSelectable = true // default: true
        textView.dataDetectorTypes = [.phoneNumber]
    }

}

С помощью этого кода при нажатии на номер телефона UIAlertController будет pop.


В качестве альтернативы вы можете использовать NSAttributedString :

import UIKit

class ViewController: UIViewController {

    // Link this outlet to a UITextView in your Storyboard
    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works
        let attributes = [NSLinkAttributeName: phoneUrl]
        let attributedString = NSAttributedString(string: "phone number", attributes: attributes)

        textView.attributedText = attributedString
        textView.isUserInteractionEnabled = true // default: true
        textView.isEditable = false // default: true
        textView.isSelectable = true // default: true
    }

}

С помощью этого кода при нажатии на атрибут строка, появится UIAlertController.


Однако вы можете выполнить некоторые пользовательские действия вместо того, чтобы всплывать UIAlertController, когда вы нажимаете на номер телефона. Или вы можете захотеть, чтобы UIAlertController всплывал и выполнял ваше собственное действие в одно и то же время.

В обоих случаях вам нужно будет сделать ваш UIViewController совместимым с UITextViewDelegate протоколом и реализовать textView(_:shouldInteractWith:in:interaction:) . Код ниже показывает, как это сделать.

import UIKit

class ViewController: UIViewController, UITextViewDelegate {

    // Link this outlet to a UITextView in your Storyboard
    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        textView.delegate = self

        textView.text = "+33687654321"
        textView.isUserInteractionEnabled = true
        textView.isEditable = false
        textView.isSelectable = true
        textView.dataDetectorTypes = [.phoneNumber]
    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        /* perform your own custom actions here */
        print(URL)

        return false // return true if you still want UIAlertController to pop up
    }

}

С помощью этого кода при нажатии на номер телефона не появится UIAlertController, и вместо этого вы получите следующую распечатку в консоли:

tel: +33687654321

blockquote>

146
задан zython 30 March 2018 в 19:55
поделиться

4 ответа

Существует интересный поток на Лямбда Окончательное , который обсуждает LALR-грамматика для C++ .

Это включает ссылку на диссертация , который включает обсуждение парсинга C++, который указывает что:

"грамматика C++ неоднозначна, контекстно-зависима и потенциально требует, чтобы бесконечное предвидение разрешило некоторые неоднозначности".

Это продолжает давать много примеров (см. страницу 147 PDF).

пример:

int(x), y, *const z;

значение

int x;
int y;
int *const z;

Выдерживают сравнение с:

int(x), y, new int;

значение

(int(x)), (y), (new int));

(разделенное от запятой выражение).

две маркерных последовательности имеют ту же начальную подпоследовательность, но различные деревья синтаксического анализа, которые зависят от последнего элемента. Перед снимающим неоднозначность может быть произвольно много маркеров.

91
ответ дан anatolyg 30 March 2018 в 19:55
поделиться

Я думаю, что Вы достаточно близки к ответу.

LR (1) средства, что, анализируя от левого до правильных потребностей только один маркер к предвидению для контекста, тогда как LR (∞) означает бесконечное предвидение. Таким образом, синтаксический анализатор должен был бы знать все, что прибывало для выяснения, где это теперь.

6
ответ дан Ry- 30 March 2018 в 19:55
поделиться

LR parsers can't handle ambiguous grammar rules, by design. (Made the theory easier back in the 1970s when the ideas were being worked out).

C and C++ both allow the following statement:

x * y ;

It has two different parses:

  1. It can be the declaration of y, as pointer to type x
  2. It can be a multiply of x and y, throwing away the answer.

Now, you might think the latter is stupid and should be ignored. Most would agree with you; however, there are cases where it might have a side effect (e.g., if multiply is overloaded). but that isn't the point. The point is there are two different parses, and therefore a program can mean different things depending on how this should have been parsed.

The compiler must accept the appropriate one under the appropriate circumstances, and in the absence of any other information (e.g., knowledge of the type of x) must collect both in order to decide later what to do. Thus a grammar must allow this. And that makes the grammar ambiguous.

Thus pure LR parsing can't handle this. Nor can many other widely available parser generators, such as Antlr, JavaCC, YACC, or traditional Bison, or even PEG-style parsers, used in a "pure" way.

There are lots of more complicated cases (parsing template syntax requires arbitrary lookahead, whereas LALR(k) can look ahead at most k tokens), but only it only takes one counterexample to shoot down pure LR (or the others) parsing.

Most real C/C++ parsers handle this example by using some своего рода детерминированный парсер с дополнительным хаком: они переплетают парсинг с таблицей символов коллекция ... так что к моменту "x" синтаксический анализатор знает, является ли x типом или нет, и поэтому может выберите между двумя возможными синтаксическими анализами. Но парсер который делает это, не является контекстным, и парсеры LR (чистые и т. д.) (в лучшем случае) контекстно-свободны.

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

И если вы достаточно обманываете, вы можете заставить парсеры LR работать для C и C ++. Ребята из GCC какое-то время делали это, но дали для ручного синтаксического анализа, я думаю, потому что они хотели улучшенная диагностика ошибок.

Однако есть другой подход, приятный и понятный и отлично разбирает C и C ++ без какой-либо таблицы символов хакерство: парсеры GLR . Это полные контекстно-свободные парсеры (фактически имеющие бесконечное смотреть вперед). Парсеры GLR просто принимают оба синтаксического анализа, создание "дерева" (на самом деле ориентированного ациклического графа, который в основном похож на дерево) что представляет собой неоднозначный синтаксический анализ. Этап пост-синтаксического анализа может разрешить неоднозначности.

Мы используем эту технику во внешних интерфейсах C и C ++ для наших DMS Software Reengineering Tookit (по состоянию на июнь 2017 г. они обрабатывают полный C ++ 17 на диалектах MS и GNU). Они использовались для обработки миллионов строк of large C and C++ systems, with complete, precise parses producing ASTs with complete details of the source code. (See the AST for C++'s most vexing parse.)

226
ответ дан 23 November 2019 в 22:33
поделиться

Как вы можете видеть в моем ответе здесь , C ++ содержит синтаксис, который не может быть детерминированно проанализирован анализатором LL или LR из-за стадии разрешения типа (обычно после анализа ) изменяя порядок операций , и, следовательно, основную форму AST (обычно ожидается, что она будет обеспечена синтаксическим анализом на первом этапе).

9
ответ дан 23 November 2019 в 22:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: