3
    %%{
  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)*;
}%% 

EDIT: Make me understand the meaning of this ">" operator. I have quoted its description from the ragel guide in a comment to @jcomeu

I understand ClearNumber action is called before RecordDigit, if so, currentNumber is initialised to zero, what is the use of multiplying it by 10.

And lastly, the definition of number. What does number=((digit @RecordDigit)+) >ClearNumber mean?

This is the source of code: here

EDIT : *Specifically how does RecordDigit work? What is p? A Pointer? if so, what is it pointing to? What is digit =(*p)- '0'; mean? [solved]

Soham
  • 863
  • 2
  • 19
  • 35

5 Answers5

3

The p pointer

p in RecordDigit is a variable required by Ragel. It is a pointer “to the character data to process.” (In Java and Ruby it is an offset to a byte array, data). The expression (*p) - '0' therefore takes the character code of the current character (for example '7'’s code is 55 in ASCII), subtracts the character code of '0' (48 in ASCII) to get the actual numeric value represented by the character: 55 - 48 = 7.

The > and @ operators

The > operator is used to execute an action when entering a machine from the start state. The @ operator is used to execute an action when moving the machine into a final state.

This means that:

((digit @RecordDigit)+) >ClearNumber

calls first ClearNumber on entering, and calls RecordDigit every time digit is matched. This can be easily verified by altering the actions as follows:

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

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

prints out:

ClearNumber
RecordDigit
RecordDigit
RecordDigit

for a 3-digit number.

Summary

When meeting a new digit for the first time, the currentNumber is set to 0. The digit is changed into a uint8_t by (*p) - '0', and stored into currentNumber. When the next digit comes, its numeric value is computed, and added to the current value of currentNumber multiplied by 10, etc. So the aim of this Ragel sample is to convert space-separated numbers in a string into integers.

Reference

The Ragel user guide contains all the information on the elements above, and is pretty easy to read. I am myself a beginner with Ragel, and had no problem writing my own samples.

Sébastien Le Callonnec
  • 26,254
  • 8
  • 67
  • 80
1

To really understand ragel you must generate the diagram. Install graphviz and run ragel like this:

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

Usually I just use Makefile

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

So I could just run make microscript.png

enter image description here

Zakaria
  • 851
  • 1
  • 7
  • 14
1

I don't know ragel, but the code of RecordDigit is very similar to C, so here's what it does. as you suspected, p is a pointer; *p looks at a character of a character array (string). subtracting '0' from the character '9' leaves the numeric value 9. as you noticed, multiplying by 10 makes no sense the first time this is called, but as successive digits are translated it makes a lot of sense, as now the digits '321' become the number 321, multiplying by 10 after each invocation of RecordDigit to shift the number over by a decimal point.

I don't yet grok "number".

jcomeau_ictx
  • 37,688
  • 6
  • 92
  • 107
  • I thought about the same for multiplication by 10, but still it doesnt make sense, because currentNumber is set to 0 right at the invocation of "number" because it calls ClearNumber first. – Soham Feb 16 '11 at 03:58
  • ClearNumber is called between numbers, not between digits. right? – jcomeau_ictx Feb 16 '11 at 04:00
  • @soham as far as i know in C we need to initialize variables that is the reason i think it has been set to 0 prior to doing any calculations. – Algorithmist Feb 16 '11 at 04:02
  • I understand the final line now too, it's a kind of BNF, processing an arbitrary number of numbers separated by whitespace. – jcomeau_ictx Feb 16 '11 at 04:04
  • I am not very sure but then it makes perfect sense. number = ((digit @RecordDigit)) is intuitive. Adding a '+'after it means look for repetitions, i.e parse variable length numbers and once done ClearNumber; The problem is, the link which I showed didnt explain it like that, which confused me. I am quoting the same in the next comment – Soham Feb 16 '11 at 04:06
  • The ">" character indicates an entering action. This means that when we encounter the first digit that starts a number this action is performed. We set the current number to 0 so we can start adding in the digits. The '@' character indicates a finishing action. That is it will be run when we have a complete "digit" expression - as we encounter each digit. – Soham Feb 16 '11 at 04:07
  • @jcomeau_ictx I didnt see your BNF code. And we both agree on it. – Soham Feb 16 '11 at 04:08
  • heh, looks like I could have saved myself some guesswork by following the link you provided earlier :^} (but then, it's more fun to figure things out than to study). thanks for the +1. – jcomeau_ictx Feb 16 '11 at 04:22
1

Although I do not know the ragel.But looking at the code it seems that it converts a string into a number.If you remember ASCII value of numbers 0-9 range from 48 to 57.Thus suppose input string is '123' so you are obtaining first character and subtracting it by 48 to obtain its value that is 1.And then multiplying by 10 form the decimal number 123.

Algorithmist
  • 6,657
  • 7
  • 35
  • 49
  • @ALL At the time i was posting my comment i didn't notice @jcomeau comment (indeed it was not present both of us were answering concurrently).So we have very similar answers. – Algorithmist Feb 16 '11 at 03:59
  • :) I agree. But then it still doesnt solve a few of my questions – Soham Feb 16 '11 at 04:02
  • @soham what part of the code are you not able to interpret (in terms of logic).Could just tell us the order in which the above code work in ragel. – Algorithmist Feb 16 '11 at 04:04
  • I think you are confused that as current numbr is initialized to 0 so it would always be 0.But this is not the case.For e.g if string is "123".Then the digit variable would contain 1 when the loop is called for the first time.And thus value of currentnumber=0 *10 +1.Thus now it becomes 1 and thus it goes on. – Algorithmist Feb 16 '11 at 04:09
  • Thats the issue, the problem is I am just started learning Ragel (about an hour ago) :) and so getting confused in the simplest stuff. – Soham Feb 16 '11 at 04:09
  • @Algorithmist, yes I got that, but now what bothers me is the operator ">" Which action is called first, is what I dont understand.As per ragel guide(official documentation): "The entering action operator embeds an action into all transitions that enter into the machine from the start state. If the start state is final, then the action is also embedded into the start state as a leaving action. " – Soham Feb 16 '11 at 04:16
1
number = ((digit @RecordDigit)+) >ClearNumber;

'digit' is a built-in machine for : [0-9]

It collects digits one by one (using the '+' operator, meaning '1..N') and enters ClearNumber action at the start of a new number.

@RecordDigit action is used to compute the number during parsing.

Sorry for my English, not my native language. Hope this helps.

Redger
  • 573
  • 3
  • 11