All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unlaxer.parser.AbstractParser Maven / Gradle / Ivy

package org.unlaxer.parser;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import org.unlaxer.Committed;
import org.unlaxer.Name;
import org.unlaxer.Parsed;
import org.unlaxer.Tag;
import org.unlaxer.TokenKind;
import org.unlaxer.ast.ASTNodeKind;
import org.unlaxer.context.ParseContext;

public abstract class AbstractParser implements Parser {
	
	private static final long serialVersionUID = -7497886240652402031L;
	
	Set tags = new HashSet<>();

	Name name;
	
	Name specifiedName;

	Parser parser;

	List children;

	public Optional parent;
	
	Optional root = Optional.empty();
	
	Map parserByName = new HashMap<>();
	
	boolean donePrepareChildren = false;
	
	NodeReduceMarker nodeReduceMarker;
	
	ASTNodeKind astNodeKind;
	
	public AbstractParser() {
		this(null, new ArrayList<>());
	}
	
	public AbstractParser(Name name) {
		this(name,new ArrayList<>());
	}
	
	public AbstractParser(List children) {
		this(null,children);
	}
	
	public AbstractParser(Name name , List children) {
		super();
		this.specifiedName = name == null ? Name.of(getClass()) : name; 
		this.name = name == null ? Name.of(getClass()) : Name.of(getClass(),name);
		this.parent = Optional.empty();
		this.children = children;
		children.stream()
			.forEach(child->child.setParent(this));
		nodeReduceMarker = new NodeReduceMarker();
	}
	
	@Override
	public Parsed parse(ParseContext parseContext , TokenKind tokenKind ,boolean invertMatch) {
		
		parseContext.startParse(this, parseContext, tokenKind, invertMatch);
		
		parseContext.begin(this);
		Parsed parsed = getParser().parse(parseContext,tokenKind,invertMatch);
		
		if(parsed.isSucceeded()){
			Committed commited = parseContext.commit(this , tokenKind);

			Parsed succeededParsed = new Parsed(commited);
			parseContext.endParse(this, succeededParsed , parseContext, tokenKind, invertMatch);
			return succeededParsed;
		}
		
		parseContext.rollback(this);
		parseContext.endParse(this, Parsed.FAILED , parseContext, tokenKind, invertMatch);
		return Parsed.FAILED;
	}

	public Parser getParser() {
		
		if (parser == null) {
			parser = createParser();
			if(this != parser){
				parser.setParent(this);

				if(false ==getChildren().contains(parser)){
					getChildren().add(parser);
				}
			}
		}
		createParserAndThen(parser);
		return parser;
	}

	public void createParserAndThen(Parser createdParser){
		
	}
	
	public abstract Parser createParser();

	@Override
	public Optional getParent() {
		return parent;
	}
	
	@Override
	public Parser getRoot(){
		if(false == root.isPresent()){
			root = Optional.of(findFirstToParent(Parser.isRoot).orElse(this));
		}
		return root.get();
	}

	@Override
	public void setParent(Parser parent) {
		this.parent = Optional.ofNullable(parent);
		nodeReduceMarker.parent = Optional.of(nodeReduceMarker);
	}

	@Override
	public List getChildren() {
		if(false == donePrepareChildren){
			prepareChildren(children);
			donePrepareChildren = true;
		}
		return children;
	}

	@Override
	public Name getName(NameKind nameKind) {
		return nameKind.isSpecifiedName() ? specifiedName : name;
	}

	@Override
	public Set getTags() {
		return tags;
	}

	@Override
	public Optional getParser(Name name) {
		
		Parser matched = parserByName.get(name);
		if(matched == null ){
			Optional findFirstFromRoot = findFirstFromRoot(parser->parser.getName().equals(name));
			findFirstFromRoot.ifPresent(parser->parserByName.put(name , parser));
			return findFirstFromRoot;
		}
		return Optional.of(matched);
	}
	
	
	@Override
	public Stream getPathStream(boolean containCallerParser){
		List describeParents = findParents(Parser.isRoot,containCallerParser);
		Collections.reverse(describeParents);
		
		return describeParents.stream();
	}

	@Override
	public NodeReduceMarker getNodeReduceMarker() {
		return nodeReduceMarker;
	}

  @Override
  public Parser setASTNodeKind(ASTNodeKind astNodeKind) {
    this.astNodeKind = astNodeKind;
    addTag(astNodeKind.tag()); // TODO too much?
    return this;
  }

  @Override
  public ASTNodeKind astNodeKind() {
    
    if(astNodeKind == null) {
      return ASTNodeKind.NotSpecified;
    }
    return astNodeKind;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy