Advertisement

Advice on writing a parser..

Started by June 06, 2001 07:15 AM
2 comments, last by gimp 23 years, 8 months ago
I''m attempting to make an extremely simple parser. I only need minimal XML compatability as I only expect this document to be read back with my own event based loader. Right now I''m attempting to save a tree to a XML document. I''d generally like to stick to XML simply so people can open the document in an XML editor and modify it. Here is a document generated with MS''s XML Notepad, which seems neat enough(providing the board doesn''t mess with the code)

<XML>
<Window BoundsVisible="True" Position="100 20 0" Colour="195 195 195" Width="250" Height="150">
<Button Position="160 120 0" Width="80" Height="20"/>
<DragBox Position="2 2 0" Width="246" Height="15" Colour="10 36 102" BoundsVisible="False"/>
</Window>
</XML>

The way I want to create it is something like: Stream.BeginObject(std::string("XML")); Stream.BeginObject(std::string("World")); Stream.Attribute(std::string("Name"), std::string("TheWorld")); Stream.EndObject(std::string("World")); Stream.EndObject(std::string("XML")); The problem I''m having is that there is two ways of closing an object, with say </Blah> and /> Will I need to create a stack and trace whats happening or is there a simple way of handling this. Right now I have no clean way when closing an object weather it''s having attributes added and be closed with a slash , contains other objects and needs to be closed with a closing tag. Any advice gladly accepted. Thanks
Chris Brodie
Just a tip for the parser (what you describe above is not a parser):

Use lex/flex and yacc/byacc/bison. This will simplify the parser-writing alot. They aren''t difficult to use.

Bison info
Flex info

It might not be strictly ''necessary'' if you are writing a very simple parser, but it will be nice to know these utilities if you ever want to write a parser and/or scanner for anything larger (In my opinion, they are very useful for small projects too )
Advertisement
The solution to your problem is actually a lot simpler than you think.

The way XML works you can do the short ending (/>) for an object only
if there are no other objects nested in there.

To do this just add a single bool to your Stream class which you can
call bAllowShortEndObject (no doubt you can come up with a better name)
This bool if set to true means that the next EndObject call will be
able to close the previous Object using the short "/>" ending instead
of the verbose ending.

Now everytime you do a BeginObject call you set this flag to true since
if the next call is EndObject you can close with "/>".

Your attribute calls should not need to go near this variable.

Each EndObject call will start with a check on this flag, if it is true
then you use "/>" and if false you use "</Blah>". Then at the end of
each EndObject call you set this flag to false.

Hope this explanation is clear enough if not feel free to e-mail me.

Another tip that is handy in debugging your code is to add a depth
counter that you increment each begin object call and decrement each end
object call, you can use this to add whitespace to properly indent your
xml (4 spaces * depth) or sth like that and it will make your xml more
easily readable. If you do this then each begin object and verbose form
end object call adds a newline and however many spaces indent you like
times depth and makes the stuff more readable for you.

The depth counter can also be a nice quick check to make sure you are
closing all your tags (though it doesnt gurantee they are being closed
with the appropriate closing tag)

Eamonn



Edited by - Skulver on June 6, 2001 12:41:13 PM

Edited by - Skulver on June 6, 2001 12:41:45 PM
I''m not familar with XML. Is the end required to be abbreviated when there are no subobjects or is it optional? If it is optional then why not just use the full ending? It might waste space, but if that was a concern would you be using XML?
Keys to success: Ability, ambition and opportunity.

This topic is closed to new replies.

Advertisement