sync
[Bookkeeping.git] / grammar / xml.g
blobf79a06e92af9c76f1c8833c3b2070f702af58406
3 /*
4 Rudimentary lexer grammar for a non-validating XML parser.
5 Lexer is not intended to be used by parser, but is standalone.
6 Use something like
8             while ( lexer.nextToken().getType() != Token.EOF_TYPE );
10 to iterate through tokens.
12 Replace print statements (only there to make something visible) with your 
13 own code and have fun.
15 Limitations:
16 - internal DTD is parsed but not processed
17 - only supported encoding is iso-8859-1 aka extended ASCII aka ISO-latin-1
18 - special entity references (like &amp; &lt;) do not get resolved (to '&', '<')
19 - uses SAX attribute implementation (could easily be dropped)
20   [TJP: commented out so it compiles w/o SAX.]
21 - probably many more 
23 The good thing about some of these limitations is, that the parsed XML
24 can be written *literally* unmodified.
26 Author: Olli Z. (oliver@zeigermann.de)
28 Initial date: 07.02.1999 (02/07/99)
29 Complete revision: 16.01.2003 (01/16/03)
31 Developed and testes with ANTLR 2.7.2
33 header {
34     // import org.xml.sax.helpers.*;
37 class XMLLexer extends Lexer;
38 options {
39     // needed to tell "<!DOCTYPE..."
40     // from "<?..." and "<tag..." and "</tag...>" and "<![CDATA...>"
41     // also on exit branch "]]>", "-->"
42         //k=3;
43         k=10;
44         //charVocabulary = '\3'..'\377'; // extended ASCII (3-255 in octal notation)
45         charVocabulary='\u0000'..'\u007F'; // allow ascii
46         caseSensitive=true;
47         exportVocab=XMLLexer;
50 ZZZ: "<xml/>" ;
52 DOCTYPE!
53     :
54         "<!DOCTYPE" WS rootElementName:NAME 
55         { System.out.println("ROOTELEMENT: "+rootElementName.getText()); }   
56         WS
57         ( 
58             ( "SYSTEM" WS sys1:STRING
59                 { System.out.println("SYSTEM: "+sys1.getText()); }   
60                 
61             | "PUBLIC" WS pub:STRING WS sys2:STRING
62                 { System.out.println("PUBLIC: "+pub.getText()); }   
63                 { System.out.println("SYSTEM: "+sys2.getText()); }   
64             )
65             ( WS )?
66         )?
67         ( dtd:INTERNAL_DTD ( WS )? 
68             { System.out.println("DTD: "+dtd.getText()); }   
70         )?
71                 '>'
72         ;
74 protected INTERNAL_DTD
75     :
76         '['!
77         // reports warning, but is absolutely ok (checked generated code)
78         // besides this warning was not generated with k=1 which is 
79         // enough for this rule...
80         ( options {greedy=false;} : NL
81         | STRING // handle string specially to avoid to mistake ']' in string for end dtd
82         | .
83         )*
84         ']'!
85     ;
87 PI! 
88     :
89         // { AttributesImpl attributes = new AttributesImpl(); }
90         "<?" 
91         target:NAME
92         ( WS )?
93                 ( ATTR /*[attributes]*/ ( WS )? )*
94         {
95             if (target.getText().equalsIgnoreCase("xml")) {
96                 // this is the xml declaration, handle it
97                 System.out.println("XMLDECL: "+target.getText());
98             } else {
99                 System.out.println("PI: "+target.getText());
100             }
101         }
102                 "?>"
103         ;
105 //////////////////
107 COMMENT!
108         :       "<!--" c:COMMENT_DATA "-->"
109         { System.out.println("COMMENT: "+c.getText()); }
110         ;
112 protected COMMENT_DATA
113     : 
114         ( options {greedy=false;} : NL
115         | .
116         )*
117     ;
119 //////////////////
121 ENDTAG! :
122         "</" g:NAME ( WS )? '>'
123         { System.out.println("ENDTAG: "+g.getText()); }
124         ;
126 //////////////////
128 ZZZ!: "<xml/>" ;
130 STARTTAG! : 
131         // XXX should org.xml.sax.AttributesImpl be replaced by something else?
132         // { AttributesImpl attributes = new AttributesImpl(); }
133         '<' 
134         g:NAME
135         ( WS )?
136                 ( ATTR /*[attributes]*/ ( WS )? )*
137                 ( "/>"
138             { System.out.println("EMTYTAG: "+g.getText()); }
139                 | '>'
140             { System.out.println("STARTTAG: "+g.getText()); }
141                 )
142         ;
144 PCDATA! : 
145         p:PCDATA_DATA
146         { System.out.println("PCDATA: "+p.getText()); }
147         ;
149 protected PCDATA_DATA
150         : 
151         ( options {greedy=true;} : NL
152         | ~( '<' | '\n' | '\r' )
153         )+
154     ;
156 CDATABLOCK!
157         : "<![CDATA[" p:CDATA_DATA "]]>"
158         { System.out.println("CDATABLOCK: "+p.getText()); }
159         ;
161 protected CDATA_DATA
162     : 
163         ( options {greedy=false;} : NL
164         | .
165         )*
166     ;
168 protected ATTR // [AttributesImpl attributes]
169         :       name:NAME ( WS )? '=' ( WS )? value:STRING_NO_QUOTE
170         /*
171                 { attributes.addAttribute("", "", name.getText(), "CDATA", 
172                 value.getText()); 
173         }
174         */
175         { System.out.println("ATTRIBUTE: "+name.getText()+"="+value.getText()); }
176         ;
178 protected STRING_NO_QUOTE
179         :       '"'! (~'"')* '"'!
180         |       '\''! (~'\'')* '\''!
181         ;
183 protected STRING
184         :       '"' (~'"')* '"'
185         |       '\'' (~'\'')* '\''
186         ;
188 protected NAME
189         :       ( LETTER | '_' | ':') ( options {greedy=true;} : NAMECHAR )*
190         ;
192 protected NAMECHAR
193         : LETTER | DIGIT | '.' | '-' | '_' | ':'
194         ;
196 protected DIGIT
197         :       '0'..'9'
198         ;
200 protected LETTER
201         : 'a'..'z' 
202         | 'A'..'Z'
203         ;
205 protected WS
206         :       (       options {
207                 greedy = true;
208                         }
209                 :       ' '
210                 |       ESC
211                 )+
212         ;
214 protected ESC
215         : ( '\t'
216                 |       NL
217                 )
218         ;
220 // taken from html.g
221 // Alexander Hinds & Terence Parr
222 // from antlr 2.5.0: example/html 
224 // '\r' '\n' can be matched in one alternative or by matching
225 // '\r' in one iteration and '\n' in another.  I am trying to
226 // handle any flavor of newline that comes in, but the language
227 // that allows both "\r\n" and "\r" and "\n" to all be valid
228 // newline is ambiguous.  Consequently, the resulting grammar
229 // must be ambiguous.  I'm shutting this warning off.
230 protected NL
231     : ( options {
232         generateAmbigWarnings=false;
233         greedy = true;
234     }
235                 : '\n'
236                 |       "\r\n"
237                 |       '\r'
238                 )
239                 { newline(); }
240         ;