package org.develnext.jphp.core.syntax.generators; import org.develnext.jphp.core.tokenizer.TokenMeta; import org.develnext.jphp.core.tokenizer.token.SemicolonToken; import org.develnext.jphp.core.tokenizer.token.Token; import org.develnext.jphp.core.tokenizer.token.expr.BackslashExprToken; import org.develnext.jphp.core.tokenizer.token.expr.BraceExprToken; import org.develnext.jphp.core.tokenizer.token.expr.CommaToken; import org.develnext.jphp.core.tokenizer.token.expr.value.FulledNameToken; import org.develnext.jphp.core.tokenizer.token.expr.value.NameToken; import org.develnext.jphp.core.tokenizer.token.stmt.*; import org.develnext.jphp.core.syntax.SyntaxAnalyzer; import php.runtime.Information; import php.runtime.common.LangMode; import php.runtime.common.StringUtils; import php.runtime.env.Environment; import php.runtime.env.Package; import php.runtime.env.PackageManager; import java.util.ArrayList; import java.util.Collections; import java.util.ListIterator; import static org.develnext.jphp.core.tokenizer.token.stmt.NamespaceUseStmtToken.UseType.CLASS; import static org.develnext.jphp.core.tokenizer.token.stmt.NamespaceUseStmtToken.UseType.CONSTANT; import static org.develnext.jphp.core.tokenizer.token.stmt.NamespaceUseStmtToken.UseType.FUNCTION; public class UseGenerator extends Generator<NamespaceUseStmtToken> { public UseGenerator(SyntaxAnalyzer analyzer) { super(analyzer); } public void parseBody(NamespaceUseStmtToken use, Token current, ListIterator<Token> iterator, FulledNameToken prefix, NamespaceUseStmtToken.UseType prefixUseType) { boolean first = true; NamespaceUseStmtToken.UseType useType = prefixUseType; Environment environment = this.analyzer.getEnvironment(); PackageManager packageManager = null; if (environment != null) { packageManager = environment.getPackageManager(); } do { Token next = nextToken(iterator); if (next instanceof FunctionStmtToken) { if ((!first && prefix == null) || (prefixUseType != CLASS)) { unexpectedToken(next); } useType = FUNCTION; next = nextToken(iterator); } else if (next instanceof ConstStmtToken) { if ((!first && prefix == null) || (prefixUseType != CLASS)) { unexpectedToken(next); } useType = CONSTANT; next = nextToken(iterator); } use.setUseType(useType); if (prefix != null && next instanceof FulledNameToken && next.getMeta().getWord().startsWith("\\")) { unexpectedToken(new BackslashExprToken(TokenMeta.of("\\", next)), "identifier or function or const", false); } FulledNameToken name = analyzer.generator(NameGenerator.class).getToken( next, iterator ); if (name == null) { unexpectedToken(iterator.previous()); return; } if (prefix == null) { use.setName(name); } else { ArrayList<NameToken> nameTokens = new ArrayList<>(prefix.getNames()); nameTokens.addAll(name.getNames()); use.setName(new FulledNameToken(name.getMeta(), nameTokens)); } Token token = nextToken(iterator); if (token instanceof AsStmtToken){ token = nextToken(iterator); if (token instanceof NameToken){ use.setAs((NameToken)token); token = nextToken(iterator); } else unexpectedToken(token); } else if (isOpenedBrace(token, BraceExprToken.Kind.BLOCK)) { if (prefix == null) { parseBody(use, current, iterator, name, useType); return; } } else if (token instanceof BackslashExprToken) { next = nextToken(iterator); if (isOpenedBrace(next, BraceExprToken.Kind.BLOCK) && prefix == null) { parseBody(use, current, iterator, name, useType); return; } } NamespaceStmtToken namespace = analyzer.getNamespace(); if (analyzer.getEnvironment() != null && analyzer.getEnvironment().scope.getLangMode() == LangMode.MODERN) { if (packageManager != null && use.isPackageImport()) { Package aPackage = packageManager.tryFind(use.getName().toName(), use.toTraceInfo(analyzer.getContext())); if (aPackage != null) { for (String cls : aPackage.getClasses()) { FulledNameToken nameToken = FulledNameToken.valueOf(StringUtils.split(cls, Information.NAMESPACE_SEP_CHAR)); NamespaceUseStmtToken useStmtToken = new NamespaceUseStmtToken(TokenMeta.of(cls, use)); useStmtToken.setName(nameToken); useStmtToken.setUseType(NamespaceUseStmtToken.UseType.CLASS); namespace.getUses().add(useStmtToken); } for (String s : aPackage.getFunctions()) { FulledNameToken nameToken = FulledNameToken.valueOf(StringUtils.split(s, Information.NAMESPACE_SEP_CHAR)); NamespaceUseStmtToken useStmtToken = new NamespaceUseStmtToken(TokenMeta.of(s, use)); useStmtToken.setName(nameToken); useStmtToken.setUseType(NamespaceUseStmtToken.UseType.FUNCTION); namespace.getUses().add(useStmtToken); } for (String s : aPackage.getConstants()) { FulledNameToken nameToken = FulledNameToken.valueOf(StringUtils.split(s, Information.NAMESPACE_SEP_CHAR)); NamespaceUseStmtToken useStmtToken = new NamespaceUseStmtToken(TokenMeta.of(s, use)); useStmtToken.setName(nameToken); useStmtToken.setUseType(NamespaceUseStmtToken.UseType.CONSTANT); namespace.getUses().add(useStmtToken); } } else { namespace.getUses().add(use); } } else { namespace.getUses().add(use); } } else { namespace.getUses().add(use); } if (token instanceof CommaToken){ use = new NamespaceUseStmtToken(current.getMeta()); } else if (!(token instanceof SemicolonToken)){ if (prefix != null && isClosedBrace(token, BraceExprToken.Kind.BLOCK)) { nextAndExpected(iterator, SemicolonToken.class); break; } unexpectedToken(token); } else break; first = false; } while (true); } @Override public NamespaceUseStmtToken getToken(Token current, ListIterator<Token> iterator) { if (current instanceof NamespaceUseStmtToken){ if (analyzer.getClazz() != null) unexpectedToken(current); NamespaceUseStmtToken use = (NamespaceUseStmtToken) current; parseBody(use, current, iterator, null, CLASS); return use; } return null; } }