开发者

What does this piece of Ragel Code do?

开发者 https://www.devze.com 2023-02-10 22:53 出处:网络
%%{ machine microscript; action ClearNumber { currentNumber = 0; } action RecordDigit { uint8_t digit = (*p) - \'0\';
    %%{
  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 i开发者_高级运维t 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]


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.


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".


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.


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.


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

What does this piece of Ragel Code do?

0

精彩评论

暂无评论...
验证码 换一张
取 消