// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library parser_helper;

import "package:expect/expect.dart";

import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart";
import "../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart";
import "../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart";
import "../../../sdk/lib/_internal/compiler/implementation/source_file.dart";
import "../../../sdk/lib/_internal/compiler/implementation/util/util.dart";

import "../../../sdk/lib/_internal/compiler/implementation/elements/modelx.dart"
    show CompilationUnitElementX,
         LibraryElementX;

import "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart";

export "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart"
    show DiagnosticListener;
// TODO(ahe): We should have token library to export instead.
export "../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart";

class LoggerCanceler implements DiagnosticListener {
  void cancel(String reason, {node, token, instruction, element}) {
    throw new CompilerCancelledException(reason);
  }

  void log(message) {
    print(message);
  }

  void internalErrorOnElement(element, String message) {
    log(message);
  }

  void internalError(String message, {node, token, instruction, element}) {
    log(message);
  }

  SourceSpan spanFromSpannable(node, [uri]) {
    throw 'unsupported operation';
  }

  void reportMessage(SourceSpan span, Diagnostic message, kind) {
    log(message);
  }

  void reportError(Spannable node, MessageKind errorCode, [Map arguments]) {
    log(new Message(errorCode, arguments, false));
  }

  void reportInfo(Spannable node, MessageKind errorCode, [Map arguments]) {
    log(new Message(errorCode, arguments, false));
  }

  withCurrentElement(Element element, f()) => f();
}

Token scan(String text) => new StringScanner.fromString(text).tokenize();

Node parseBodyCode(String text, Function parseMethod,
                   {DiagnosticListener diagnosticHandler}) {
  Token tokens = scan(text);
  if (diagnosticHandler == null) diagnosticHandler = new LoggerCanceler();
  Script script =
      new Script(
          new Uri(scheme: "source"),
          new MockFile(text));
  LibraryElement library = new LibraryElementX(script);
  library.canUseNative = true;
  NodeListener listener =
      new NodeListener(diagnosticHandler, library.entryCompilationUnit);
  Parser parser = new Parser(listener);
  Token endToken = parseMethod(parser, tokens);
  assert(endToken.kind == EOF_TOKEN);
  Node node = listener.popNode();
  Expect.isNotNull(node);
  Expect.isTrue(listener.nodes.isEmpty, 'Not empty: ${listener.nodes}');
  return node;
}

Node parseStatement(String text) =>
  parseBodyCode(text, (parser, tokens) => parser.parseStatement(tokens));

Node parseFunction(String text, Compiler compiler) {
  Element element = parseUnit(text, compiler, compiler.mainApp).head;
  Expect.isNotNull(element);
  Expect.equals(ElementKind.FUNCTION, element.kind);
  return element.parseNode(compiler);
}

Node parseMember(String text, {DiagnosticListener diagnosticHandler}) {
  return parseBodyCode(text, (parser, tokens) => parser.parseMember(tokens),
                       diagnosticHandler: diagnosticHandler);
}

class MockFile extends StringSourceFile {
  MockFile(text)
      : super('<string>', text);
}

var sourceCounter = 0;

Link<Element> parseUnit(String text, Compiler compiler,
                        LibraryElement library,
                        [void registerSource(Uri uri, String source)]) {
  Token tokens = scan(text);
  Uri uri = new Uri(scheme: "source", path: '${++sourceCounter}');
  if (registerSource != null) {
    registerSource(uri, text);
  }
  var script = new Script(uri, new MockFile(text));
  var unit = new CompilationUnitElementX(script, library);
  int id = 0;
  ElementListener listener = new ElementListener(compiler, unit, () => id++);
  PartialParser parser = new PartialParser(listener);
  compiler.withCurrentElement(unit, () => parser.parseUnit(tokens));
  return unit.localMembers;
}

NodeList fullParseUnit(String source, {DiagnosticListener diagnosticHandler}) {
  return parseBodyCode(source, (parser, tokens) => parser.parseUnit(tokens),
                       diagnosticHandler: diagnosticHandler);
}
