Merge pull request #41 from blackducksw/ubuntu_14
[ohcount] / src / parsers / fsharp.rl
1 // fsharp.rl written by Pavel Shiryaev. Hill30  http://www.hill30.com
2 // based on c.rl
3
4 /************************* Required for every parser *************************/
5 #ifndef OHCOUNT_FSHARP_PARSER_H
6 #define OHCOUNT_FSHARP_PARSER_H
7
8 #include "../parser_macros.h"
9
10 // the name of the language
11 const char *FSHARP_LANG = LANG_FSHARP;
12
13 // the languages entities
14 const char *fsharp_entities[] = {
15   "space", "comment", "string", "number", "preproc",
16   "keyword", "identifier", "operator", "any"
17 };
18
19 // constants associated with the entities
20 enum {
21   FSHARP_SPACE = 0, FSHARP_COMMENT, FSHARP_STRING, FSHARP_NUMBER, FSHARP_PREPROC,
22   FSHARP_KEYWORD, FSHARP_IDENTIFIER, FSHARP_OPERATOR, FSHARP_ANY
23 };
24
25 /*****************************************************************************/
26
27 %%{
28   machine fsharp;
29   write data;
30   include common "common.rl";
31
32   # Line counting machine
33
34   action fsharp_ccallback {
35     switch(entity) {
36     case FSHARP_SPACE:
37       ls
38       break;
39     case FSHARP_ANY:
40       code
41       break;
42     case INTERNAL_NL:
43       std_internal_newline(FSHARP_LANG)
44       break;
45     case NEWLINE:
46       std_newline(FSHARP_LANG)
47     }
48   }
49
50   fsharp_line_comment =
51     '//' @comment (
52       escaped_newline %{ entity = INTERNAL_NL; } %fsharp_ccallback
53       |
54       ws
55       |
56       (nonnewline - ws) @comment
57     )*;
58   fsharp_block_comment =
59     '(*' @comment (
60       newline %{ entity = INTERNAL_NL; } %fsharp_ccallback
61       |
62       ws
63       |
64       (nonnewline - ws) @comment
65     )* :>> '*)';
66   fsharp_comment = fsharp_line_comment | fsharp_block_comment;
67
68   fsharp_sq_str =
69     '\'' @code (
70       escaped_newline %{ entity = INTERNAL_NL; } %fsharp_ccallback
71       |
72       ws
73       |
74       [^\t '\\] @code
75       |
76       '\\' nonnewline @code
77     )* '\'';
78   fsharp_dq_str =
79     '"' @code (
80       escaped_newline %{ entity = INTERNAL_NL; } %fsharp_ccallback
81       |
82       ws
83       |
84       [^\t "\\] @code
85       |
86       '\\' nonnewline @code
87     )* '"';
88   fsharp_string = fsharp_sq_str | fsharp_dq_str;
89
90   fsharp_line := |*
91     spaces    ${ entity = FSHARP_SPACE; } => fsharp_ccallback;
92     fsharp_comment;
93     fsharp_string;
94     newline   ${ entity = NEWLINE; } => fsharp_ccallback;
95     ^space    ${ entity = FSHARP_ANY;   } => fsharp_ccallback;
96   *|;
97
98   # Entity machine
99
100   action fsharp_ecallback {
101     callback(FSHARP_LANG, fsharp_entities[entity], cint(ts), cint(te), userdata);
102   }
103
104   fsharp_line_comment_entity = '//' (escaped_newline | nonnewline)*;
105   fsharp_block_comment_entity = '(*' any* :>> '*)';
106   fsharp_comment_entity = fsharp_line_comment_entity | fsharp_block_comment_entity;
107
108   fsharp_string_entity = sq_str_with_escapes | dq_str_with_escapes;
109
110   fsharp_number_entity = float | integer;
111
112   fsharp_preproc_word =
113     'define' | 'elif' | 'else' | 'endif' | 'error' | 'if' | 'ifdef' |
114     'ifndef' | 'import' | 'include' | 'line' | 'pragma' | 'undef' |
115     'using' | 'warning';
116   # TODO: find some way of making preproc match the beginning of a line.
117   # Putting a 'when starts_line' conditional throws an assertion error.
118   fsharp_preproc_entity =
119     '#' space* (fsharp_block_comment_entity space*)?
120       fsharp_preproc_word (escaped_newline | nonnewline)*;
121
122   fsharp_identifier_entity = (alpha | '_') (alnum | '_')*;
123
124   fsharp_keyword_entity =
125     'and' | 'and_eq' | 'asm' | 'auto' | 'bitand' | 'bitor' | 'bool' |
126     'break' | 'case' | 'catch' | 'char' | 'class' | 'compl' | 'const' |
127     'const_cast' | 'continue' | 'default' | 'delete' | 'do' | 'double' |
128     'dynamic_cast' | 'else' | 'enum' | 'explicit' | 'export' | 'extern' |
129     'false' | 'float' | 'for' | 'friend' | 'goto' | 'if' | 'inline' | 'int' |
130     'long' | 'mutable' | 'namespace' | 'new' | 'not' | 'not_eq' |
131     'operator' | 'or' | 'or_eq' | 'private' | 'protected' | 'public' |
132     'register' | 'reinterpret_cast' | 'return' | 'short' | 'signed' |
133     'sizeof' | 'static' | 'static_cast' | 'struct' | 'switch' |
134     'template' | 'this' | 'throw' | 'true' | 'try' | 'typedef' | 'typeid' |
135     'typename' | 'union' | 'unsigned' | 'using' | 'virtual' | 'void' |
136     'volatile' | 'wchar_t' | 'while' | 'xor' | 'xor_eq';
137
138   fsharp_operator_entity = [+\-/*%<>!=^&|?~:;.,()\[\]{}];
139
140   fsharp_entity := |*
141     space+              ${ entity = FSHARP_SPACE;      } => fsharp_ecallback;
142     fsharp_comment_entity    ${ entity = FSHARP_COMMENT;    } => fsharp_ecallback;
143     fsharp_string_entity     ${ entity = FSHARP_STRING;     } => fsharp_ecallback;
144     fsharp_number_entity     ${ entity = FSHARP_NUMBER;     } => fsharp_ecallback;
145     fsharp_preproc_entity    ${ entity = FSHARP_PREPROC;    } => fsharp_ecallback;
146     fsharp_identifier_entity ${ entity = FSHARP_IDENTIFIER; } => fsharp_ecallback;
147     fsharp_keyword_entity    ${ entity = FSHARP_KEYWORD;    } => fsharp_ecallback;
148     fsharp_operator_entity   ${ entity = FSHARP_OPERATOR;   } => fsharp_ecallback;
149     ^(space | digit)    ${ entity = FSHARP_ANY;        } => fsharp_ecallback;
150   *|;
151 }%%
152
153 /************************* Required for every parser *************************/
154
155 /* Parses a string buffer with C/C++ code.
156  *
157  * @param *buffer The string to parse.
158  * @param length The length of the string to parse.
159  * @param count Integer flag specifying whether or not to count lines. If yes,
160  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
161  *   machine optimized for returning entity positions.
162  * @param *callback Callback function. If count is set, callback is called for
163  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
164  *   'lblank' respectively. Otherwise callback is called for each entity found.
165  */
166 void parse_fsharp(char *buffer, int length, int count,
167              void (*callback) (const char *lang, const char *entity, int s,
168                                int e, void *udata),
169              void *userdata
170   ) {
171   init
172
173   %% write init;
174   cs = (count) ? fsharp_en_fsharp_line : fsharp_en_fsharp_entity;
175   %% write exec;
176
177   // if no newline at EOF; callback contents of last line
178   if (count) { process_last_line(FSHARP_LANG) }
179 }
180
181 #endif
182
183 /*****************************************************************************/