Ответы пользователя по тегу Парсинг
  • Синтаксический анализатор if-else конструкции на основе контекстно свободной грамматики в БНФ?

    @so-olitary
    1) Да, ты правильно построил БНФ - там нет ничего сверхъестественного.
    Только вот это Expression := Expression;, в общем говоря, всё-таки неверно, т.к. нельзя присвоить: a + b = 5.
    И на мой вкус:
    Expression := Expression | ID=Expression
    Block := Expression; | Expression; Block
    ArrayExpression := { Block }
    BoolExp, как и в С, можно отдельно не выделять, 0 - false, !0 - true


    2) Можно использовать готовый синтаксический анализатор, который разбивает на токены сам по сгенерированным тобой правилам (yacc, bison), можно писать вручную.
    3) Как вручную:

    Я писал в своё время интерпретатор языка программирования.
    БНФ - есть алгоритм - собственно как ты будешь парсить файл. Можешь смотреть на свою структуру, она описывает всевозможные варианты того, что ты можешь увидеть в файле с программой. Читаешь по файлу и проверяешь, что ты оказался прав.

    Сначала регулярными выражениями выдели "токены", что у тебя есть "слово языка":
    1. (\d)+ - Integer
    2. \w (\w | \d )* - identificator
    3. + | - | * | / | % | := | < | > | <= | >= | != | == | ( | )  | ... - arithmetic sign
    4. ; | [ | ] | { | } | ... - separators


    Приступай к разбору:
    Введи понятие функционального оператора, а также понятие ID, которое включает в себя имя переменной или обращание к массиву, как единый "токен" с числовым значением (или Expression) внутри [...].
    Рассматривай файл, как подряд идущие инструкции языка.
    Сначала ты должен понять в какой из них ты находишься - это (1) объявление переменной, (2) арифметическое выражение, (3) условный оператор. Как это понять? Просто читай подряд по словам. например:
    1. если это if - то за ним
    (а) идёт ( Expression ) - это какое-то арифметическое выражение:
    Первое, что с ним нужно делать - это избавиться от скобок и пересобрать в последовательность операций для выполнения, имея в виду приоритеты операций. Проще всего это сделать переведя в польскую аннотацию, делается это при помощи стека - можешь в википедии посмотреть алгоритм. Смысл: (a + b) * c + d = +*+abcd.

    Хотя тебе не надо выполнять программу, я всё-таки рекомендую переводить в польскую нотацию - так ты сможешь проверить корректность арифм.выражения и понять, где оно завершилось.
    Либо можно придумать какие-то правила чтобы это понять, непример: не может быть 2 знака подряд (кроме унарного оператора), ... но так ИМХО сложнее.

    (b) затем за ним идёт Expression | ArrayExpressions, их тоже парсишь.
    (в) может быть Else или следующая инструкция
    И так далее.
    Ответ написан
    1 комментарий