Initial import of files for generating Doxygen documentation.
[ohcount] / src / parsers / rexx.rl
1 // rexx.rl written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
2
3 /************************* Required for every parser *************************/
4 #ifndef OHCOUNT_REXX_PARSER_H
5 #define OHCOUNT_REXX_PARSER_H
6
7 #include "../parser_macros.h"
8
9 // the name of the language
10 const char *REXX_LANG = LANG_REXX;
11
12 // the languages entities
13 const char *rexx_entities[] = {
14   "space", "comment", "string", "any"
15 };
16
17 // constants associated with the entities
18 enum {
19   REXX_SPACE = 0, REXX_COMMENT, REXX_STRING, REXX_ANY
20 };
21
22 /*****************************************************************************/
23
24 %%{
25   machine rexx;
26   write data;
27   include common "common.rl";
28
29   # Line counting machine
30
31   action rexx_ccallback {
32     switch(entity) {
33     case REXX_SPACE:
34       ls
35       break;
36     case REXX_ANY:
37       code
38       break;
39     case INTERNAL_NL:
40       std_internal_newline(REXX_LANG)
41       break;
42     case NEWLINE:
43       std_newline(REXX_LANG)
44     }
45   }
46
47   action rexx_comment_nc_res { nest_count = 0; }
48   action rexx_comment_nc_inc { nest_count++; }
49   action rexx_comment_nc_dec { nest_count--; }
50
51   rexx_comment =
52     '/*' >rexx_comment_nc_res @comment (
53       newline %{ entity = INTERNAL_NL; } %rexx_ccallback
54       |
55       ws
56       |
57       '/*' @rexx_comment_nc_inc @comment
58       |
59       '*/' @rexx_comment_nc_dec @comment
60       |
61       ^space @comment
62     )* :>> ('*/' when { nest_count == 0 }) @comment;
63
64   rexx_sq_str = '\'' @code ([^\r\n\f'\\] | '\\' nonnewline)* '\'';
65   rexx_dq_str = '"' @code ([^\r\n\f"\\] | '\\' nonnewline)* '"';
66   rexx_string = rexx_sq_str | rexx_dq_str;
67
68   rexx_line := |*
69     spaces        ${ entity = REXX_SPACE; } => rexx_ccallback;
70     rexx_comment;
71     rexx_string;
72     newline       ${ entity = NEWLINE;    } => rexx_ccallback;
73     ^space        ${ entity = REXX_ANY;   } => rexx_ccallback;
74   *|;
75
76   # Entity machine
77
78   action rexx_ecallback {
79     callback(REXX_LANG, rexx_entities[entity], cint(ts), cint(te), userdata);
80   }
81
82   rexx_comment_entity = '/*' >rexx_comment_nc_res (
83     '/*' @rexx_comment_nc_inc
84     |
85     '*/' @rexx_comment_nc_dec
86     |
87     any
88   )* :>> ('*/' when { nest_count == 0 });
89
90   rexx_entity := |*
91     space+              ${ entity = REXX_SPACE;   } => rexx_ecallback;
92     rexx_comment_entity ${ entity = REXX_COMMENT; } => rexx_ecallback;
93     # TODO:
94     ^space;
95   *|;
96 }%%
97
98 /************************* Required for every parser *************************/
99
100 /* Parses a string buffer with Pike code.
101  *
102  * @param *buffer The string to parse.
103  * @param length The length of the string to parse.
104  * @param count Integer flag specifying whether or not to count lines. If yes,
105  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
106  *   machine optimized for returning entity positions.
107  * @param *callback Callback function. If count is set, callback is called for
108  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
109  *   'lblank' respectively. Otherwise callback is called for each entity found.
110  */
111 void parse_rexx(char *buffer, int length, int count,
112                 void (*callback) (const char *lang, const char *entity, int s,
113                                   int e, void *udata),
114                 void *userdata
115   ) {
116   init
117
118   int nest_count = 0;
119
120   %% write init;
121   cs = (count) ? rexx_en_rexx_line : rexx_en_rexx_entity;
122   %% write exec;
123
124   // if no newline at EOF; callback contents of last line
125   if (count) { process_last_line(REXX_LANG) }
126 }
127
128 #endif
129
130 /*****************************************************************************/