Merge pull request #41 from blackducksw/ubuntu_14
[ohcount] / src / parsers / mxml.rl
1 // mxml.rl written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
2
3 /************************* Required for every parser *************************/
4 #ifndef OHCOUNT_MXML_PARSER_H
5 #define OHCOUNT_MXML_PARSER_H
6
7 #include "../parser_macros.h"
8
9 // the name of the language
10 const char *MXML_LANG = LANG_MXML;
11
12 // the languages entities
13 const char *mxml_entities[] = {
14   "space", "comment", "doctype",
15   "tag", "entity", "any"
16 };
17
18 // constants associated with the entities
19 enum {
20   MXML_SPACE = 0, MXML_COMMENT, MXML_DOCTYPE,
21   MXML_TAG, MXML_ENTITY, MXML_ANY
22 };
23
24 /*****************************************************************************/
25
26 #include "css.h"
27 #include "actionscript.h"
28
29 %%{
30   machine mxml;
31   write data;
32   include common "common.rl";
33   #EMBED(css)
34   #EMBED(actionscript)
35
36   # Line counting machine
37
38   action mxml_ccallback {
39     switch(entity) {
40     case MXML_SPACE:
41       ls
42       break;
43     case MXML_ANY:
44       code
45       break;
46     case INTERNAL_NL:
47       std_internal_newline(MXML_LANG)
48       break;
49     case NEWLINE:
50       std_newline(MXML_LANG)
51       break;
52     case CHECK_BLANK_ENTRY:
53       check_blank_entry(MXML_LANG)
54     }
55   }
56
57   mxml_comment =
58     '<!--' @comment (
59       newline %{ entity = INTERNAL_NL; } %mxml_ccallback
60       |
61       ws
62       |
63       (nonnewline - ws) @comment
64     )* :>> '-->';
65
66   mxml_sq_str =
67     '\'' @code (
68       newline %{ entity = INTERNAL_NL; } %mxml_ccallback
69       |
70       ws
71       |
72       [^\r\n\f\t '\\] @code
73       |
74       '\\' nonnewline @code
75     )* '\'';
76   mxml_dq_str =
77     '"' @code (
78       newline %{ entity = INTERNAL_NL; } %mxml_ccallback
79       |
80       ws
81       |
82       [^\r\n\f\t "\\] @code
83       |
84       '\\' nonnewline @code
85     )* '"';
86   mxml_string = mxml_sq_str | mxml_dq_str;
87
88   ws_or_inl = (ws | newline @{ entity = INTERNAL_NL; } %mxml_ccallback);
89
90   mxml_css_entry = '<mx:Style>' @code;
91   mxml_css_outry = '</mx:Style>' @check_blank_outry @code;
92   mxml_css_line := |*
93     mxml_css_outry @{ p = ts; fret; };
94     # unmodified CSS patterns
95     spaces      ${ entity = CSS_SPACE; } => css_ccallback;
96     css_comment;
97     css_string;
98     newline     ${ entity = NEWLINE;   } => css_ccallback;
99     ^space      ${ entity = CSS_ANY;   } => css_ccallback;
100   *|;
101
102   mxml_as_entry = '<mx:Script>' @code;
103   mxml_as_outry = '</mx:Script>' @check_blank_outry @code;
104   mxml_as_line := |*
105     mxml_as_outry @{ p = ts; fret; };
106     # unmodified Actionscript patterns
107     spaces      ${ entity = AS_SPACE; } => as_ccallback;
108     as_comment;
109     as_string;
110     newline     ${ entity = NEWLINE;  } => as_ccallback;
111     ^space      ${ entity = AS_ANY;   } => as_ccallback;
112   *|;
113
114   mxml_line := |*
115     mxml_css_entry @{ entity = CHECK_BLANK_ENTRY; } @mxml_ccallback
116       @{ saw(CSS_LANG); } => { fcall mxml_css_line; };
117     mxml_as_entry @{ entity = CHECK_BLANK_ENTRY; } @mxml_ccallback
118       @{ saw(AS_LANG); } => { fcall mxml_as_line; };
119     # standard MXML patterns
120     spaces        ${ entity = MXML_SPACE; } => mxml_ccallback;
121     mxml_comment;
122     mxml_string;
123     newline       ${ entity = NEWLINE;    } => mxml_ccallback;
124     ^space        ${ entity = MXML_ANY;   } => mxml_ccallback;
125   *|;
126
127   # Entity machine
128
129   action mxml_ecallback {
130     callback(MXML_LANG, mxml_entities[entity], cint(ts), cint(te), userdata);
131   }
132
133   mxml_css_entry_entity = '<mx:Style>';
134   mxml_css_outry_entity = '</mx:Style>';
135   mxml_css_entity := |*
136     mxml_css_outry_entity @{ fret; };
137     # unmodified CSS patterns
138     space+             ${ entity = CSS_SPACE;   } => css_ecallback;
139     css_comment_entity ${ entity = CSS_COMMENT; } => css_ecallback;
140     # TODO:
141     ^space;
142   *|;
143
144   mxml_as_entry_entity = '<mx:Script>';
145   mxml_as_outry_entity = '</mx:Script>';
146   mxml_as_entity := |*
147     mxml_as_outry_entity @{ fret; };
148     # unmodified Actionscript patterns
149     space+            ${ entity = AS_SPACE;   } => as_ecallback;
150     as_comment_entity ${ entity = AS_COMMENT; } => as_ecallback;
151     # TODO:
152     ^space;
153   *|;
154
155   mxml_comment_entity = '<!--' any* :>> '-->';
156
157   mxml_entity := |*
158     # TODO: mxml_ecallback for mxml_*_{entry,outry}_entity
159     mxml_css_entry_entity => { fcall mxml_css_entity; };
160     mxml_as_entry_entity  => { fcall mxml_as_entity;  };
161     # standard MXML patterns
162     space+              ${ entity = MXML_SPACE;   } => mxml_ecallback;
163     mxml_comment_entity ${ entity = MXML_COMMENT; } => mxml_ecallback;
164     # TODO:
165     ^space;
166   *|;
167 }%%
168
169 /************************* Required for every parser *************************/
170
171 /* Parses a string buffer with MXML markup.
172  *
173  * @param *buffer The string to parse.
174  * @param length The length of the string to parse.
175  * @param count Integer flag specifying whether or not to count lines. If yes,
176  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
177  *   machine optimized for returning entity positions.
178  * @param *callback Callback function. If count is set, callback is called for
179  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
180  *   'lblank' respectively. Otherwise callback is called for each entity found.
181  */
182 void parse_mxml(char *buffer, int length, int count,
183                 void (*callback) (const char *lang, const char *entity, int s,
184                                   int e, void *udata),
185                 void *userdata
186   ) {
187   init
188
189   %% write init;
190   cs = (count) ? mxml_en_mxml_line : mxml_en_mxml_entity;
191   %% write exec;
192
193   // if no newline at EOF; callback contents of last line
194   if (count) { process_last_line(MXML_LANG) }
195 }
196
197 #endif
198
199 /*****************************************************************************/