Overview

Namespaces

  • None
  • Peg
    • Cli
      • Commands
    • Config
    • Custom
      • Command
        • Action
          • Generate
          • Parse
      • CommandLine
      • Config
      • Localization
      • Utilities
    • Lib
      • Definitions
        • Element
      • Generator
      • Lexers
      • Plugins
      • Signals
        • Data
          • Definitions
          • Lexers
        • Type
  • PHP

Classes

  • Base
  • ZendPHP
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
  1: <?php
  2: /**
  3:  * @author Jefferson González
  4:  * @license MIT
  5:  * @link http://github.com/peg-org/peg-src Source code.
  6:  */
  7: 
  8: namespace Peg\Lib\Generator;
  9: 
 10: /**
 11:  * Base class to implement a source code generator.
 12:  */
 13: abstract class Base
 14: {
 15: 
 16:     /**
 17:      * Reference to the symbols object with all definitions required 
 18:      * to generate the code.
 19:      * @var \Peg\Lib\Definitions\Symbols 
 20:      */
 21:     public $symbols;
 22:     
 23:     /**
 24:      * Path where template files reside.
 25:      * @var string
 26:      */
 27:     public $templates_path;
 28:     
 29:     /**
 30:      * Path where the generated source code is going to be saved.
 31:      * @var string 
 32:      */
 33:     public $output_path;
 34:     
 35:     /**
 36:      * Name of the generator implementing this base class. Useful to determine
 37:      * the directory where generated source code is going to be stored.
 38:      * @var string
 39:      */
 40:     public $generator_name;
 41:     
 42:     /**
 43:      * The symbols object with all definitions required to generate the code.
 44:      * @param string $templates Path where template files reside.
 45:      * @param string $output Path where the generated source code is going to be saved.
 46:      * @param string $generator_name Name of the generator being instantiated.
 47:      * Should be all lower case.
 48:      * @param \Peg\Lib\Definitions\Symbols $symbols
 49:      */
 50:     public function __construct(
 51:         $templates,
 52:         $output,
 53:         $generator_name,
 54:         \Peg\Lib\Definitions\Symbols &$symbols
 55:     )
 56:     {
 57:         $this->symbols =& $symbols;
 58:         $this->templates_path = rtrim($templates, "\\/") . "/";
 59:         $this->output_path = rtrim($output, "\\/") . "/";
 60:         $this->generator_name = $generator_name;
 61:         
 62:         // Strip generator name if passed by user since it should be
 63:         // appended automatically by this constructor.
 64:         $this->output_path = str_replace(
 65:             "/$generator_name/", 
 66:             "/", 
 67:             $this->output_path
 68:         ) . $generator_name . "/";
 69:         
 70:         $this->templates_path = str_replace(
 71:             "/$generator_name/", 
 72:             "/", 
 73:             $this->templates_path
 74:         ) . $generator_name . "/";
 75:     }
 76:     
 77:     /**
 78:      * Useful to indent the output of a template.
 79:      * @param string $code Output code of template.
 80:      * @param int $spaces Amount of spaces to indent the code.
 81:      * @return string Code indented.
 82:      */
 83:     public function Indent($code, $spaces)
 84:     {
 85:         $indent = "";
 86:         
 87:         for($i=0; $i<$spaces; $i++)
 88:         {
 89:             $indent .= " ";
 90:         }
 91:         
 92:         if(substr_count($code, "\n") <= 1)
 93:             return $indent . $code;
 94:         
 95:         $code = str_replace("\n", "\n$indent", $code);
 96:         
 97:         return $code;
 98:     }
 99:     
100:     /**
101:      * Converts a header file name into a suitable flag for the compiler 
102:      * pre-processor. Eg: header.h -> PHP_HEADER_H this can be used for
103:      * #ifndef checks on the generated code to prevent double inclusions.
104:      * @param string $name
105:      */
106:     public function GetHeaderDefine($name)
107:     {
108:         return "PHP_" . strtoupper(
109:             str_replace(
110:                 array("/", ".", "-"), 
111:                 "_", 
112:                 $name
113:             )
114:         );
115:     }
116:     
117:     /**
118:      * Converts a header filename into one that doesn't conflicts with
119:      * original which can be used to store the generated code. Eg:
120:      * header.h -> php_header.h or lib/header.h -> php_lib_header.h
121:      * @param string $name
122:      */
123:     public function GetHeaderNamePHP($name)
124:     {
125:         return "php_" . strtolower(
126:             str_replace(
127:                 array("/", "-"), 
128:                 "_", 
129:                 $name
130:             )
131:         );
132:     }
133:     
134:     /**
135:      * Converts a header filename into a source file name which can be used 
136:      * to store the generated code. 
137:      * Eg: header.h -> php_header.cpp or lib/header.h -> php_lib_header.cpp
138:      * @param string $name
139:      */
140:     public function GetSourceNamePHP($name)
141:     {
142:         return str_replace(
143:             ".h", 
144:             ".cpp", 
145:             $this->GetHeaderNamePHP($name)
146:         );
147:     }
148:     
149:     /**
150:      * Gets a list of custom source files on the custom_sources directory
151:      * that resides in the templates/$generator_name directory with the .php
152:      * extension stripped out.
153:      */
154:     public function GetCustomSources()
155:     {
156:         $sources = scandir($this->templates_path . "custom_sources");
157:         
158:         foreach($sources as $index=>$source)
159:         {
160:             // Skip non .php files
161:             if(strpos($source, ".php") === false)
162:             {
163:                 unset($sources[$index]);
164:                 continue;
165:             }
166:             
167:             $sources[$index] = str_replace(".php", "", $source);
168:         }
169:         
170:         return $sources;
171:     }
172:     
173:     /**
174:      * Get a php template file path based on the given parameters.
175:      * @param string $name Name of element.
176:      * @param string $type Main type of template.
177:      * @param string $subtype Subtype of template.
178:      * @param string $dir Relative dir to templates path where template resides.
179:      * @param string $overrides_prefix In case $dir is shared with other template types.
180:      * @param string $namespace Namespace of the $name element.
181:      * @return string
182:      */
183:     public function GetTemplatePath(
184:         $name, $type, $subtype, $dir, $overrides_prefix="", $namespace=""
185:     )
186:     {   
187:         if($namespace)
188:         {
189:             $namespace = strtolower(
190:                 str_replace(
191:                     array("\\", "::"),
192:                     "_",
193:                     $namespace
194:                 )
195:             ) . "_";
196:         }
197:         
198:         if($overrides_prefix)
199:         {
200:             $overrides_prefix = rtrim($overrides_prefix, "_") . "_";
201:         }
202: 
203:         $override = $this->templates_path
204:             . "{$dir}/{$overrides_prefix}overrides/"
205:             . "{$subtype}_" . $namespace . strtolower(
206:                 str_replace(
207:                     array("/", "-", "."),
208:                     "_",
209:                     $name
210:                 )
211:             )
212:             . ".php"
213:         ;
214: 
215:         if(file_exists($override))
216:         {
217:             return $override;
218:         }
219:         
220:         if($type)
221:             $type .= "_";
222: 
223:         return $this->templates_path
224:             . "{$dir}/"
225:             . "{$type}{$subtype}.php"
226:         ;
227:     }
228:     
229:     /**
230:      * Get a php template file for a given file name.
231:      * @param string $name Filename of source file, eg: php_extension.h, config.m4
232:      * @param string $subdir Relative path to the templates_path where the file resides.
233:      * @return string Path to template file.
234:      */
235:     public function GetGenericTemplate($name, $subdir="")
236:     {
237:         if($subdir)
238:             $subdir = trim($subdir, "\\/") . "/";
239:         
240:         return $this->templates_path
241:             . $subdir
242:             . "{$name}.php"
243:         ;
244:     }
245:     
246:     /**
247:      * Retrieve the template path for parameters, also checks
248:      * if a valid override exists and returns that instead.
249:      * @param string $parameter Name of the function.
250:      * @param string $namespace
251:      * @param string $type Can be declare, parse_string, parse, 
252:      * parse_string_ref, parse_reference or object_validate.
253:      * @return string Path to template file.
254:      */
255:     public function GetParameterTemplate(
256:         \Peg\Lib\Definitions\Element\Parameter $parameter,
257:         $namespace="",
258:         $type="declare"
259:     )
260:     {
261:         if(!$this->generator_name)
262:         {
263:             throw new \Exception(t("The generator name wasn't set."));
264:         }
265:         
266:         if($namespace)
267:         {
268:             $namespace = str_replace(
269:                 array("\\", "::"),
270:                 "_",
271:                 $namespace
272:             ) . "_";
273:         }
274: 
275:         $function_name = strtolower($parameter->overload->function->name);
276: 
277:         $parameter_type = strtolower($parameter->type);
278: 
279:         $const = "";
280:         if($parameter->is_const)
281:         {
282:             $const .= "_const";
283:         }
284: 
285:         $ptr = "";
286:         if($parameter->is_pointer)
287:         {
288:             for($i=0; $i<$parameter->indirection_level; $i++)
289:             {
290:                 $ptr .= "_ptr";
291:             }
292:         }
293: 
294:         $ref = "";
295:         if($parameter->is_reference)
296:         {
297:             $ref .= "_ref";
298:         }
299: 
300:         $array = "";
301:         if($parameter->is_array)
302:         {
303:             $array .= "_arr";
304:         }
305: 
306:         $override_function = $this->templates_path
307:             . "parameters/{$type}/overrides/"
308:             . $function_name . "_" . $parameter_type
309:             . $const
310:             . $ptr
311:             . $ref
312:             . $array
313:             . ".php"
314:         ;
315: 
316:         if(file_exists($override_function))
317:         {
318:             return $override_function;
319:         }
320: 
321:         $override = $this->templates_path
322:             . "parameters/{$type}/overrides/"
323:             . $parameter_type
324:             . $const
325:             . $ptr
326:             . $ref
327:             . $array
328:             . ".php"
329:         ;
330: 
331:         if(file_exists($override))
332:         {
333:             return $override;
334:         }
335: 
336:         $standard_type = $this->symbols->GetStandardType($parameter);
337: 
338:         $template = $this->templates_path
339:             . "parameters/{$type}/"
340:             . $standard_type
341:             . $const
342:             . $ptr
343:             . $ref
344:             . $array
345:             . ".php"
346:         ;
347: 
348:         if(!file_exists($template))
349:         {
350:             return $this->templates_path
351:                 . "parameters/{$type}/"
352:                 . "default.php"
353:             ;
354:         }
355: 
356:         return $template;
357:     }
358:     
359:     /**
360:      * Retrieve the template path for return, also checks
361:      * if a valid override exists and returns that instead.
362:      * @param string $return Name of the function.
363:      * @param string $namespace
364:      * @param string $type Can be function, method or static_method.
365:      * @return string Path to template file.
366:      */
367:     public function GetReturnTemplate(
368:         \Peg\Lib\Definitions\Element\ReturnType $return,
369:         $namespace="",
370:         $type="function"
371:     )
372:     {
373:         if(!$this->generator_name)
374:         {
375:             throw new \Exception(t("The generator name wasn't set."));
376:         }
377:         
378:         if($namespace)
379:         {
380:             $namespace = str_replace(
381:                 array("\\", "::"),
382:                 "_",
383:                 $namespace
384:             ) . "_";
385:         }
386: 
387:         $function_name = strtolower($return->overload->function->name);
388: 
389:         $return_type = strtolower($return->type);
390: 
391:         $const = "";
392:         if($return->is_const)
393:         {
394:             $const .= "_const";
395:         }
396: 
397:         $ptr = "";
398:         if($return->is_pointer)
399:         {
400:             for($i=0; $i<$return->indirection_level; $i++)
401:             {
402:                 $ptr .= "_ptr";
403:             }
404:         }
405: 
406:         $ref = "";
407:         if($return->is_reference)
408:         {
409:             $ref .= "_ref";
410:         }
411: 
412:         $array = "";
413:         if($return->is_array)
414:         {
415:             $array .= "_arr";
416:         }
417: 
418:         $override_function = $this->templates_path
419:             . "return/{$type}/overrides/"
420:             . $function_name . "_" . $return_type
421:             . $const
422:             . $ptr
423:             . $ref
424:             . $array
425:             . ".php"
426:         ;
427: 
428:         if(file_exists($override_function))
429:         {
430:             return $override_function;
431:         }
432: 
433:         $override = $this->templates_path
434:             . "return/{$type}/overrides/"
435:             . $return_type
436:             . $const
437:             . $ptr
438:             . $ref
439:             . $array
440:             . ".php"
441:         ;
442: 
443:         if(file_exists($override))
444:         {
445:             return $override;
446:         }
447: 
448:         $standard_type = $this->symbols->GetStandardType($return);
449: 
450:         $template = $this->templates_path
451:             . "return/{$type}/"
452:             . $standard_type
453:             . $const
454:             . $ptr
455:             . $ref
456:             . $array
457:             . ".php"
458:         ;
459: 
460:         if(!file_exists($template))
461:         {
462:             return $this->templates_path
463:                 . "return/{$type}/"
464:                 . "default.php"
465:             ;
466:         }
467: 
468:         return $template;
469:     }
470:     
471:     /**
472:      * Deletes a generated header declarations file and its source file
473:      * @param string $header_name Original name of header.
474:      */
475:     public function RemoveHeader($header_name)
476:     {
477:         $header = $this->output_path 
478:             . "includes/" 
479:             . $this->GetHeaderNamePHP($header_name)
480:         ;
481:         
482:         $source = $this->output_path 
483:             . "src/" 
484:             . $this->GetSourceNamePHP($header_name)
485:         ;
486:         
487:         if(file_exists($header))
488:             unlink($header);
489:         
490:         if(file_exists($source))
491:             unlink($source);
492:     }
493:     
494:     /**
495:      * Adds or updates a header file if neccessary.
496:      * @param string $header_name Original name of header.
497:      * @param string $content
498:      * @param string $subdir
499:      */
500:     public function AddHeader($header_name, &$content, $subdir="includes")
501:     {
502:         if($subdir)
503:         {
504:             $subdir = trim($subdir, "\\/") . "/";
505:             
506:             if(!file_exists($this->output_path . $subdir))
507:                 \Peg\Lib\Utilities\FileSystem::MakeDir(
508:                     $this->output_path . $subdir, 
509:                     0755, 
510:                     true
511:                 );
512:         }
513:         
514:         $header = $this->output_path 
515:             . $subdir
516:             . $this->GetHeaderNamePHP($header_name)
517:         ;
518:         
519:         \Peg\Lib\Utilities\FileSystem::WriteFileIfDifferent($header, $content);
520:     }
521:     
522:     /**
523:      * Adds or updates a header source file if neccessary.
524:      * @param string $header_name Original name of header.
525:      * @param string $content
526:      * @param string $subdir
527:      */
528:     public function AddSource($header_name, &$content, $subdir="src")
529:     {
530:         if($subdir)
531:         {
532:             $subdir = trim($subdir, "\\/") . "/";
533:             
534:             if(!file_exists($this->output_path . $subdir))
535:                 \Peg\Lib\Utilities\FileSystem::MakeDir(
536:                     $this->output_path . $subdir, 
537:                     0755, 
538:                     true
539:                 );
540:         }
541:         
542:         $header = $this->output_path 
543:             . $subdir
544:             . $this->GetSourceNamePHP($header_name)
545:         ;
546:         
547:         \Peg\Lib\Utilities\FileSystem::WriteFileIfDifferent($header, $content);
548:     }
549:     
550:     /**
551:      * Adds or updates a generic file if neccessary.
552:      * @param string $file_name Original name of header.
553:      * @param string $content
554:      * @param string $subdir
555:      */
556:     public function AddGenericFile($file_name, &$content, $subdir="")
557:     {
558:         if($subdir)
559:         {
560:             $subdir = trim($subdir, "\\/") . "/";
561:             
562:             if(!file_exists($this->output_path . $subdir))
563:                 \Peg\Lib\Utilities\FileSystem::MakeDir(
564:                     $this->output_path . $subdir, 
565:                     0755, 
566:                     true
567:                 );
568:         }
569:         
570:         $output_file = $this->output_path 
571:             . $subdir
572:             . $file_name
573:         ;
574:         
575:         \Peg\Lib\Utilities\FileSystem::WriteFileIfDifferent(
576:             $output_file, 
577:             $content
578:         );
579:     }
580:     
581:     /**
582:      * Generate all the sources.
583:      */
584:     abstract public function Start();
585:     
586:     /**
587:      * Generate the header source of a specific header file.
588:      * @param string $header_name
589:      * @return string Source code.
590:      */
591:     abstract public function GenerateHeader($header_name);
592:     
593:     /**
594:      * Generate the source file of a specific header file.
595:      * @param string $header_name
596:      * @return string Source code.
597:      */
598:     abstract public function GenerateSource($header_name);
599:     
600:     /**
601:      * Generate the wrapping code of a specific C/C++ function.
602:      * @param \Peg\Lib\Definitions\Element\FunctionElement $function_object
603:      * @return string Source code.
604:      */
605:     abstract public function GenerateFunction(
606:         \Peg\Lib\Definitions\Element\FunctionElement $function_object
607:     );
608: }
PEG Api API documentation generated by ApiGen 2.8.0