combinators.nim 4.07 KB
import petitparser, context

# DelegateParser
type
  DelegateParser* = ref object of Parser
    delegate*: Parser

proc newDelegateParser*(delegate: Parser not nil): DelegateParser =
  DelegateParser(delegate: delegate)

method parseOn*(self: DelegateParser, context: Context): Result =
  self.delegate.parseOn(context)

method replace*(self: DelegateParser, source, target: Parser) =
  procCall(Parser(self).replace(source, target))
  if delegate == source:
    delegate = target

method getChildren(self: DelegateParser): seq[Parser] =
  @[delegate]

method copy(self: DelegateParser): Parser =
  newDelegateParser(self.delegate)


## A parser that optionally parsers its delegate, or answers nil.
type
  OptionalParser* = ref object of DelegateParser
    otherwise*: RootRef

proc newOptionalParser*(delegate: Parser, otherwise: RootRef): OptionalParser =
  OptionalParser(delegate: delegate, otherwise: otherwise)

#  public OptionalParser(Parser delegate, Object otherwise) {
#    super(delegate);
#    this.otherwise = otherwise;
#  }

method parseOn*(self: OptionalParser, context: Context): Result =
  result = self.delegate.parseOn(context)
  if result.isSuccess:
    return
  current.success(elements)


#  public Result parseOn(Context context) {
#    Result result = delegate.parseOn(context);
#    if (result.isSuccess()) {
#      return result;
#    } else {
#      return context.success(otherwise);
#    }
#  }

method hasEqualProperties*(self: OptionalParser, other: Parser): bool =
  return true
  
#  protected boolean hasEqualProperties(Parser other) {
#    return super.hasEqualProperties(other) &&
#        Objects.equals(otherwise, ((OptionalParser) other).otherwise);
#  }

method copy*(self: OptionalParser): Parser =
  newOptionalParser(self.delegate, self.otherwise)

#  @Override
#  public Parser copy() {
#    return new OptionalParser(delegate, otherwise);
#  }



# Abstract parser that parses a list of things in some way (to be specified by the subclasses).
type
  ListParser* = ref object of Parser
    parsers*: seq[Parser]

#proc newListParser*(parsers: seq[Parser] not nil): ListParser =
#  ListParser(parsers: parsers)

method replace*(self: ListParser, source, target: Parser) =
  procCall(Parser(self).replace(source, target))
  for i in 0..high(parsers):
    if parsers[i] == source:
      parsers[i] = target

#  public void replace(Parser source, Parser target) {
#    super.replace(source, target);
#    for (int i = 0; i < parsers.length; i++) {
#      if (parsers[i] == source) {
#        parsers[i] = target;
#      }
#    }
#  }

method getChildren(self: ListParser): seq[Parser] =
  self.parsers

#  public List<Parser> getChildren() {
#    return Arrays.asList(parsers);
#  }

  
# A parser that parses a sequence of parsers.
type
  SequenceParser* = ref object of ListParser

method parseOn*(self: SequenceParser, context: Context): Result =
  var
    current = context
    elements = newSeq[auto](self.parsers.len)
  for parser in self.parsers:
    result = parser.parseOn(current)
    if result.isFailure:
      return
    elements.add(result.get())
    current = result
  current.success(elements)
  
#  public Result parseOn(Context context) {
#    Context current = context;
#    List<Object> elements = new ArrayList<>(parsers.length);
#   for (Parser parser : parsers) {
#      Result result = parser.parseOn(current);
#      if (result.isFailure()) {
#        return result;
#      }
#      elements.add(result.get());
#      current = result;
#    }
#    return current.success(elements);
#  }

method seq*(self: SequenceParser, others: varargs[Parser]): Parser =
  newSequenceParser(self.parsers & others)
#  let all = newSeq[Parser](self.parsers.len + others.len)
  
#  public Parser seq(Parser... others) {
#    Parser[] array = Arrays.copyOf(parsers, parsers.length + others.length);
#    System.arraycopy(others, 0, array, parsers.length, others.length);
#    return new SequenceParser(array);
#  }

method copy*(self: SequenceParser): Parser =
  newSequenceParser(@[] & self.parsers)


#  @Override
#  public Parser copy() {
#    return new SequenceParser(Arrays.copyOf(parsers, parsers.length));
#  }
#}