com.github.jonathanxd.textlexer.ext.parser.Parser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of textlexer Show documentation
Show all versions of textlexer Show documentation
Lexical Analyzer API for Java!
/*
* TextLexer - Lexical Analyzer API for Java!
* Copyright (C) 2016 TheRealBuggy/JonathanxD (https://github.com/JonathanxD/)
*
* GNU GPLv3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package com.github.jonathanxd.textlexer.ext.parser;
import com.github.jonathanxd.iutils.optional.Require;
import com.github.jonathanxd.textlexer.ext.parser.holder.TokenHolder;
import com.github.jonathanxd.textlexer.ext.parser.processor.ParserProcessor;
import com.github.jonathanxd.textlexer.ext.parser.structure.Options;
import com.github.jonathanxd.textlexer.ext.parser.structure.ParseStructure;
import com.github.jonathanxd.textlexer.ext.parser.structure.StructureOptions;
import com.github.jonathanxd.textlexer.lexer.token.IToken;
import com.github.jonathanxd.textlexer.lexer.token.history.ITokenList;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.Optional;
/**
* Created by jonathan on 17/02/16.
*/
public class Parser {
private final ITokenList tokenList;
private final List processors = new ArrayList<>();
private final List tokenHolders = new ArrayList<>();
public Parser(ITokenList tokenList) {
this.tokenList = tokenList;
}
public ITokenList getTokenList() {
return tokenList;
}
public void addProcessor(ParserProcessor processor) {
getProcessors().add(processor);
}
protected List getProcessors() {
return processors;
}
public ParseStructure process() {
ParseStructure structure = new ParseStructure();
ParseStructure.ParseSection section = structure.createSection();
Deque> tokenDeque = new LinkedList<>();
List> tokenList = getTokenList().allToList();
ListIterator> tokenIterator = tokenList.listIterator();
TokenHolder previousHeadHolder = null;
while (tokenIterator.hasNext()) {
int index = tokenIterator.nextIndex();
IToken> token = tokenIterator.next();
IToken> next = next(index, tokenList);
IToken> previous = (index - 1 > -1 ? tokenList.get(tokenIterator.previousIndex()) : null);
if (!call(token, index, tokenList, structure, section)) {
StructureOptions options = optionsOf(token);
if (options.is(Options.IGNORE))
continue;
if (!options.is(Options.HARD_HEAD) && !options.is(Options.HEAD)
&& (options.is(Options.STACK) || options.is(Options.ELEMENT))) {
if (next == null || optionsOf(next).is(Options.STACK)) {
if (previousHeadHolder != null) {
previousHeadHolder.link(token);
} else {
section.enter(structure.addToken(token));
}
} else {
tokenDeque.addLast(token);
}
} else {
if (options.is(Options.HEAD)) {
if (!section.canExit()) {
previousHeadHolder = structure.addToken(token);
section.enter(previousHeadHolder);
} else {
previousHeadHolder = section.link(token);
}
} else {
previousHeadHolder = structure.addToken(token);
section.enter(previousHeadHolder);
}
for (IToken> iToken : tokenDeque) {
section.link(iToken);
if (optionsOf(iToken).is(Options.EXIT)) {
section.exit();
}
}
tokenDeque.clear();
if (optionsOf(token).is(Options.EXIT)) {
section.exit();
}
}
}
}
if (!tokenDeque.isEmpty()) {
for (IToken> token : tokenDeque) {
if (previousHeadHolder != null) {
previousHeadHolder.link(token);
} else {
section.enter(structure.addToken(token));
}
}
}
processingEnd(structure);
return structure;
}
private IToken> next(int index, List> tokenList) {
for (int x = index + 1; x < tokenList.size(); ++x) {
IToken> token = tokenList.get(x);
if (!optionsOf(token).is(Options.IGNORE)) {
return token;
}
}
return null;
}
private void processingEnd(ParseStructure structure) {
processors.forEach(processor -> processor.processFinish(structure));
}
private boolean call(IToken> token, int index, List> tokenList, ParseStructure structure, ParseStructure.ParseSection section) {
//boolean isProcessor = false;
for (ParserProcessor parserProcessor : processors) {
if(parserProcessor.isProcessor()) {
ListIterator> iterator = tokenList.listIterator(index);
Processor processor = new AProcessor(token, iterator, structure, section);
parserProcessor.process(processor);
//isProcessor = true;
// TODO NOTE: Don't supports multiple processing at time.
return true;
}
}
return false; //isProcessor
}
public StructureOptions optionsOf(IToken> token) {
Optional processorOptional = processors.stream().findFirst();
return Objects.requireNonNull(Require.require(processorOptional, "Cannot find Options for Tokens: " + token).tokenOptions(token), "Null options!");
}
public ParseStructure parse() {
return process();
}
private static final class AProcessor implements Processor {
private final IToken> token;
private final ListIterator> iterator;
private final ParseStructure structure;
private final ParseStructure.ParseSection section;
private AProcessor(IToken> token, ListIterator> iterator, ParseStructure structure, ParseStructure.ParseSection section) {
this.token = token;
this.iterator = iterator;
this.structure = structure;
this.section = section;
}
@Override
public IToken> currentToken() {
return token;
}
@Override
public IToken> safeNext() {
return iterator.next();
}
@Override
public ParseStructure structure() {
return structure;
}
@Override
public ParseStructure.ParseSection section() {
return section;
}
}
}