File: simplify.html

package info (click to toggle)
jing-trang 20091111-3
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 6,312 kB
  • ctags: 10,531
  • sloc: java: 50,336; xml: 24,925; sh: 451; makefile: 50
file content (147 lines) | stat: -rw-r--r-- 4,421 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Implementing RELAX NG simplification</title>
</head>

<body>
<h1>Implementing RELAX NG simplification</h1>

<h2>Simplifying <code>grammar</code>, <code>define</code> and
<code>ref</code></h2>

<p>This section sketches how to handle the simplification of
<code>grammar</code>, <code>define</code> and <code>ref</code>
described in sections 4.18 and 4.19 of the RELAX NG specification.</p>

<h3>Initial parse</h3>

<p>The result of the initial parse of the full syntax is a Pattern
object representing the schema; this differs from the simple syntax
pattern in that it contains an additional kind of Pattern, namely a
RefPattern.  A RefPattern is a Pattern containing a reference to
another Pattern.</p>

<p>During parsing maintain a current Grammar object.  A Grammar object
contains</p>

<ul>

<li>a reference to the start pattern</li>
<li>a map from NCNames to RefPatterns</li>
<li>a reference to a parent grammar</li>

</ul>

<p>When you see a <code>&lt;grammar&gt;</code> start-tag, create a new
Grammar object that becomes the new current Grammar.  Initially the
map is empty, the start pattern is null, and the parent Grammar is the
old current Grammar.</p>

<p>When you see a <code>define</code> element, look up the name in the
current Grammar's map. If it doesn't exist, add a new RefPattern
referring to the body of the definition.  If it does exist, then check
with the RefPattern's pattern reference is null; it is is null, then
change it to refer to the body of the definition; if it's not null,
then we have a duplicate definition.</p>

<p>Handle <code>&lt;start&gt;</code> similarly to
<code>&lt;define&gt;</code>.</p>

<p>When you see a <code>&lt;ref&gt;</code> element, lookup the name in
the current Grammar's map. If it doesn't exist, add a new RefPattern
with a null pattern reference to the map. In either case, return that
RefPattern as the result of parsing the <code>&lt;ref&gt;</code>
element.</p>

<p>When you see a <code>&lt;parentRef&gt;</code> do the same as
<code>&lt;ref&gt;</code> except use the parent Grammar's map.</p>

<p>At the <code>&lt;grammar&gt;</code> end-tag, check that the start
of the current grammar is non-null. Also walk the map to check that
all RefPatterns have non-null pattern references. Return the start
pattern as the result of parsing the <code>&lt;grammar&gt;</code>
element.</p>

<h3>Checking for illegal recursion</h3>

<p>The next task is to check that there is no illegal recursion. For
this it is convenient to add a <code>checkRecursionDepth</code> field
to the PatternRef object. This should be initialized to -1.  Define a
<code>checkRecursion(int depth)</code> method on Patterns. By default
this simply calls <code>checkRecursion</code> with the same argument
on all subpatterns.  For an ElementPattern it calls
<code>checkRecursion(depth + 1)</code>. For a PatternRef pattern it
does this:</p>

<pre>
checkRecursion(int depth) {
  if (checkRecursionDepth == -1) {
    checkRecursionDepth = depth;
    referencedPattern.checkRecursion(depth);
    checkRecursionDepth = -2;
  }
  else if (depth == checkRecursionDepth)
    error("illegal recursion");
}
</pre>

<p>To check for illegal recursions, call
<code>checkRecursion(0)</code> on the pattern for the schema as a
whole.</p>

<h3>Expanding references</h3>

<p>After determining that there is no illegal recursion, the next
stage is to eliminate RefPatterns.  Do this with an
<code>expand()</code> method on Patterns. It is convenient to add a
<code>boolean</code> expanded field to ElementPattern; this is
initialized to false. For an ElementPattern the code for expand is</p>

<pre>
Pattern expand() {
  if (!expanded) {
    expanded = true;
    content = expand(content);
  }
  return this;
}
</pre>

<p>For a RefPattern it would be simply</p>

<pre>
Pattern expand() {
  return referencedPattern.expand();
}
</pre>


<p>For a Text/DataPattern etc it would be simply</p>

<pre>
Pattern expand() {
  return this;
}
</pre>

<p>For a Choice it would be</p>

<pre>
Pattern expand() {
  return makeChoice(operand1.expand(), operand2.expand());
}
</pre>

<h2>Handling <code>include</code> and <code>combine</code></h2>

<p>See the following <a
href="http://lists.oasis-open.org/archives/relax-ng/200106/msg00058.html"
>message</a> from Kohsuke Kawaguchi.</p>

<address>
<a href="mailto:jjc@jclark.com">James Clark</a>
</address>


</body>
</html>