package cparser;

import java.util.List;

public class AST {

  public static class Error {
    public final Span span;
    public final String message;

    public Error(Span span, String message) {
      this.span = span;
      this.message = message;
    }
  }

  public static class Span {
    public final int startOffset;
    public final int endOffset;

    public Span(int startOffset, int endOffset) {
      this.startOffset = startOffset;
      this.endOffset = endOffset;
    }

    public Span() {
      this.startOffset = -1;
      this.endOffset = -1;
    }

    public boolean isValid() {
      return endOffset > startOffset;
    }
  }

  public static class PreprocessorExpression {
    public final Span span;

    public PreprocessorExpression(Span span) {
      this.span = span;
    }
  }

  public static class Type {
    // The entire type definition, e.g. "byte**"
    public final Span span;
    // the base type name, e.g. byte in "byte* (&value)[20]"
    public final Span baseSpan;

    public Type(Span span, Span baseSpan) {
      this.span = span;
      this.baseSpan = baseSpan;
    }
  }

  public static class Identifier {
    public final Span span;

    public Identifier(Span span) {
      this.span = span;
    }
  }

  public static class ArgumentList {
    public final List<Object> arguments;

    public ArgumentList(List<Object> arguments) {
      this.arguments = arguments;
    }
  }

  private static class Expr {
    public final Span span;

    public Expr(Span span) {
      this.span = span;
    }
  };

  public static class VariableDeclaration {
    public final String type;
    public final String identifier;
    public final boolean isPointer;
    public final boolean isReference;
    public final boolean isArray;
    public final int arraySize;
    public final boolean isFunction;
    public final Span span;

    public VariableDeclaration(String type, String identifier, boolean isPointer, boolean isReference,
                               boolean isArray, int arraySize, boolean isFunction, Span span) {
        this.type = type;
        this.identifier = identifier;
        this.isPointer = isPointer;
        this.isReference = isReference;
        this.isArray = isArray;
        this.arraySize = arraySize;
        this.isFunction = isFunction;
        this.span = span;
    }
  }

  public static class FunctionDecl {
    public final Identifier name;
    public final Type returnValue;
    public final ArgumentList args;

    public FunctionDecl(Identifier name, Type returnValue, ArgumentList args) {
      this.name = name;
      this.returnValue = returnValue;
      this.args = args;
    }
  }

  public static class FunctionCall {
    public final Identifier name;
    public final ArgumentList args;

    public FunctionCall(Identifier name, ArgumentList args) {
      this.name = name;
      this.args = args;
    }
  }
}
