Skip to content

Instantly share code, notes, and snippets.

@zed
Last active May 12, 2017 00:32
Show Gist options
  • Select an option

  • Save zed/e7bad76d922825604d1d93bb43f6cfa6 to your computer and use it in GitHub Desktop.

Select an option

Save zed/e7bad76d922825604d1d93bb43f6cfa6 to your computer and use it in GitHub Desktop.
/** Convert Roman numerals given on the command line to decimals.
$ ragel -F0 -p -o roman_numerals.c roman_numerals.rl
$ cc -o roman_numerals roman_numerals.c
$ ./roman_numerals IX XII
9
12
$ ./roman_numerals IIX && exit 1 || echo invalid
invalid
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
%%{
machine roman_numerals;
write data;
}%%
int main(int argc, char* argv[]) {
if (argc < 2) {
fputs("Usage: roman_numerals <text>...\n", stderr);
exit(EXIT_FAILURE);
}
for (int i = 1; i < argc; ++i) {
int n, cs;
char *p = argv[i], *pe = p + strlen(p), *eof = pe;
%%{
thousands = ('M' %{ n += 1000; }){,3};
hundreds = "CM" %{ n += 900; }
| "CD" %{ n += 400; }
| ('D' %{ n += 500; } )? ('C' %{ n += 100; }){,3};
tens = "XC" %{ n += 90; }
| "XL" %{ n += 40; }
| ('L' %{ n += 50; } )? ('X' %{ n += 10; }){,3};
units = "IX" %{ n += 9; }
| "IV" %{ n += 4; }
| ('V' %{ n += 5; } )? ('I' %{ n += 1; }){,3};
numeral = thousands hundreds tens units;
main := numeral > { n = 0; } ;
write init;
write exec;
}%%
if (!n || cs == roman_numerals_error)
exit(EXIT_FAILURE);
printf("%d\n", n); /* print result */
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment