Fix Rust numbers and update keywords.
[ohcount] / src / parsers / rust.rl
1 // rust.rl written by Sébastien Crozet <developer@crozet.re>
2 // Inpired by golang.rl
3
4 /************************* Required for every parser *************************/
5 #ifndef OHCOUNT_RUST_PARSER_H
6 #define OHCOUNT_RUST_PARSER_H
7
8 #include "../parser_macros.h"
9
10 // the name of the language
11 const char *RUST_LANG = LANG_RUST;
12
13 // the languages entities
14 const char *rust_entities[] = {
15   "space", "comment", "string", "number",
16   "keyword", "identifier", "operator", "any"
17 };
18
19 // constants associated with the entities
20 enum {
21   RUST_SPACE = 0, RUST_COMMENT, RUST_STRING, RUST_NUMBER,
22   RUST_KEYWORD, RUST_IDENTIFIER, RUST_OPERATOR, RUST_ANY
23 };
24
25 /*****************************************************************************/
26
27 %%{
28   machine rust;
29   write data;
30   include common "common.rl";
31
32   # Line counting machine
33
34   action rust_ccallback {
35     switch(entity) {
36     case RUST_SPACE:
37       ls
38       break;
39     case RUST_ANY:
40       code
41       break;
42     case INTERNAL_NL:
43       std_internal_newline(RUST_LANG)
44       break;
45     case NEWLINE:
46       std_newline(RUST_LANG)
47     }
48   }
49
50   rust_line_comment =
51     '//' @comment (
52       escaped_newline %{ entity = INTERNAL_NL; } %rust_ccallback
53       |
54       ws
55       |
56       (nonnewline - ws) @comment
57     )*;
58   rust_block_comment =
59     '/*' @comment (
60       newline %{ entity = INTERNAL_NL; } %rust_ccallback
61       |
62       ws
63       |
64       (nonnewline - ws) @comment
65     )* :>> '*/';
66   rust_comment = rust_line_comment | rust_block_comment;
67
68   rust_dq_str =
69     '"' @code (
70       escaped_newline %{ entity = INTERNAL_NL; } %rust_ccallback
71       |
72       ws
73       |
74       [^\t "\\] @code
75       |
76       '\\' nonnewline @code
77     )* '"';
78   rust_string = rust_dq_str;
79
80   rust_line := |*
81     spaces    ${ entity = RUST_SPACE; } => rust_ccallback;
82     rust_comment;
83     rust_string;
84     newline   ${ entity = NEWLINE; } => rust_ccallback;
85     ^space    ${ entity = RUST_ANY;   } => rust_ccallback;
86   *|;
87
88   # Entity machine
89
90   action rust_ecallback {
91     callback(RUST_LANG, rust_entities[entity], cint(ts), cint(te), userdata);
92   }
93
94   rust_line_comment_entity = '//' (escaped_newline | nonnewline)*;
95   rust_block_comment_entity = '/*' any* :>> '*/';
96   rust_comment_entity = rust_line_comment_entity | rust_block_comment_entity;
97
98   rust_string_entity = dq_str_with_escapes;
99
100   # Up to and including "the number entity" these are almost verbatim from the
101   # "number literals" section of the Rust reference manual
102   rust_int_suffix = [iu] ('8' | '16' | '32' | '64')?;
103
104   rust_float_suffix_ty = 'f' ('32' | '64');
105   rust_dec_lit = [0-9_]+;
106   rust_exponent = [Ee] [\-+]? rust_dec_lit;
107   rust_float_suffix = (rust_exponent | '.' rust_dec_lit rust_exponent?)?
108                       rust_float_suffix_ty?;
109
110   rust_num_suffix = rust_int_suffix | rust_float_suffix;
111
112   rust_number_entity = [1-9]     [0-9_]*       rust_num_suffix?
113                      | '0' (     [0-9_]*       rust_num_suffix?
114                            | 'b' [01_]+        rust_int_suffix?
115                            | 'o' [0-7_]+       rust_int_suffix?
116                            | 'x' [0-9A-Fa-f_]+ rust_int_suffix?);
117
118   rust_identifier_entity = (alpha | '_') (alnum | '_')*;
119
120   rust_keyword_entity =
121     'alignof' | 'as' | 'be' | 'break' | 'const' | 'continue' | 'do' | 'else' |
122     'enum' | 'extern' | 'false' | 'fn' | 'for' | 'if' | 'impl' | 'impl' |
123     'in' | 'let' | 'let' | 'log' | 'log' | 'loop' | 'match' | 'mod' | 'mod' |
124     'mut' | 'offsetof' | 'once' | 'priv' | 'pub' | 'pure' | 'ref' | 'return' |
125     'self' | 'sizeof' | 'static' | 'struct' | 'super' | 'trait' | 'true' |
126     'type' | 'typeof' | 'unsafe' | 'use' | 'while' | 'yield';
127
128   rust_operator_entity = [+\-/*%<>!=^&|?~:;.,()\[\]{}@];
129
130   rust_entity := |*
131     space+                 ${ entity = RUST_SPACE;      } => rust_ecallback;
132     rust_comment_entity    ${ entity = RUST_COMMENT;    } => rust_ecallback;
133     rust_string_entity     ${ entity = RUST_STRING;     } => rust_ecallback;
134     rust_number_entity     ${ entity = RUST_NUMBER;     } => rust_ecallback;
135     rust_identifier_entity ${ entity = RUST_IDENTIFIER; } => rust_ecallback;
136     rust_keyword_entity    ${ entity = RUST_KEYWORD;    } => rust_ecallback;
137     rust_operator_entity   ${ entity = RUST_OPERATOR;   } => rust_ecallback;
138     ^(space | digit)       ${ entity = RUST_ANY;        } => rust_ecallback;
139   *|;
140 }%%
141
142 /************************* Required for every parser *************************/
143
144 /* Parses a string buffer with C/C++ code.
145  *
146  * @param *buffer The string to parse.
147  * @param length The length of the string to parse.
148  * @param count Integer flag specifying whether or not to count lines. If yes,
149  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
150  *   machine optimized for returning entity positions.
151  * @param *callback Callback function. If count is set, callback is called for
152  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
153  *   'lblank' respectively. Otherwise callback is called for each entity found.
154  */
155 void parse_rust(char *buffer, int length, int count,
156              void (*callback) (const char *lang, const char *entity, int s,
157                                int e, void *udata),
158              void *userdata
159   ) {
160   init
161
162   %% write init;
163   cs = (count) ? rust_en_rust_line : rust_en_rust_entity;
164   %% write exec;
165
166   // if no newline at EOF; callback contents of last line
167   if (count) { process_last_line(RUST_LANG) }
168 }
169
170 const char *ORIG_RUST_LANG = LANG_RUST;
171
172 #endif
173
174 /*****************************************************************************/