PhpGrammar.php
<?php
namespace Tlf\Lexer;
/**
*
* This is not for actual parsing yet. This is for design work. The $directives array & 'php_open' and 'namespace' are design aspects I'm interested in implementing at some point... maybe
*
*/
class PhpGrammar extends Grammar {
use Php\LanguageDirectives;
use Php\ClassDirectives;
use Php\ClassMemberDirectives;
use Php\BodyDirectives;
use Php\OtherDirectives;
protected $directives;
public $notin = [
'keyword'=>[
// 'match'=>'/this-regex-available on php.net keywords page/',
'__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor'
],
];
public function getNamespace(){return 'php';}
public function buildDirectives(){
$this->directives = array_merge(
$this->_language_directives,
$this->_body_directives,
$this->_class_directives,
$this->_class_member_directives,
$this->_other_directives,
);
}
public function onGrammarAdded($lexer){
$this->buildDirectives();
$lexer->addDirective($this->getDirectives(':php_open')['php_open']);
}
public function onLexerStart($lexer,$file,$token){
$lexer->addGrammar(new DocblockGrammar());
// $this->buildDirectives();
// $lexer->addDirective($this->getDirectives(':html')[':html']);
// $lexer->stackDirectiveList('phpgrammar:html', 'phpgrammar:php_open');
// $lexer->setDirective([$this->getDirective('html')]);
if ($file->type=='file'){
$file->set('namespace', '');
}
}
public function holdNamespaceName($lexer, $file, $token){
$prev = $lexer->previous('namespace.name');
if ($prev == null)$prev = [];
$prev[] = $token->buffer();
$lexer->setPrevious('namespace.name', $prev);
}
public function saveNamespace($lexer, $file, $token){
$namespace = $lexer->previous('namespace.name');
$namespace = implode('\\',$namespace);
$file->set('namespace.docblock', $lexer->unsetPrevious('docblock'));
$file->set('namespace', $namespace);
$lexer->setPrevious('namespace.name', $namespace);
}
public function handleClassDeclaration($lexer, $class, $token){
$class->set('declaration', $lexer->unsetPrevious('class.declaration'));
}
public function processDocBlock($lexer, $ast, $token){
$lexer->setPrevious('docblock', $token->buffer());
}
public function captureUseTrait($lexer, $ast, $token){
$ast->add('traits',$token->buffer());
}
public function processComment($lexer, $ast, $token){
$comment = trim($token->buffer());
$ast->add('comments', $comment);
$lexer->previous('comment', $comment);
}
// public function end_docblock($lexer, $unknownAst, $token){
// $block = $token->buffer();
// $block = trim($block);
// $block = trim(substr($block,strlen('/**'),-1));
// $block = preg_replace('/^\s*\*+/m','',$block);
// $block = \Tlf\Scrawl\Utility::trimTextBlock($block);
// $block = trim($block);
// // if (substr($block,0,3)=='/**')$block = substr($block,3);
//
// $docLex = new \Tlf\Lexer();
// $docLex->addGrammar(new \Tlf\Lexer\DocBlockGrammar());
//
// $docAst = new \Tlf\Lexer\Ast('docblock');
// $docAst->set('src', $block);
// $docLex->setHead($docAst);
//
// $docAst = $docLex->lexAst($docAst, $block);
//
// $lexer->setPrevious('docblock', $docAst);
// $unknownAst->add('childDocblock', $docAst);
// $token->setBuffer($token->match(0));
// }
/**
* Do nothing, apparently? I thought it was supposed to append to previous('whitespace'). Idunno
*/
public function appendToWhitespace($lexer, $ast, $token, $directive){
// $whitespace = $lexer->previous('whitespace') ?? '';
// $lexer->setPrevious('whitespace', $whitespace.$directive->_matches[0]);
// $lexer->setPrevious('whitespace', $whitespace.$token->buffer());
}
/**
* Combine the stored modifier with the stored property declaration
*/
public function setPropertyDeclaration($lexer, $ast, $token, $directive){
$ast->set('declaration',
$lexer->unsetPrevious('modifier')
.$lexer->unsetPrevious('property.declaration')
);
}
/**
*
*/
public function storeMethodDefinition($lexer, $ast, $token, $directive){
$ast->set('definition',
$lexer->unsetPrevious('modifier')
.$lexer->unsetPrevious('method.definition')
);
$ast->set('arglist', $lexer->unsetPrevious('method.arglist') );
$name = $lexer->unsetPrevious('method.name');
$ast->set('name', $name);
//remove the method name from the modifiers.
$modifiers = $ast->get('modifiers');
$ast->set('modifiers', substr($modifiers,0, -strlen($name)));
}
}