Package dtool.parser

Source Code of dtool.parser.DeeParser_Common$ElementListParseHelper

package dtool.parser;

import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;

import java.util.ArrayList;

import dtool.ast.ASTNode;
import dtool.ast.NodeListView;
import dtool.ast.definitions.DefUnit.ProtoDefSymbol;
import dtool.ast.definitions.Symbol;
import dtool.ast.references.RefIdentifier;
import dtool.ast.references.Reference;
import dtool.parser.common.AbstractParser;
import dtool.parser.common.BaseLexElement;


public abstract class DeeParser_Common extends AbstractParser {
 
  protected abstract DeeParser thisParser();
 
  /* ----------------------------------------------------------------- */
 
  public DeeTokens lookAheadGrouped() {
    return lookAheadElement().type.getGroupingToken();
  }
 
  public String idTokenToString(BaseLexElement id) {
    return id.isMissingElement() ? null : id.getSourceValue();
  }
 
  public static boolean isCloseBracketChar(DeeTokens token) {
    return
      token == DeeTokens.CLOSE_BRACE ||
      token == DeeTokens.CLOSE_BRACKET ||
      token == DeeTokens.CLOSE_PARENS;
  }
 
  /* -----------------------  List parse helper  ----------------------- */
 
  public abstract class ElementListParseHelper<T extends ASTNode> extends ParseHelper {
   
    public NodeListView<T> members;
   
    public ElementListParseHelper() {
      nodeStart = -1;
    }
   
    public void parseList(DeeTokens tkOPEN, DeeTokens tkSEP, DeeTokens tkCLOSE) {
      parseList(true, tkOPEN, tkSEP, tkCLOSE, true);
    }
    public void parseList(boolean required, DeeTokens tkOPEN, DeeTokens tkSEP, DeeTokens tkCLOSE,
      boolean canHaveEndingSep) {
      ParseHelper parse = this;
      if(parse.consume(tkOPEN, !required, required) == false) {
        return;
      }
      setStartPosition(lastLexElement().getStartPos());
     
      ArrayList<T> membersList = new ArrayList<T>();
      boolean hasEndingSep = false;
     
      boolean requireElement = false;
      while(true) {
        if(requireElement == false && tryConsume(tkCLOSE))
          break;
       
        T entry = parseElement(requireElement || lookAhead() == tkSEP);
        if(entry != null) {
          membersList.add(entry);
          hasEndingSep = false;
        }
       
        if(tryConsume(tkSEP)) {
          hasEndingSep = true;
          requireElement = !canHaveEndingSep;
          continue;
        } else {
          parse.consumeRequired(tkCLOSE);
          break;
        }
      }
      members = nodeListView(membersList, hasEndingSep);
    }
   
    protected abstract T parseElement(boolean createMissing);
   
  }
 
  public abstract class SimpleListParseHelper<T extends ASTNode> {
   
    public NodeListView<T> members;
   
    public NodeListView<T> parseSimpleList(DeeTokens tkSEP, boolean canBeEmpty, boolean canHaveEndingSep) {
      ArrayList<T> membersList = new ArrayList<T>();
     
      do {
        T entry = parseElement(!canBeEmpty || lookAhead() == tkSEP);
        membersList.add(entry);
        canBeEmpty = canHaveEndingSep;
      } while(tryConsume(tkSEP));
     
      members = nodeListView(membersList);
      return members;
    }
   
    protected abstract T parseElement(boolean createMissing);
  }
 
  /* ----------------------------------------------------------------- */
 
  public static ProtoDefSymbol defSymbol(BaseLexElement id) {
    // possible bug here, should be srEffectiveRange
    return new ProtoDefSymbol(id.getSourceValue(), id.getSourceRange(), id.getMissingError());
  }
 
  public final ProtoDefSymbol parseMissingDefIdNoError() {
    return new ProtoDefSymbol("", srAt(getSourcePosition()), null);
  }
 
  public final ProtoDefSymbol parseDefId() {
    BaseLexElement defId = consumeExpectedContentToken(DeeTokens.IDENTIFIER);
    return defSymbol(defId);
  }
 
  public final ProtoDefSymbol nullIdToParseMissingDefId(ProtoDefSymbol defId) {
    if(defId == null) {
      return parseMissingDefIdNoError();
    }
    return defId;
  }
 
  public static boolean couldHaveBeenParsedAsId(Reference ref) {
    return ref instanceof RefIdentifier;
  }
 
  public static ProtoDefSymbol convertRefIdToDef(Reference ref) {
    assertTrue(couldHaveBeenParsedAsId(ref));
    RefIdentifier refId = (RefIdentifier) ref;
    ParserError error = refId.isMissing() ? getMissingIdError(refId) : null;
    return new ProtoDefSymbol(refId.getDenulledIdentifier(), ref.getSourceRange(), error);
  }
 
  protected static ParserError getMissingIdError(RefIdentifier refId) {
    return refId.getData().getNodeErrors().iterator().next();
  }
 
  public final Symbol parseIdSymbol() {
    BaseLexElement token = consumeExpectedContentToken(DeeTokens.IDENTIFIER);
    return createIdSymbol(token);
  }
  public final Symbol createIdSymbol(BaseLexElement token) {
    return conclude(token.getMissingError(), srOf(token, new Symbol(token.getSourceValue())));
  }
 
  /* ----------------------------------------------------------------- */
 
  protected class TypeId_or_Id_RuleFragment {
   
    public Reference type = null;
    public ProtoDefSymbol defId = null;
   
    public void parseRuleFragment(ParseHelper parse, boolean createMissing) {
      type = parse.checkResult(thisParser().parseTypeReference());
     
      if(parse.ruleBroken) {
        defId = parseMissingDefIdNoError();
      } else if(lookAhead() == DeeTokens.IDENTIFIER) {
        defId = parseDefId();
      } else {
        // No defId so far
        if(couldHaveBeenParsedAsId(type)) {
          singleIdReparse();
        } else {
          if(type == null && !createMissing) {
            return;
          }
          missingDefIdParse();
        }
      }
     
      if(parse.nodeStart == -1) {
        parse.setStartPosition(type != null ? type.getStartPos() : defId.getStartPos());
      }
    }
   
    protected void singleIdReparse() {
      defId = convertRefIdToDef(type);
      type = null;
    }
   
    protected void missingDefIdParse() {
      defId = parseDefId(); //This will create a full missing defId, with error
    }
   
  }
 
  protected final class TypeId_or_Type_RuleFragment extends TypeId_or_Id_RuleFragment {
   
    @Override
    public void singleIdReparse() {
      defId = parseMissingDefIdNoError();
    }
   
    @Override
    public void missingDefIdParse() {
      if(type == null) {
        type = thisParser().parseMissingTypeReference(true);
      }
      defId = parseMissingDefIdNoError();
    }
   
  }
 
}
TOP

Related Classes of dtool.parser.DeeParser_Common$ElementListParseHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
script>