diff options
Diffstat (limited to 'examples/cxx/parser/minimal')
-rw-r--r-- | examples/cxx/parser/minimal/README | 51 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/driver.cxx | 145 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/gender.hxx | 14 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/makefile | 66 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/people-pimpl-mixin.hxx | 82 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/people-pimpl-tiein.hxx | 90 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/people.map | 7 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/people.xml | 28 | ||||
-rw-r--r-- | examples/cxx/parser/minimal/people.xsd | 37 |
9 files changed, 520 insertions, 0 deletions
diff --git a/examples/cxx/parser/minimal/README b/examples/cxx/parser/minimal/README new file mode 100644 index 0000000..a525533 --- /dev/null +++ b/examples/cxx/parser/minimal/README @@ -0,0 +1,51 @@ +This example is a minimal parser implementation that is +intended to work without STL, iostream, or C++ exceptions. + +The example consists of the following files: + +people.xsd + XML Schema which describes a collection of person + records. + +people.xml + Sample XML instance document. + +gender.hxx + C++ gender enum that corresponds to the gender types + in people.xsd. + +people.map + Type map. It maps XML Schema gender type defined in + people.xsd to C++ gender enum defined in gender.hxx. + +people-pskel.hxx +people-pskel.ixx +people-pskel.cxx + Parser skeletons generated by XSD/e from people.xsd and + people.map. The --no-stl and --no-exceptions options + were used to produce these files. + +people-pimpl-mixin.hxx + +people-pimpl-tiein.hxx + Parser implementations (using either mixin or tiein parser + reuse style) that prints the results to STDERR. These are + hand-written implementations of the parser skeletons defined + in people-pskel.hxx. + +driver.cxx + Driver for the example. It first constructs a parser instance + from the parser implementation mentioned above and a couple of + predefined parsers for the XML Schema built-in types. In then + invokes this parser instance to parse the input file. It also + shows how to handle parsing and validation errors using error + codes. + +To run the example on the sample XML instance document simply +execute: + +$ ./driver people.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver <people.xml diff --git a/examples/cxx/parser/minimal/driver.cxx b/examples/cxx/parser/minimal/driver.cxx new file mode 100644 index 0000000..e526358 --- /dev/null +++ b/examples/cxx/parser/minimal/driver.cxx @@ -0,0 +1,145 @@ +// file : examples/cxx/parser/minimal/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <stdio.h> + +#include "people-pskel.hxx" // Get the configuration macros (XSDE_*). + +#if defined(XSDE_REUSE_STYLE_MIXIN) +# include "people-pimpl-mixin.hxx" +#elif defined(XSDE_REUSE_STYLE_TIEIN) +# include "people-pimpl-tiein.hxx" +#else +# error this example requires mixin or tiein parser reuse support +#endif + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + fprintf (stderr, "XML file not specified, reading from STDIN\n"); + } + else + input = argv[1]; + + // Construct the parser. + // + xml_schema::unsigned_short_pimpl unsigned_short_p; + xml_schema::string_pimpl string_p; + + gender_pimpl gender_p; + person_pimpl person_p; + people_pimpl people_p; + + person_p.parsers (string_p, string_p, gender_p, unsigned_short_p); + people_p.parsers (person_p); + + // Open the file or use STDIN. + // + FILE* f = argc > 1 ? fopen (argv[1], "rb") : stdin; + + if (f == 0) + { + fprintf (stderr, "%s: unable to open\n", input); + return 1; + } + + // Parse. + // + typedef xml_schema::parser_error error; + error e; + bool io_error = false; + + do + { + xml_schema::document_pimpl doc_p (people_p, "people"); + + if (e = doc_p._error ()) + break; + + people_p.pre (); + + if (e = people_p._error ()) + break; + + char buf[4096]; + + do + { + size_t s = fread (buf, 1, sizeof (buf), f); + + if (s != sizeof (buf) && ferror (f)) + { + io_error = true; + break; + } + + doc_p.parse (buf, s, feof (f) != 0); + e = doc_p._error (); + + } while (!e && !feof (f)); + + if (io_error || e) + break; + + people_p.post_people (); + + e = people_p._error (); + + } while (false); + + if (argc > 1) + fclose (f); + + // Handle errors. + // + + if (io_error) + { + fprintf (stderr, "%s: read failure\n", input); + return 1; + } + + if (e) + { + switch (e.type ()) + { + case error::sys: + { + fprintf (stderr, "%s: %s\n", input, e.sys_text ()); + break; + } + case error::xml: + { + fprintf (stderr, "%s:%lu:%lu: %s\n", + input, e.line (), e.column (), e.xml_text ()); + break; + } +#ifdef XSDE_PARSER_VALIDATION + case error::schema: + { + fprintf (stderr, "%s:%lu:%lu: %s\n", + input, e.line (), e.column (), e.schema_text ()); + break; + } +#endif + case error::app: + { + fprintf (stderr, "%s:%lu:%lu: application error %d\n", + input, e.line (), e.column (), e.app_code ()); + break; + } + default: + break; + } + + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/minimal/gender.hxx b/examples/cxx/parser/minimal/gender.hxx new file mode 100644 index 0000000..d348ccd --- /dev/null +++ b/examples/cxx/parser/minimal/gender.hxx @@ -0,0 +1,14 @@ +// file : examples/cxx/parser/minimal/gender.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef GENDER_HXX +#define GENDER_HXX + +enum gender +{ + male, + female +}; + +#endif // GENDER_HXX diff --git a/examples/cxx/parser/minimal/makefile b/examples/cxx/parser/minimal/makefile new file mode 100644 index 0000000..1f0466c --- /dev/null +++ b/examples/cxx/parser/minimal/makefile @@ -0,0 +1,66 @@ +# file : examples/cxx/parser/minimal/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make + +xsd := people.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.o)) +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): cpp_options := -I$(out_base) -I$(src_base) +$(obj) $(dep): $(xsde.l.cpp-options) + +skel := $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) + +$(skel): xsde := $(out_root)/xsde/xsde +$(skel): xsde_options += --type-map $(src_base)/people.map + +$(skel): $(out_root)/xsde/xsde $(src_base)/people.map + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=-pskel.cxx.xsd.clean)) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(scf_root)/xsde/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/minimal/people-pimpl-mixin.hxx b/examples/cxx/parser/minimal/people-pimpl-mixin.hxx new file mode 100644 index 0000000..eb2c331 --- /dev/null +++ b/examples/cxx/parser/minimal/people-pimpl-mixin.hxx @@ -0,0 +1,82 @@ +// file : examples/cxx/parser/people/people-pimpl-mixin.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef PEOPLE_PIMPL_HXX +#define PEOPLE_PIMPL_HXX + +#include "gender.hxx" +#include "people-pskel.hxx" + +struct gender_pimpl: virtual gender_pskel, xml_schema::string_pimpl +{ + virtual gender + post_gender () + { + char* s = post_string (); + + if (!_error ()) + { + gender g = strcmp (s, "male") ? female : male; + + delete[] s; + return g; + } + else + return male; // This value will never be used. + } +}; + +struct person_pimpl: virtual person_pskel +{ + virtual void + first_name (char* n) + { + printf ("first: %s\n", n); + delete[] n; + } + + virtual void + last_name (char* n) + { + printf ("last: %s\n", n); + delete[] n; + } + + virtual void + gender (::gender g) + { + switch (g) + { + case male: + { + printf ("gender: male\n"); + break; + } + case female: + { + printf ("gender: female\n"); + break; + } + } + } + + virtual void + age (unsigned short a) + { + printf ("age: %hu\n", a); + } +}; + +struct people_pimpl: virtual people_pskel +{ + virtual void + person () + { + // Add an extra newline after each person record. + // + printf ("\n"); + } +}; + +#endif // PEOPLE_PIMPL_HXX diff --git a/examples/cxx/parser/minimal/people-pimpl-tiein.hxx b/examples/cxx/parser/minimal/people-pimpl-tiein.hxx new file mode 100644 index 0000000..154c861 --- /dev/null +++ b/examples/cxx/parser/minimal/people-pimpl-tiein.hxx @@ -0,0 +1,90 @@ +// file : examples/cxx/parser/people/people-pimpl-tiein.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef PEOPLE_PIMPL_HXX +#define PEOPLE_PIMPL_HXX + +#include "gender.hxx" +#include "people-pskel.hxx" + +struct gender_pimpl: gender_pskel +{ + gender_pimpl () + : gender_pskel (&base_impl_) + { + } + + virtual gender + post_gender () + { + char* s = post_string (); + + if (!_error ()) + { + gender g = strcmp (s, "male") ? female : male; + + delete[] s; + return g; + } + else + return male; // This value will never be used. + } + +private: + xml_schema::string_pimpl base_impl_; +}; + +struct person_pimpl: person_pskel +{ + virtual void + first_name (char* n) + { + printf ("first: %s\n", n); + delete[] n; + } + + virtual void + last_name (char* n) + { + printf ("last: %s\n", n); + delete[] n; + } + + virtual void + gender (::gender g) + { + switch (g) + { + case male: + { + printf ("gender: male\n"); + break; + } + case female: + { + printf ("gender: female\n"); + break; + } + } + } + + virtual void + age (unsigned short a) + { + printf ("age: %hu\n", a); + } +}; + +struct people_pimpl: people_pskel +{ + virtual void + person () + { + // Add an extra newline after each person record. + // + printf ("\n"); + } +}; + +#endif // PEOPLE_PIMPL_HXX diff --git a/examples/cxx/parser/minimal/people.map b/examples/cxx/parser/minimal/people.map new file mode 100644 index 0000000..05558a1 --- /dev/null +++ b/examples/cxx/parser/minimal/people.map @@ -0,0 +1,7 @@ +# file : examples/cxx/parser/minimal/people.map +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : not copyrighted - public domain + +include "gender.hxx"; + +gender ::gender ::gender; diff --git a/examples/cxx/parser/minimal/people.xml b/examples/cxx/parser/minimal/people.xml new file mode 100644 index 0000000..fce688c --- /dev/null +++ b/examples/cxx/parser/minimal/people.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/parser/minimal/people.xml +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="people.xsd"> + + <person> + <first-name>John</first-name> + <last-name>Doe</last-name> + <gender>male</gender> + <age>32</age> + </person> + + <person> + <first-name>Jane</first-name> + <last-name>Doe</last-name> + <gender>female</gender> + <age>28</age> + </person> + +</people> diff --git a/examples/cxx/parser/minimal/people.xsd b/examples/cxx/parser/minimal/people.xsd new file mode 100644 index 0000000..d2e8f47 --- /dev/null +++ b/examples/cxx/parser/minimal/people.xsd @@ -0,0 +1,37 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/parser/minimal/people.xsd +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + + <xsd:simpleType name="gender"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="male"/> + <xsd:enumeration value="female"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="person"> + <xsd:sequence> + <xsd:element name="first-name" type="xsd:string"/> + <xsd:element name="last-name" type="xsd:string"/> + <xsd:element name="gender" type="gender"/> + <xsd:element name="age" type="xsd:unsignedShort"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="people"> + <xsd:sequence> + <xsd:element name="person" type="person" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="people" type="people"/> + +</xsd:schema> |