OTWO-1213 Works around lost encoding in Ruby/C binding layer
[ohcount] / src / parsers / stratego.rl
1 /************************* Required for every parser *************************/
2 #ifndef OHCOUNT_STRATEGO_PARSER_H
3 #define OHCOUNT_STRATEGO_PARSER_H
4
5 #include "../parser_macros.h"
6
7 // the name of the language
8 const char *STRATEGO_LANG = LANG_STRATEGO;
9
10 // the languages entities
11 const char *stratego_entities[] = {
12   "space", "comment", "string", "any"
13 };
14
15 // constants associated with the entities
16 enum {
17   STRATEGO_SPACE = 0, STRATEGO_COMMENT, STRATEGO_STRING, STRATEGO_ANY
18 };
19
20 /*****************************************************************************/
21
22 %%{
23   machine stratego;
24   write data;
25   include common "common.rl";
26
27   # Line counting machine
28
29   action stratego_ccallback {
30     switch(entity) {
31     case STRATEGO_SPACE:
32       ls
33       break;
34     case STRATEGO_ANY:
35       code
36       break;
37     case INTERNAL_NL:
38       std_internal_newline(STRATEGO_LANG)
39       break;
40     case NEWLINE:
41       std_newline(STRATEGO_LANG)
42     }
43   }
44
45   stratego_line_comment =
46     '//' @comment (
47       escaped_newline %{ entity = INTERNAL_NL; } %stratego_ccallback
48       |
49       ws
50       |
51       (nonnewline - ws) @comment
52     )*;
53
54   stratego_block_comment =
55     '/*' @comment (
56       newline %{ entity = INTERNAL_NL; } %stratego_ccallback
57       |
58       ws
59       |
60       (nonnewline - ws) @comment
61     )* :>> '*/';
62
63   stratego_comment = stratego_line_comment | stratego_block_comment;
64
65   stratego_dq_str =
66     '"' @code (
67       escaped_newline %{ entity = INTERNAL_NL; } %stratego_ccallback
68       |
69       ws
70       |
71       [^\t "\\] @code
72       |
73       '\\' nonnewline @code
74     )* '"';
75
76   stratego_char_str =
77     '\'' (
78       ('\\' [.] '\'') @code
79       |
80       ([^'\\] '\'') @code
81     );
82
83   stratego_string = stratego_dq_str | stratego_char_str;
84
85   stratego_line := |*
86     spaces    ${ entity = STRATEGO_SPACE; } => stratego_ccallback;
87     stratego_comment;
88     stratego_string;
89     newline   ${ entity = NEWLINE; } => stratego_ccallback;
90     ^space    ${ entity = STRATEGO_ANY;   } => stratego_ccallback;
91   *|;
92
93   # Entity machine
94
95   action stratego_ecallback {
96     callback(STRATEGO_LANG, stratego_entities[entity], cint(ts), cint(te),
97              userdata);
98   }
99
100   stratego_line_comment_entity = '//' (escaped_newline | nonnewline)*;
101   stratego_block_comment_entity = '/*' any* :>> '*/';
102   stratego_comment_entity = stratego_line_comment_entity | stratego_block_comment_entity;
103   stratego_string_entity = dq_str_with_escapes | ('\'' (('\\' [.] '\'') | ([^'\\] '\'')));
104
105   stratego_entity := |*
106     space+                  ${ entity = STRATEGO_SPACE;   } => stratego_ecallback;
107     stratego_comment_entity ${ entity = STRATEGO_COMMENT; } => stratego_ecallback;
108     stratego_string_entity  ${ entity = STRATEGO_STRING;   } => stratego_ecallback;
109     # TODO;
110     ^space;
111   *|;
112 }%%
113
114 /************************* Required for every parser *************************/
115
116 /* Parses a string buffer with Stratego code.
117  *
118  * @param *buffer The string to parse.
119  * @param length The length of the string to parse.
120  * @param count Integer flag specifying whether or not to count lines. If yes,
121  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
122  *   machine optimized for returning entity positions.
123  * @param *callback Callback function. If count is set, callback is called for
124  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
125  *   'lblank' respectively. Otherwise callback is called for each entity found.
126  */
127 void parse_stratego(char *buffer, int length, int count,
128                     void (*callback) (const char *lang, const char *entity,
129                                       int s, int e, void *udata),
130                     void *userdata
131   ) {
132   init
133
134   %% write init;
135   cs = (count) ? stratego_en_stratego_line : stratego_en_stratego_entity;
136   %% write exec;
137
138   // if no newline at EOF; callback contents of last line
139   if (count) { process_last_line(STRATEGO_LANG) }
140 }
141
142 #endif
143
144 /*****************************************************************************/