Что делает этот кусок Ragel Code? - PullRequest
3 голосов
/ 16 февраля 2011
    %%{
  machine microscript;

  action ClearNumber {
    currentNumber = 0;
  }

  action RecordDigit {
    uint8_t digit = (*p) - '0';
    currentNumber = (currentNumber * 10) + digit;
  }

  number = ((digit @RecordDigit)+) >ClearNumber;
  whitespace = space+;

  main := number (whitespace number)*;
}%% 

РЕДАКТИРОВАТЬ: Дайте мне понять значение этого оператора ">". Я цитировал его описание из руководства по ragel в комментарии к @ jcomeu

Я понимаю, что действие ClearNumber вызывается перед RecordDigit, если так, то currentNumber инициализируется нулем, зачем использовать умножение на 10.

И, наконец, определение числа. Что значит number=((digit @RecordDigit)+) >ClearNumber?

Это источник кода: здесь

РЕДАКТИРОВАТЬ : * В частности, как работает RecordDigit? Что такое р? Указатель? если да, то на что это указывает? Что означает digit =(*p)- '0';? [решено]

Ответы [ 5 ]

3 голосов
/ 02 апреля 2012

Указатель p

p в RecordDigit - это переменная, требуемая Ragel. Это указатель «на символьные данные для обработки». (В Java и Ruby это смещение байтового массива, data). Поэтому выражение (*p) - '0' принимает код символа текущего символа (например, код '7' равен 55 в ASCII), вычитает код символа '0' (48 в ASCII), чтобы получить фактическое числовое значение, представленное как символ: 55 - 48 = 7.

Операторы > и @

Оператор > используется для выполнения действия при входе машины из состояния запуска. Оператор @ используется для выполнения действия при переводе машины в конечное состояние.

Это означает, что:

((digit @RecordDigit)+) >ClearNumber

звонит первым ClearNumber при входе и звонит RecordDigit каждый раз, когда digit совпадает. Это можно легко проверить, изменив действия следующим образом:

  action ClearNumber {
    printf("ClearNumber\n");
    currentNumber = 0;
  }

  action RecordDigit {
    printf("RecordDigit\n");
    uint8_t digit = (*p) - '0';
    currentNumber = (currentNumber * 10) + digit;
  }

распечатывает:

ClearNumber
RecordDigit
RecordDigit
RecordDigit

для трехзначного числа.

Основная информация

При первой встрече новой цифры currentNumber устанавливается на 0. Цифра изменяется на uint8_t на (*p) - '0' и сохраняется в currentNumber. Когда приходит следующая цифра, ее числовое значение вычисляется и добавляется к текущему значению currentNumber, умноженному на 10, и т. Д. Таким образом, целью этого примера Ragel является преобразование разделенных пробелами чисел в строке в целые числа.

Ссылка

Руководство пользователя Ragel содержит всю информацию об элементах выше и довольно легко читается. Я сам новичок в Ragel, и у меня не было проблем с написанием моих собственных образцов.

1 голос
/ 04 апреля 2012

Чтобы по-настоящему понять ragel, вы должны сгенерировать диаграмму.Установите graphviz и запустите ragel следующим образом:

ragel -V -p microscript.rl | dot -Tpng -o microscript.png

Обычно я просто использую Makefile

%.png: %.rl
        ragel -V -p $*.rl | dot -Tpng -o $@

Чтобы я мог просто запустить make microscript.png

enter image description here

1 голос
/ 16 февраля 2011

Хотя я не знаю ragel . Но, глядя на код, кажется, что преобразует строку в число . Если вы помните значение ASCII чисел в диапазоне 0-9от 48 до 57. Таким образом, предположим, что входной строкой является '123', поэтому вы получаете первый символ и вычитаете его на 48, чтобы получить его значение, равное 1. А затем умножаете на 10, чтобы получить десятичное число 123.

1 голос
/ 17 февраля 2011
number = ((digit @RecordDigit)+) >ClearNumber;

'digit' - это встроенная машина для: [0-9]

Она собирает цифры одна за другой (используя оператор «+», что означает «1..N»)и вводит действие ClearNumber в начале нового номера.

@ Действие RecordDigit используется для вычисления числа во время синтаксического анализа.

Извините за мой английский, а не за мой родной язык.Надеюсь, это поможет.

1 голос
/ 16 февраля 2011

Я не знаю ragel, но код RecordDigit очень похож на C, так что вот что он делает.как вы и предполагали, p - указатель;* p смотрит на символ массива символов (строку).вычитание «0» из символа «9» оставляет числовое значение 9. Как вы заметили, умножение на 10 не имеет смысла при первом вызове, но при переводе последовательных цифр это имеет большой смысл, как теперь цифры«321» становится числом 321, умноженным на 10 после каждого вызова RecordDigit, чтобы сдвинуть число на десятичную точку.

Я пока не получаю «число».

...