Created 'init' macro for parsers.
[ohcount] / ext / ohcount_native / ragel_parser_macros.h
1 #ifndef RAGEL_PARSER_MACROS
2 #define RAGEL_PARSER_MACROS
3
4 /* Sets the line_start variable to ts.
5  * This is typically used for the SPACE entity in the main action.
6  */
7 #define ls { if (!line_start) line_start = ts; }
8
9 /* The C equivalent of the Ragel 'code' action.
10  * This is tyically used in the main action for entities where Ragel actions
11  * cannot, for one reason or another, be used.
12  */
13 #define code {\
14   if (!line_contains_code && !line_start) line_start = ts; \
15   line_contains_code = 1; \
16 }
17
18 /* The C equivalent of the Ragel 'comment' action.
19  * This is typically unused, but here for consistency.
20  */
21 #define comment {\
22   if (!line_contains_code) { \
23     whole_line_comment = 1; \
24     if (!line_start) line_start = ts; \
25   } \
26 }
27
28 /* Executes standard line counting actions for INTERNAL_NL entities.
29  * This is typically used in the main action for the INTERNAL_NL entity.
30  * @param lang The language name string.
31  */
32 #define std_internal_newline(lang) { \
33   if (callback && p > line_start) { \
34     if (line_contains_code) \
35       callback(lang, "lcode", cint(line_start), cint(p)); \
36     else if (whole_line_comment) \
37       callback(lang, "lcomment", cint(line_start), cint(p)); \
38     else \
39       callback(lang, "lblank", cint(line_start), cint(p)); \
40   } \
41   whole_line_comment = 0; \
42   line_contains_code = 0; \
43   line_start = p; \
44 }
45
46 /* Executes standard line counting actions for NEWLINE entities.
47  * This is typically used in the main action for the NEWLINE entity.
48  * @param lang The language name string.
49  */
50 #define std_newline(lang) {\
51   if (callback && te > line_start) { \
52     if (line_contains_code) \
53       callback(lang, "lcode", cint(line_start), cint(te)); \
54     else if (whole_line_comment) \
55       callback(lang, "lcomment", cint(line_start), cint(te)); \
56     else \
57       callback(lang, "lblank", cint(ts), cint(te)); \
58   } \
59   whole_line_comment = 0; \
60   line_contains_code = 0; \
61   line_start = 0; \
62 }
63
64 /* Processes the last line for buffers that don't have a newline at EOF.
65  * This is typically used at the end of the parse_lang function after the Ragel
66  * parser has been executed.
67  * @param lang The language name string.
68  */
69 #define process_last_line(lang) {\
70   if ((whole_line_comment || line_contains_code) && callback) { \
71     if (line_contains_code) \
72       callback(lang, "lcode", cint(line_start), cint(pe)); \
73     else if (whole_line_comment) \
74       callback(lang, "lcomment", cint(line_start), cint(pe)); \
75   } \
76 }
77
78 /* Determines whether or not the rest of the line is blank.
79  * This is typically used when entering an embedded language.
80  * @param p The position of entry into the emebedded language.
81  * @return 0 if the rest of the line is not blank, the position at the end of
82  *   the newline otherwise (inclusive).
83  */
84 int is_blank_entry(char *p) {
85   char *pos = p+1;
86   while (*pos != '\n' && *pos != '\r' && *pos != '\f') {
87     if (*pos != '\t' || *pos != ' ') return 0;
88     pos++;
89   }
90   if (*pos == '\r' && *(pos+1) == '\n') pos++;
91   return pos;
92 }
93
94 /* If there is a transition into an embedded language and there is only parent
95  * language code on the line (the rest of the line is blank with no child code),
96  * count the line as a line of parent code.
97  * Moves p and te to the end of the newline and calls the std_newline macro. (p
98  * is inclusive, te is not.)
99  * This is typically used in the main action for the CHECK_BLANK_ENTRY entity.
100  * @param lang The language name string.
101  */
102 #define check_blank_entry(lang) { \
103   if (is_blank_entry(p)) { \
104     p = is_blank_entry(p); \
105     te = p + 1; \
106     std_newline(lang) \
107   } \
108 }
109
110 // Variables used by all parsers. Do not modify.
111
112 // used for newlines
113 #define NEWLINE -1
114
115 // used for newlines inside patterns like strings and comments that can have
116 // newlines in them
117 #define INTERNAL_NL -2
118
119 #define CHECK_BLANK_ENTRY -3
120
121 // required by Ragel
122 int cs, act;
123 char *p, *pe, *eof, *ts, *te;
124 int stack[5], top;
125
126 // used for calculating offsets from buffer start for start and end positions
127 char *buffer_start;
128 #define cint(c) ((int) (c - buffer_start))
129
130 // state flags for line and comment counting
131 int whole_line_comment;
132 int line_contains_code;
133
134 // the beginning of a line in the buffer for line and comment counting
135 char *line_start;
136
137 // state variable for the current entity being matched
138 int entity;
139
140 #define init { \
141   p = buffer; \
142   pe = buffer + length; \
143   eof = pe; \
144   \
145   buffer_start = buffer; \
146   whole_line_comment = 0; \
147   line_contains_code = 0; \
148   line_start = 0; \
149   entity = 0; \
150 }
151
152 #endif