source: applications/nimpad/branches/0.2/lib/HatenaSyntax/Locator.php @ 1488

SVN
Revision 1488, 9.8 KB checked in by anatoo, 10 months ago (diff)

HatenaSyntax?とPEGをリポジトリの中に置いておくようにした

Line 
1<?php
2/**
3 * @package HatenaSyntax
4 * @author anatoo<anatoo@nequal.jp>
5 * @license http://www.opensource.org/licenses/mit-license.php MIT License
6 * @version $Id: Locator.php 1159 2009-09-06 09:43:29Z anatoo $
7 */
8
9class HatenaSyntax_Locator
10{
11    protected $elt_ref = null;
12    protected $objects = array();
13   
14    private function __construct()
15    {
16        $this->setup();
17    }
18   
19    static function it()
20    {
21        static $obj = null;
22        return $obj ? $obj : $obj = new self;
23    }
24   
25    public function __get($name)
26    {
27        return isset($this->objects[$name]) ? 
28            $this->objects[$name] : 
29            $this->objects[$name] = $this->{'create' . $name}();
30    }
31   
32    protected function createFactory()
33    {
34        return new HatenaSyntax_Factory($this);
35    }
36   
37    protected function createLineChar()
38    {
39        return PEG::second(PEG::not(PEG::char("\n\r")), PEG::anything());
40    }
41   
42    protected function createEndOfLine()
43    {
44        return PEG::choice(PEG::newLine(), PEG::eos());
45    }
46   
47    protected function createFootnote()
48    {
49        $close = '))';
50        $elt = PEG::andalso(PEG::not($close), 
51                            PEG::choice($this->bracket, $this->lineChar));
52                           
53        $parser = PEG::pack('((', 
54                            HatenaSyntax_Util::segment(PEG::many1($elt)), 
55                            $close);
56                           
57        return $this->factory->createNodeCreater('footnote', $parser);
58    }
59   
60    protected function createLineElement()
61    {
62        return $this->factory->createLineElement();
63    }
64   
65    protected function createLineSegment()
66    {
67        return HatenaSyntax_Util::segment(PEG::many($this->lineElement));
68    }
69   
70    protected function createHttpLink()
71    {
72        $title_char = PEG::andalso(PEG::not(']'), 
73                                   $this->lineChar);
74       
75        $title = PEG::second(':title=', PEG::join(PEG::many1($title_char)));
76       
77        $url_char = PEG::andalso(PEG::not(PEG::choice(']', ':title=')), 
78                                 $this->lineChar);
79                                 
80        $url = PEG::join(PEG::seq(PEG::choice('http://', 'https://'), 
81                                  PEG::many1($url_char)));
82        $parser = PEG::seq($url, PEG::optional($title));
83       
84        return $this->factory->createNodeCreater('httplink', $parser, array('href', 'title'));
85    }
86   
87    protected function createImageLink()
88    {
89        $url_char = PEG::subtract(PEG::anything(), ']', ':image]');
90       
91        $url = PEG::join(PEG::seq(PEG::choice('http://', 'https://'),
92                                  PEG::many1($url_char)));
93                                 
94        $parser = PEG::first($url, ':image');
95       
96        return $this->factory->createNodeCreater('imagelink', $parser);
97    }
98   
99    protected function createKeywordLink()
100    {
101        $body = PEG::join(PEG::many1(PEG::subtract(PEG::anything(), PEG::newLine(), ']]')));
102        $body = PEG::subtract($body, 'javascript:', ' ', "\t");
103        $parser = PEG::pack('[', $body, ']');
104       
105        return $this->factory->createNodeCreater('keywordlink', $parser);
106    }
107   
108    protected function createNullLink()
109    {
110        $body = PEG::join(PEG::many1(PEG::subtract(PEG::anything(), '[]', PEG::newLine())));
111        $parser = PEG::pack(']', $body, '[');
112       
113        return $parser;
114    }
115   
116    protected function createTableOfContents()
117    {
118        $parser = PEG::seq(PEG::token('[:contents]'), $this->endOfLine);
119       
120        return $this->factory->createNodeCreater('tableofcontents', $parser);
121    }
122   
123    protected function createInlineTableOfContents()
124    {
125        $parser = PEG::token(':contents');
126        return $this->factory->createNodeCreater('tableofcontents', $parser);
127    }
128   
129    protected function createBracket()
130    {
131        return PEG::pack('[', PEG::choice($this->inlineTableOfContents, $this->nullLink, $this->keywordLink, $this->imageLink, $this->httpLink), ']');
132    }
133   
134    protected function createDefinition()
135    {
136        $c = PEG::token(':');
137        $sep = PEG::drop($c);
138        $factory = $this->factory;
139        $parser = PEG::seq($sep, 
140                           $factory->createLineSegment($c, true), 
141                           $sep, 
142                           $factory->createLineSegment($c), 
143                           PEG::drop($this->endOfLine));
144        return $parser;
145    }
146   
147    protected function createDefinitionList()
148    {
149        $parser = PEG::many1($this->definition);
150        return $this->factory->createNodeCreater('definitionlist', $parser);
151    }
152   
153    protected function createPre()
154    {
155        $nl = PEG::newLine();
156        $closing = PEG::seq(PEG::optional($nl), '|<', $this->endOfLine);
157        $line = PEG::second($nl, $this->factory->createLineSegment($closing));
158        $parser = PEG::pack('>|', PEG::many1($line), $closing);
159       
160        return $this->factory->createNodeCreater('pre', $parser);
161    }
162   
163    protected function createSuperPreElement()
164    {
165        $cond = PEG::not(PEG::seq('||<', $this->endOfLine));
166        $elt = PEG::second($cond, $this->lineChar);
167        $parser = PEG::third(PEG::newLine(), $cond, PEG::join(PEG::many($elt)));
168       
169        return $parser;
170       
171    }
172   
173    protected function createHeader()
174    {
175        $parser = PEG::seq(PEG::drop('*'),
176                           PEG::count(PEG::many('*')),
177                           HatenaSyntax_Util::segment(PEG::many(PEG::choice($this->lineChar, $this->footnote))),
178                           PEG::drop($this->endOfLine));
179       
180        return $this->factory->createNodeCreater('header', $parser, array('level', 'body'));
181    }
182
183    protected function createSuperPre()
184    {
185        $open = PEG::pack('>|', 
186                          PEG::join(PEG::many(PEG::secondSeq(PEG::lookaheadNot(PEG::char("\r\n|")), PEG::anything()))),
187                          '|');
188        $body = PEG::many1($this->superPreElement);
189       
190        $close = PEG::drop(PEG::optional(PEG::newLine()),
191                           '||<',
192                           $this->endOfLine);
193       
194        $parser = PEG::seq($open, $body, $close);
195       
196        return $this->factory->createNodeCreater('superpre', $parser, array('type', 'body'));
197    }
198
199    protected function createList()
200    {
201        $item = PEG::callbackAction(array('HatenaSyntax_Util', 'processListItem'), PEG::many1(PEG::char('-+')),
202                                                                                   $this->lineSegment,
203                                                                                   PEG::drop($this->endOfLine));
204        $list = PEG::callbackAction(array('HatenaSyntax_Util', 'normalizeList'), PEG::many1($item));
205       
206        return $this->factory->createNodeCreater('list', $list);
207    }
208
209    protected function createTableCell()
210    {
211        $parser = PEG::seq(PEG::drop('|', PEG::lookaheadNot($this->endOfLine)),
212                           PEG::optional('*'),
213                           $this->factory->createLineSegment(PEG::token('|'), true));
214        return $parser;
215    }
216   
217    protected function createTable()
218    {
219        $line = PEG::first(PEG::many1($this->tableCell), 
220                           '|', 
221                           $this->endOfLine);
222        $parser = PEG::many1($line);
223       
224        return $this->factory->createNodeCreater('table', $parser);
225    }
226
227    protected function createBlockQuote()
228    {
229        $url = PEG::join(PEG::seq(PEG::choice('http://', 'https://'), 
230                                  PEG::many1(PEG::subtract(PEG::anything(), 
231                                                           PEG::seq('>', PEG::newLine()), 
232                                                           PEG::newLine()))));
233       
234        $header = PEG::pack('>', PEG::optional($url), PEG::seq('>', PEG::newLine()));
235       
236        $elt = PEG::second(PEG::not('<<', $this->endOfLine), $this->element);
237       
238        $parser = PEG::seq($header, PEG::many1($elt), PEG::drop('<<', $this->endOfLine));
239                                     
240        return $this->factory->createNodeCreater('blockquote', $parser, array('url', 'body'));
241    }
242   
243    protected function createParagraph()
244    {
245        $parser = PEG::first($this->lineSegment, $this->endOfLine); 
246       
247        return $this->factory->createNodeCreater('paragraph', $parser);
248    }
249   
250    protected function createEmptyParagraph()
251    {
252        $parser = PEG::count(PEG::many1(PEG::newLine()));
253        return $this->factory->createNodeCreater('emptyparagraph', $parser);
254    }
255   
256    protected function createElement()
257    {
258        $parser = PEG::ref($ref);
259        $this->elt_ref = &$ref;
260        return $parser;
261    }
262
263    protected function createParser()
264    {
265        return $this->factory->createNodeCreater('root', PEG::many($this->element));
266    }
267   
268    protected function setup()
269    {
270        $this->element;
271        $this->elt_ref = PEG::memo(PEG::choice($this->header,
272                                               $this->blockQuote,
273                                               $this->definitionList,
274                                               $this->table,
275                                               $this->list,
276                                               $this->pre,
277                                               $this->superpre,
278                                               $this->tableOfContents,
279                                               $this->emptyParagraph,
280                                               $this->paragraph));
281    }
282}
Note: See TracBrowser for help on using the repository browser.