/** 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 #include #include %%{ machine roman_numerals; write data; }%% int main(int argc, char* argv[]) { if (argc < 2) { fputs("Usage: roman_numerals ...\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; }