/[suikacvs]/test/suikawebwww/www/js/sami/script/sami-pg.js
Suika

Contents of /test/suikawebwww/www/js/sami/script/sami-pg.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download) (as text)
Sun Jun 7 09:58:31 2009 UTC (17 years, 2 months ago) by wakaba
Branch: MAIN
File MIME type: application/javascript
implemented LR(1)

1 wakaba 1.1 /*
2    
3     sami-pg.js - SAMI Parser Generator Module
4    
5     */
6    
7     /* Requires sami-core.js */
8    
9     if (!SAMI.PG) SAMI.PG = {};
10    
11     /* --- Common Grammer Vocabulary --- */
12    
13     SAMI.PG.Symbol = new SAMI.Class (function () {
14    
15     }, {
16     isTerminal: false,
17     key: null
18     }); // Symbol
19    
20     SAMI.PG.TerminalSymbol = new SAMI.Subclass (function (tokenType) {
21     this.tokenType = tokenType;
22     this.key = /* 'terminal-' + */ tokenType;
23     }, SAMI.PG.Symbol, {
24     isTerminal: true,
25     // tokenType
26     // key
27    
28     isSameSymbol: function (s) {
29     if (!s || !s.isTerminal) return false;
30     return this.tokenType == s.tokenType;
31     }, // isSameSymbol
32    
33     getFirsts: function (ruleSet) {
34     return new SAMI.List ([this.tokenType]);
35     }, // getFirsts
36    
37     toString: function () {
38     return '"' + this.tokenType.replace (/([\u0022\u005C])/g, '\\$1') + '"';
39     } // toString
40     }); // TerminalSymbol
41    
42     SAMI.PG.NonTerminalSymbol = new SAMI.Subclass (function (symbolName) {
43     this.symbolName = symbolName;
44     this.key = 'nonterminal-' + symbolName;
45     }, SAMI.PG.Symbol, {
46     // symbolName
47     // key
48    
49     isSameSymbol: function (s) {
50     if (!s || s.isTerminal) return false;
51     return this.symbolName == s.symbolName;
52     }, // isSameSymbol
53    
54    
55     getFirsts: function (ruleSet) {
56     var firstHash = new SAMI.Hash;
57    
58     var firstNonTerminals = new SAMI.List ([this.symbolName]);
59     var checkedNames = {};
60     while (firstNonTerminals.list.length) {
61     var first = firstNonTerminals.shift ();
62     if (checkedNames['nonterminal-' + first]) continue;
63     checkedNames['nonterminal-' + first] = true;
64    
65     ruleSet.getRulesByName (first).rules.forEach (function (rule) {
66     var ruleFirst = rule.symbols.list[0];
67     if (!ruleFirst) return;
68     if (ruleFirst.isTerminal) {
69     firstHash.set (ruleFirst.tokenType, true);
70     } else {
71     firstNonTerminals.push (ruleFirst.symbolName);
72     }
73     });
74     }
75    
76     return firstHash.mapToList (function (n) { return n });
77     }, // getFirsts
78    
79     toString: function () {
80     return this.symbolName;
81     } // toString
82     }); // NonTerminalSymbol
83    
84     SAMI.PG.Rule = new SAMI.Class (function (symbolName, symbols) {
85     this.symbolName = symbolName;
86     this.symbols = new SAMI.List (symbols);
87     }, {
88     // symbolName
89     // symbols
90    
91     getKey: function () {
92     return this.toString ();
93     }, // getKey
94    
95     clone: function () {
96     var newRule = new this.constructor (this.symbolName, this.symbols.clone ());
97     return newRule;
98     }, // clone
99    
100     toString: function () {
101     return this.symbolName + ' := ' + this.symbols.list.join (' ');
102     } // toString
103     }); // Rule
104    
105     SAMI.PG.RuleSet = new SAMI.Class (function (rules) {
106     this.rules = new SAMI.List (rules);
107     }, {
108     // rules
109    
110     getRulesByName: function (symbolName) {
111     return new this.constructor (this.rules.grep (function (r) { return r.symbolName == symbolName }));
112     }, // getRulesByName
113    
114     getSymbols: function () {
115     var symbols = new SAMI.Hash;
116     this.rules.forEach (function (rule) {
117     rule.symbols.forEach (function (symbol) {
118     symbols.set (symbol.key, symbol);
119     });
120     });
121     return symbols;
122     }, // getSymbols
123    
124     getKey: function () {
125     return this.toString ();
126     }, // getKey
127    
128     toString: function () {
129     return this.rules.list.join ("\n");
130     } // toString
131     }); // RuleSet
132    
133     SAMI.PG.Collection = new SAMI.Class (function (ruleSets) {
134     this.ruleSets = new SAMI.List (ruleSets);
135     }, {
136     // ruleSets
137    
138     toString: function () {
139     return this.ruleSets.list.join ("\n\n");
140     } // toString
141     }); // Collection
142    
143     /* --- LR(1) Parser Generator --- */
144    
145     SAMI.PG.LR1 = new SAMI.Class (function () {
146    
147     }, {
148    
149     }); // LR1
150    
151     SAMI.Class.addClassMethods (SAMI.PG.LR1, {
152     ruleSetToParsingTable: function (ruleSet, startSymbolName) {
153     var col = new SAMI.PG.LR1.RuleSet ([]).getCanonCollection (startSymbolName, ruleSet);
154     return col.toParsingTable ();
155     }, // ruleSetToParsingTable
156     rulesStringToParsingTable: function (s, startSymbolName, onerror) {
157     var p = new SAMI.PG.LR1.RulesParser;
158    
159     new SAMI.Observer ('error', p, onerror || function (ev) {
160     outn ('Error: Unexpected token type {' + ev.token.type + ', ' + ev.token.value + '}; ' + ev.value);
161     });
162    
163     var ruleSet = p.parseString (s);
164     if (!ruleSet) return null;
165    
166     if (!startSymbolName && ruleSet.rules.list.length) {
167     startSymbolName = ruleSet.rules.list[0].symbolName;
168     }
169    
170     return this.ruleSetToParsingTable (ruleSet, startSymbolName);
171     } // rulesStringToParsingTable
172     }); // LR1 class methods
173    
174     SAMI.PG.LR1.Rule = new SAMI.Subclass (function (symbolName, symbols, index, firsts) {
175     this._super.apply (this, [symbolName, symbols]);
176     this.index = index;
177     this.firsts = new SAMI.List (firsts);
178     }, SAMI.PG.Rule, {
179     // index
180    
181     getNextSymbol: function () {
182     return this.symbols.list[this.index];
183     }, // getNextSymbol
184     getNextNextSymbol: function () {
185     return this.symbols.list[this.index + 1];
186     }, // getNextNextSymbol
187    
188     // firsts
189    
190     clone: function () {
191     var newRule = this._super.prototype.clone.apply (this, arguments);
192     newRule.index = this.index;
193     newRule.firsts = this.firsts.clone ();
194     return newRule;
195     }, // clone
196    
197     toString: function () {
198     var suffix = '';
199     if (this.firsts) {
200     suffix += ', ' + this.firsts.list.join (' / ');
201     }
202     if (this.index == null) { // Normal production rule
203     return this.symbolName + ' := ' + this.symbols.list.join (' ') + suffix;
204     } else { // Production rule with a pointer
205     return this.symbolName
206     + ' := ' + this.symbols.list.slice (0, this.index).join (' ')
207     + ' \u30FB ' + this.symbols.list.slice (this.index).join (' ')
208     + suffix;
209     }
210     } // toString
211     }); // LR1.Rule
212    
213     SAMI.PG.LR1.RuleSet = new SAMI.Subclass (function () {
214     this._super.apply (this, arguments);
215     this.rules = this.rules.map (function (rule) {
216     return rule instanceof SAMI.PG.LR1.Rule ? rule : new SAMI.PG.LR1.Rule (rule.symbolName, rule.symbols, 0);
217     });
218     this.goTo = new SAMI.Hash;
219     }, SAMI.PG.RuleSet, {
220     // ruleSetId
221    
222     getClosureLR0: function (ruleSet) {
223     var closureHash = new SAMI.Hash ();
224    
225     var rulesToBeAdded = this.rules.clone ();
226     while (rulesToBeAdded.list.length) {
227     var rule = rulesToBeAdded.shift ();
228     var ruleKey = rule.getKey ();
229     if (closureHash.has (ruleKey)) continue;
230     closureHash.set (ruleKey, rule);
231    
232     var nextSymbol = rule.getNextSymbol ();
233     if (nextSymbol) {
234     if (!nextSymbol.isTerminal) {
235     rulesToBeAdded.append (ruleSet.getRulesByName (nextSymbol.symbolName).rules.map (function (rule) {
236     return new SAMI.PG.LR1.Rule (rule.symbolName, rule.symbols, 0);
237     }));
238     }
239     }
240     }
241    
242     return new SAMI.PG.LR1.RuleSet (closureHash.mapToList (function (n, v) { return v }));
243     }, // getClosureLR0
244    
245    
246     getClosure: function (ruleSet) {
247     var closureHash = new SAMI.Hash ();
248    
249     var rulesToBeAdded = this.rules.clone ();
250     while (rulesToBeAdded.list.length) {
251     var rule = rulesToBeAdded.shift ();
252     var ruleKey = rule.getKey ();
253     if (closureHash.has (ruleKey)) continue;
254     closureHash.set (ruleKey, rule);
255    
256     var nextSymbol = rule.getNextSymbol ();
257     if (nextSymbol) {
258     if (!nextSymbol.isTerminal) {
259     var firsts;
260     var nextNextSymbol = rule.getNextNextSymbol ();
261     if (nextNextSymbol) {
262     firsts = nextNextSymbol.getFirsts (ruleSet) || rule.firsts;
263     } else {
264     firsts = rule.firsts;
265     }
266    
267     rulesToBeAdded.append (ruleSet.getRulesByName (nextSymbol.symbolName).rules.map (function (rule) {
268     return new SAMI.PG.LR1.Rule (rule.symbolName, rule.symbols, 0, firsts);
269     }));
270     }
271     }
272     }
273    
274     return new SAMI.PG.LR1.RuleSet (closureHash.mapToList (function (n, v) { return v }));
275     }, // getClosure
276    
277     // goTo
278     getGoTo: function (symbol, allRuleSet) {
279     var reduction = false;
280     var goTo = new this.constructor (this.rules.grep (function (rule) {
281     if (rule.index == rule.symbols.list.length) reduction = true;
282     return symbol.isSameSymbol (rule.getNextSymbol ());
283     }).map (function (rule) {
284     var newRule = rule.clone ();
285     newRule.index++;
286     return newRule;
287     })).getClosure (allRuleSet);
288     return goTo;
289     }, // getGoTo
290    
291     toParsingTableRow: function () {
292     var hash = new SAMI.Parser.LR1.ParsingTableRow;
293     this.goTo.forEach (function (n, v) {
294     var sk = v.symbolKey;
295     if (sk != null) sk = sk.replace (/^nonterminal-/, '');
296     hash.set (n.replace (/^nonterminal-/, ''),
297     new SAMI.Parser.LR1.ParsingTableCell (v.isReduction, sk, v.symbolsLength, v.ruleSetId));
298     });
299     return hash;
300     }, // toParsingTableEntry
301    
302     getCanonCollection: function (startSymbolName, allRuleSet) {
303     var startRule = new SAMI.PG.LR1.Rule ('$start', [new SAMI.PG.NonTerminalSymbol (startSymbolName)], 0, ['EOF']);
304     var startRuleSet = new SAMI.PG.LR1.RuleSet ([startRule]);
305     this.rules.push (startRule);
306    
307     var endRule = startRule.clone ();
308     endRule.index = endRule.symbols.list.length;
309     var endRuleSet = new SAMI.PG.LR1.RuleSet ([endRule]);
310     this.rules.push (endRule);
311    
312     var startClosure = startRuleSet.getClosure (allRuleSet);
313     startClosure.ruleSetId = 0;
314     var endClosure = endRuleSet.getClosure (allRuleSet);
315     endClosure.ruleSetId = 1;
316     var errorClosure = new SAMI.PG.LR1.RuleSet;
317     errorClosure.ruleSetId = 2;
318    
319     var closures = [startClosure, endClosure, errorClosure];
320     var closureToId = {};
321     closureToId[startClosure.getKey ()] = 0;
322     closureToId[endClosure.getKey ()] = 1;
323     closureToId[errorClosure.getKey ()] = 2;
324    
325     var symbols = allRuleSet.getSymbols ();
326     symbols.set (startRule.symbols.list[0].key, startRule.symbols.list[0]);
327    
328     var i = 0;
329     while (i < closures.length) {
330     var currentClosure = closures[i];
331    
332     symbols.forEach (function (symbolKey, symbol) {
333     var goTo = currentClosure.getGoTo (symbol, allRuleSet);
334     if (goTo) {
335     var goToKey = goTo.getKey ();
336     if (closureToId[goToKey] == null) {
337     goTo.ruleSetId = closures.length;
338     closureToId[goToKey] = goTo.ruleSetId;
339     closures.push (goTo);
340     }
341     }
342    
343     if (goTo) {
344     var id = closureToId[goTo.getKey ()];
345     if (id != 2 /* error */) {
346     currentClosure.goTo.set (symbol.key, new SAMI.PG.LR1.GoToRuleSet (id));
347     }
348     }
349     });
350    
351     currentClosure.rules.forEach (function (rule) {
352     if (rule.symbols.list.length == rule.index) {
353     rule.firsts.forEach (function (firstSymbol) {
354     currentClosure.goTo.set
355     (/* 'terminal-' + */ firstSymbol,
356     new SAMI.PG.LR1.GoToReduction ('nonterminal-' + rule.symbolName, rule.symbols.list.length));
357     });
358     }
359     });
360    
361     i++;
362     }
363    
364     this.rules.pop (); // end
365     this.rules.pop (); // start
366    
367     return new SAMI.PG.LR1.Collection (closures);
368     }, // getCanonCollection
369    
370     getKey: function () {
371     return this._super.prototype.toString.apply (this, []);
372     }, // getKey
373    
374     toString: function () {
375     return this.ruleSetId + ":\n"
376     + this._super.prototype.toString.apply (this, []) + "\n"
377     + this.goTo.mapToList (function (n, v) { return n + ' -> ' + v }).list.join ("\n");
378     } // toString
379     }); // LR1.RuleSet
380    
381     SAMI.PG.LR1.Collection = new SAMI.Subclass (function () {
382     this._super.apply (this, arguments);
383     }, SAMI.PG.Collection, {
384     toParsingTable: function () {
385     var index = 0;
386     return new SAMI.Parser.LR1.ParsingTable (this.ruleSets.map (function (ruleSet) {
387     var row = ruleSet.toParsingTableRow ();
388     row.index = index++;
389     return row;
390     }).list);
391     } // toParsingTable
392     }); // Collection
393    
394     SAMI.PG.LR1.GoToEntry = new SAMI.Class (function () {
395    
396     }, {
397     isReduction: false
398     }); // GoToEntry
399    
400     SAMI.PG.LR1.GoToRuleSet = new SAMI.Subclass (function (id) {
401     this.ruleSetId = id;
402     }, SAMI.PG.LR1.GoToEntry, {
403     // ruleSetId
404    
405     toString: function () {
406     return "goto #" + this.ruleSetId;
407     } // toString
408     }); // GoToRuleSet
409    
410     SAMI.PG.LR1.GoToReduction = new SAMI.Subclass (function (symbolKey, symbolsLength) {
411     this.symbolKey = symbolKey;
412     this.symbolsLength = symbolsLength;
413     }, SAMI.PG.LR1.GoToEntry, {
414     isReduction: true,
415    
416     // symbolKey, symbolsLength
417    
418     toString: function () {
419     return "reduction " + this.symbolsLength + ' -> ' + this.symbolKey;
420     } // toString
421     }); // GoToReduction
422    
423    
424     SAMI.PG.LR1.RulesParser = new SAMI.Subclass (function () {
425    
426     }, SAMI.Parser.LR1, {
427     _patterns: new SAMI.List ([
428     {pattern: /[\w_-]+/, type: 'non-terminal-symbol', code: function (t, v) { t.value = v }},
429     {
430     pattern: /'(?:[^\u0027\\]|\\[\s\S])+'|"(?:[^\u0022\\]|\\[\s\S])+"/,
431     type: 'terminal-symbol',
432     code: function (t, v) {
433     t.value = v.replace (/^./, '').replace (/.$/, '').replace (/\\(.)/g, function (_, v) { return v });
434     }
435     },
436     {pattern: /\s+/, ignore: true},
437     {pattern: /:=/}
438     ]), // _patterns
439    
440     _processLR1StackObjects: function (key, objs) {
441     if (key == 'symbol') {
442     var t = objs.list[0];
443     var v;
444     if (t.type == 'non-terminal-symbol') {
445     v = new SAMI.PG.NonTerminalSymbol (t.value);
446     } else { // terminal-symbol
447     v = new SAMI.PG.TerminalSymbol (t.value);
448     }
449     return {type: key, value: v};
450     } else if (key == 'righthand') {
451     if (objs.list.length == 2) {
452     var v = objs.list[0];
453     v.value.push (objs.list[1].value);
454     return v;
455     } else {
456     return {type: key, value: new SAMI.List ([objs.list[0].value])};
457     }
458     } else if (key == 'expression') {
459     return {type: key, value: new SAMI.PG.Rule (objs.list[0].value, objs.list[2].value)};
460     } else if (key == 'rules') {
461     if (objs.list.length == 2) {
462     var v = objs.list[0].value;
463     v.rules.push (objs.list[1].value);
464     return {type: key, value: v};
465     } else {
466     return {type: key, value: new SAMI.PG.RuleSet ([objs.list[0].value])};
467     }
468     }
469     return {type: key, value: key + '{ ' + objs.map (function (s) { return s.type + ',' + s.value }).list.join (', ') + ' }'};
470     }, // _processLR1StackObjects
471    
472     _parsingTable:
473     /* Parsing Table */
474     new SAMI.Parser.LR1.ParsingTable ([
475     new SAMI.Parser.LR1.ParsingTableRow ({
476     "rules": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 3),
477     "expression": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 4),
478     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 5)
479     }).setIndex (0),
480     new SAMI.Parser.LR1.ParsingTableRow ({
481     "EOF": new SAMI.Parser.LR1.ParsingTableCell (true, "$start", 1)
482     }).setIndex (1),
483     new SAMI.Parser.LR1.ParsingTableRow ({
484    
485     }).setIndex (2),
486     new SAMI.Parser.LR1.ParsingTableRow ({
487     "expression": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 6),
488     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 5),
489     "EOF": new SAMI.Parser.LR1.ParsingTableCell (true, "$start", 1)
490     }).setIndex (3),
491     new SAMI.Parser.LR1.ParsingTableRow ({
492     "EOF": new SAMI.Parser.LR1.ParsingTableCell (true, "rules", 1),
493     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "rules", 1)
494     }).setIndex (4),
495     new SAMI.Parser.LR1.ParsingTableRow ({
496     ":=": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 7)
497     }).setIndex (5),
498     new SAMI.Parser.LR1.ParsingTableRow ({
499     "EOF": new SAMI.Parser.LR1.ParsingTableCell (true, "rules", 2),
500     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "rules", 2)
501     }).setIndex (6),
502     new SAMI.Parser.LR1.ParsingTableRow ({
503     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 8),
504     "righthand": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 9),
505     "symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 10),
506     "terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 11)
507     }).setIndex (7),
508     new SAMI.Parser.LR1.ParsingTableRow ({
509     ";": new SAMI.Parser.LR1.ParsingTableCell (true, "symbol", 1),
510     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "symbol", 1),
511     "terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "symbol", 1)
512     }).setIndex (8),
513     new SAMI.Parser.LR1.ParsingTableRow ({
514     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 8),
515     ";": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 12),
516     "symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 13),
517     "terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (false, undefined, undefined, 11)
518     }).setIndex (9),
519     new SAMI.Parser.LR1.ParsingTableRow ({
520     ";": new SAMI.Parser.LR1.ParsingTableCell (true, "righthand", 1),
521     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "righthand", 1),
522     "terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "righthand", 1)
523     }).setIndex (10),
524     new SAMI.Parser.LR1.ParsingTableRow ({
525     ";": new SAMI.Parser.LR1.ParsingTableCell (true, "symbol", 1),
526     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "symbol", 1),
527     "terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "symbol", 1)
528     }).setIndex (11),
529     new SAMI.Parser.LR1.ParsingTableRow ({
530     "EOF": new SAMI.Parser.LR1.ParsingTableCell (true, "expression", 4),
531     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "expression", 4)
532     }).setIndex (12),
533     new SAMI.Parser.LR1.ParsingTableRow ({
534     ";": new SAMI.Parser.LR1.ParsingTableCell (true, "righthand", 2),
535     "non-terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "righthand", 2),
536     "terminal-symbol": new SAMI.Parser.LR1.ParsingTableCell (true, "righthand", 2)
537     }).setIndex (13)
538     ])
539     ,/* Parsing Table */
540    
541     parseString: function (s) {
542     var tokens = this.tokenizeString (s);
543     var result = this._parseTokens (tokens);
544     return result != null ? result.value : null;
545     } // parseString
546     }); // RulesParser
547     SAMI.Class.mix (SAMI.PG.LR1.RulesParser, SAMI.Parser.SimpleTokenizer);
548    
549     /* --- Onload --- */
550    
551     if (SAMI.PG.onLoadFunctions) {
552     new SAMI.List (SAMI.PG.onLoadFunctions).forEach (function (code) {
553     code ();
554     });
555     delete SAMI.PG.onLoadFunctions;
556     }
557    
558     /* ***** BEGIN LICENSE BLOCK *****
559     * Copyright 2009 Wakaba <[email protected]>. All rights reserved.
560     *
561     * This program is free software; you can redistribute it and/or
562     * modify it under the same terms as Perl itself.
563     *
564     * Alternatively, the contents of this file may be used
565     * under the following terms (the "MPL/GPL/LGPL"),
566     * in which case the provisions of the MPL/GPL/LGPL are applicable instead
567     * of those above. If you wish to allow use of your version of this file only
568     * under the terms of the MPL/GPL/LGPL, and not to allow others to
569     * use your version of this file under the terms of the Perl, indicate your
570     * decision by deleting the provisions above and replace them with the notice
571     * and other provisions required by the MPL/GPL/LGPL. If you do not delete
572     * the provisions above, a recipient may use your version of this file under
573     * the terms of any one of the Perl or the MPL/GPL/LGPL.
574     *
575     * "MPL/GPL/LGPL":
576     *
577     * Version: MPL 1.1/GPL 2.0/LGPL 2.1
578     *
579     * The contents of this file are subject to the Mozilla Public License Version
580     * 1.1 (the "License"); you may not use this file except in compliance with
581     * the License. You may obtain a copy of the License at
582     * <http://www.mozilla.org/MPL/>
583     *
584     * Software distributed under the License is distributed on an "AS IS" basis,
585     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
586     * for the specific language governing rights and limitations under the
587     * License.
588     *
589     * The Original Code is sami-pg.js code.
590     *
591     * The Initial Developer of the Original Code is Wakaba.
592     * Portions created by the Initial Developer are Copyright (C) 2009
593     * the Initial Developer. All Rights Reserved.
594     *
595     * Contributor(s):
596     * Wakaba <[email protected]>
597     *
598     * Alternatively, the contents of this file may be used under the terms of
599     * either the GNU General Public License Version 2 or later (the "GPL"), or
600     * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
601     * in which case the provisions of the GPL or the LGPL are applicable instead
602     * of those above. If you wish to allow use of your version of this file only
603     * under the terms of either the GPL or the LGPL, and not to allow others to
604     * use your version of this file under the terms of the MPL, indicate your
605     * decision by deleting the provisions above and replace them with the notice
606     * and other provisions required by the LGPL or the GPL. If you do not delete
607     * the provisions above, a recipient may use your version of this file under
608     * the terms of any one of the MPL, the GPL or the LGPL.
609     *
610     * ***** END LICENSE BLOCK ***** */
611    

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24