compile method

void compile()

Compiles the given source into Dart code. Notice: it can be called only once. To compile the second time, you have to instantiate another Compiler.

Implementation

void compile() {
  _writeln("//Auto-generated by RSP Compiler");
  final srcnm = sourceName;
  if (srcnm != null)
    _writeln("//Source: ${_shorten(srcnm, destinationName)}");

  bool pgFound = false, started = false, written = false;
  int prevln = 1;
  for (var token; (token = _nextToken()) != null; prevln = _line) {
    if (_current.args != null && token is! VarTag && token is! _Closing
    && (token is! String || token.trim().isNotEmpty))
      _error("Only the var tag is allowed inside the ${_current.tag?.name} tag, not $token");

    if (token is PageTag) {
      if (pgFound)
        _error("Only one page tag is allowed", _line);
      if (started)
        _error("The page tag must be in front of any non-whitespace content and tags", _line);
      pgFound = true;

      push(token);
      token.begin(_current, _tagData());
      token.end(_current);
      pop();
    } else if (token is String) {
      String text = token;
      if (!written) {
        if (text.trim().isEmpty)
          continue; //skip it
        written = true;
      }
      if (!started) {
        started = true;
        _start(prevln); //use previous line number since it could be multiple lines
      }
      outText(_current, text, prevln);
    } else {
      if (!started) {
        if (token is Tag && token.name == "header") {
          assert(!token.hasClosing);
          final int line = _line;
          _headers.add(_QuedTag(token, _tagData(tag: token), line));
          continue;
        }

        started = true;
        _start();
      }

      if (token is _Expr) {
        written = true;
        _outExpr();
      } else if (token is DartTag) {
        push(token);
        token.begin(_current, _dartData());
        token.end(_current);
        pop();
      } else if (token is Tag) {
        if (!written)
          written = token.hasContent;

        push(token);
        token.begin(_current, _tagData(tag: token));
        if (!token.hasClosing) {
          token.end(_current);
          pop();
        }
      } else if (token is _Closing) {
        final _Closing closing = token;
        String? tagnm;
        final curtag = _current.tag;
        if (curtag == null || (tagnm = curtag.name) != closing.name) {
          String msg = "Unexpected [/${closing.name}]";
          if (tagnm != null)
            msg += "; expect [/$tagnm]";
          _error(msg, _line);
        }
        curtag.end(_current);
        pop();
      } else {
        _error("Unknown token: $token", _line);
      }
    }
  }

  if (started) {
    if (_tagCtxs.length > 1) {
      final sb = StringBuffer();
      for (int i = _tagCtxs.length; --i >= 1;) {
        if (!sb.isEmpty) sb.write(', ');
        sb..write(_tagCtxs[i].tag)..write(' at line ')..write(_tagCtxs[i].line);
      }
      _error("Unclosed tag(s): $sb");
    }
    _writeln("\n  return null;\n}");
  }
}