aboutsummaryrefslogtreecommitdiff
path: root/examples/cxx/parser/minimal
diff options
context:
space:
mode:
Diffstat (limited to 'examples/cxx/parser/minimal')
-rw-r--r--examples/cxx/parser/minimal/README51
-rw-r--r--examples/cxx/parser/minimal/driver.cxx145
-rw-r--r--examples/cxx/parser/minimal/gender.hxx14
-rw-r--r--examples/cxx/parser/minimal/makefile66
-rw-r--r--examples/cxx/parser/minimal/people-pimpl-mixin.hxx82
-rw-r--r--examples/cxx/parser/minimal/people-pimpl-tiein.hxx90
-rw-r--r--examples/cxx/parser/minimal/people.map7
-rw-r--r--examples/cxx/parser/minimal/people.xml28
-rw-r--r--examples/cxx/parser/minimal/people.xsd37
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>