1 #ifndef RAGEL_PARSER_MACROS
2 #define RAGEL_PARSER_MACROS
4 /* Sets the line_start variable to ts.
5 * This is typically used for the SPACE entity in the main action.
7 #define ls { if (!line_start) line_start = ts; }
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.
14 if (!line_contains_code && !line_start) line_start = ts; \
15 line_contains_code = 1; \
18 /* The C equivalent of the Ragel 'comment' action.
19 * This is typically unused, but here for consistency.
22 if (!line_contains_code) { \
23 whole_line_comment = 1; \
24 if (!line_start) line_start = ts; \
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.
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)); \
39 callback(lang, "lblank", cint(line_start), cint(p)); \
41 whole_line_comment = 0; \
42 line_contains_code = 0; \
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.
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)); \
57 callback(lang, "lblank", cint(ts), cint(te)); \
59 whole_line_comment = 0; \
60 line_contains_code = 0; \
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.
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)); \
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).
84 int is_blank_entry(char *p) {
86 while (*pos != '\n' && *pos != '\r' && *pos != '\f') {
87 if (*pos != '\t' || *pos != ' ') return 0;
90 if (*pos == '\r' && *(pos+1) == '\n') pos++;
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.
102 #define check_blank_entry(lang) { \
103 if (is_blank_entry(p)) { \
104 p = is_blank_entry(p); \
110 // Variables used by all parsers. Do not modify.
115 // used for newlines inside patterns like strings and comments that can have
117 #define INTERNAL_NL -2
119 #define CHECK_BLANK_ENTRY -3
123 char *p, *pe, *eof, *ts, *te;
126 // used for calculating offsets from buffer start for start and end positions
128 #define cint(c) ((int) (c - buffer_start))
130 // state flags for line and comment counting
131 int whole_line_comment;
132 int line_contains_code;
134 // the beginning of a line in the buffer for line and comment counting
137 // state variable for the current entity being matched
142 pe = buffer + length; \
145 buffer_start = buffer; \
146 whole_line_comment = 0; \
147 line_contains_code = 0; \