Merge pull request #41 from blackducksw/ubuntu_14
[ohcount] / src / parsers / ocaml.rl
1 /************************* Required for every parser *************************/
2 #ifndef OHCOUNT_OCAML_PARSER_H
3 #define OHCOUNT_OCAML_PARSER_H
4
5 #include "../parser_macros.h"
6
7 // the name of the language
8 const char *OCAML_LANG = LANG_OCAML;
9
10 // the languages entities
11 const char *ocaml_entities[] = {
12   "space", "comment", "string", "any"
13 };
14
15 // constants associated with the entities
16 enum {
17   OCAML_SPACE = 0, OCAML_COMMENT, OCAML_STRING, OCAML_ANY
18 };
19
20 /*****************************************************************************/
21
22 %%{
23   machine ocaml;
24   write data;
25   include common "common.rl";
26
27   # Line counting machine
28
29   action ocaml_ccallback {
30     switch(entity) {
31     case OCAML_SPACE:
32       ls
33       break;
34     case OCAML_ANY:
35       code
36       break;
37     case INTERNAL_NL:
38       std_internal_newline(OCAML_LANG)
39       break;
40     case NEWLINE:
41       std_newline(OCAML_LANG)
42     }
43   }
44
45   action ocaml_comment_nc_res { nest_count = 0; }
46   action ocaml_comment_nc_inc { nest_count++; }
47   action ocaml_comment_nc_dec { nest_count--; }
48
49   ocaml_nested_block_comment =
50                 '(*' >ocaml_comment_nc_res @comment (
51                         newline %{ entity = INTERNAL_NL; } %ocaml_ccallback
52                         |
53                         ws
54                         |
55                         '(*' @ocaml_comment_nc_inc @comment
56                         |
57                         '*)' @ocaml_comment_nc_dec @comment
58                         |
59                         (nonnewline - ws) @comment
60                 )* :>> ('*)' when { nest_count == 0 }) @comment;
61
62   ocaml_comment = ocaml_nested_block_comment;
63         ocaml_string = '"' @code ([^\r\n\f"\\] | '\\' nonnewline)* '"';
64
65
66   ocaml_line := |*
67     spaces          ${ entity = OCAML_SPACE; } => ocaml_ccallback;
68     ocaml_comment;
69     ocaml_string;
70     newline         ${ entity = NEWLINE;      } => ocaml_ccallback;
71     ^space          ${ entity = OCAML_ANY;   } => ocaml_ccallback;
72   *|;
73
74   # Entity machine
75
76   action ocaml_ecallback {
77     callback(OCAML_LANG, ocaml_entities[entity], cint(ts), cint(te), userdata);
78   }
79
80   ocaml_comment_entity = '(*' >ocaml_comment_nc_res (
81     '(*' @ocaml_comment_nc_inc
82     |
83     '*)' @ocaml_comment_nc_dec
84     |
85     any
86   )* :>> ('*)' when { nest_count == 0 });
87
88   ocaml_entity := |*
89     space+               ${ entity = OCAML_SPACE;   } => ocaml_ecallback;
90     ocaml_comment_entity ${ entity = OCAML_COMMENT; } => ocaml_ecallback;
91     # TODO:
92     ^space;
93   *|;
94 }%%
95
96 /************************* Required for every parser *************************/
97
98 /* Parses a string buffer with Objective Caml code.
99  *
100  * @param *buffer The string to parse.
101  * @param length The length of the string to parse.
102  * @param count Integer flag specifying whether or not to count lines. If yes,
103  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
104  *   machine optimized for returning entity positions.
105  * @param *callback Callback function. If count is set, callback is called for
106  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
107  *   'lblank' respectively. Otherwise callback is called for each entity found.
108  */
109 void parse_ocaml(char *buffer, int length, int count,
110                  void (*callback) (const char *lang, const char *entity, int s,
111                                    int e, void *udata),
112                  void *userdata
113   ) {
114   init
115
116   int nest_count = 0;
117
118   %% write init;
119   cs = (count) ? ocaml_en_ocaml_line : ocaml_en_ocaml_entity;
120   %% write exec;
121
122   // if no newline at EOF; callback contents of last line
123   if (count) { process_last_line(OCAML_LANG) }
124 }
125
126 #endif
127
128 /*****************************************************************************/