Index: pkg/kernel/lib/interpreter/tools/dart_to_latex.dart |
diff --git a/pkg/kernel/lib/interpreter/tools/dart_to_latex.dart b/pkg/kernel/lib/interpreter/tools/dart_to_latex.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e4482971d1a29bb734c97eeea6e22b597ae275e4 |
--- /dev/null |
+++ b/pkg/kernel/lib/interpreter/tools/dart_to_latex.dart |
@@ -0,0 +1,245 @@ |
+// Copyright (c) 2017, 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. |
+ |
+/*LATEX |
+\documentclass[a4paper,12pt,oneside]{article} |
+ |
+\usepackage[utf8]{inputenc} |
+\usepackage{amsmath} |
+\usepackage{amssymb} |
+\usepackage{listings} |
+ |
+\lstset{basicstyle=\footnotesize\ttfamily\bf} |
+ |
+\begin{document} |
+ |
+\title{dart\_to\_latex.dart} |
+\author{The Dart project authors} |
+\date{} |
+ |
+\maketitle |
+ |
+\section*{Introduction} |
+ |
+The purpose of this program is to extract comments of a special form from Dart |
+programs and put them into a .tex file in the order of their appearance in the |
+Dart program. |
+It allows writing elaborate documentation in the comments using formulas and |
+also use custom formatting commands. |
+ |
+The comments that are put into the output .tex file are of the form |
+\lstinline!/*LATEX ... */!. |
+Additionally, all Dart lines marked with one-line comment \lstinline!//LATEX! |
+are also included to the output file and are put into \lstinline!verbatim! |
+environment. |
+Using \lstinline!//LATEX! sometimes conflicts with the default behavior of |
+\lstinline!dartfmt! formatting utility that may put the one-line comment to the |
+following line. |
+To address this issue one can use \lstinline!//LATEX-NEXT! comment right before |
+the line that should be inserted into the output. |
+ */ |
+ |
+/*LATEX |
+\section{Implementation Overview} |
+ |
+First, the libraries for working with files and strings are imported. |
+ */ |
+import "dart:io"; //LATEX |
+import "dart:core"; //LATEX |
+ |
+/*LATEX |
+Most of the work is done in the Extractor class. |
+ */ |
+ |
+//LATEX-NEXT |
+class Extractor { |
+ /*LATEX |
+ There are some string constants that are used for text parsing. |
+ */ |
+ static final String latexMarker = "LATEX"; //LATEX |
+ static final String latexNextMarker = "LATEX-NEXT"; //LATEX |
+ static final String commentBegin = "/*"; //LATEX |
+ static final String commentEnd = "*/"; //LATEX |
+ static final String oneLineCommentBegin = "//"; //LATEX |
+ |
+ final String inputFilename; |
+ final String outputFilename; |
+ |
+ final File inputFile; |
+ final File outputFile; |
+ |
+ String input; |
+ |
+ /*LATEX |
+ The actual parsing is done in the following methods. |
+ */ |
+ |
+ //LATEX-NEXT |
+ Extractor(this.inputFilename, this.outputFilename) |
+ : inputFile = new File(inputFilename), |
+ outputFile = new File(outputFilename) { |
+ // Clear the output file at start. |
+ outputFile.writeAsStringSync("", mode: FileMode.WRITE, flush: true); |
+ } |
+ |
+ //LATEX-NEXT |
+ int findCommentEnd(int start) { |
+ assert(start <= input.length); |
+ assert(input.startsWith(commentBegin, start)); |
+ |
+ int balance = 1; |
+ int i = start + commentBegin.length; |
+ while (i < input.length && balance > 0) { |
+ if (input.startsWith(commentBegin, i)) { |
+ balance++; |
+ i += commentBegin.length; |
+ } else if (input.startsWith(commentEnd, i)) { |
+ balance--; |
+ i += commentEnd.length; |
+ } else { |
+ i++; |
+ } |
+ } |
+ |
+ if (balance > 0) { |
+ return -1; |
+ } |
+ |
+ return i; |
+ } |
+ |
+ //LATEX-NEXT |
+ void extractOneLineCommentsFrom(String text) { |
+ List<String> lines = text.split("\n"); |
+ List<String> outputLines = new List<String>(); |
+ int i = 0; |
+ while (i < lines.length) { |
+ String line = lines[i]; |
+ if (line.endsWith(oneLineCommentBegin + latexMarker)) { |
+ outputLines.add(line.substring( |
+ 0, line.length - (oneLineCommentBegin + latexMarker).length)); |
+ i++; |
+ } else if (line.endsWith(oneLineCommentBegin + latexNextMarker) && |
+ i + 1 < lines.length) { |
+ outputLines.add(lines[i + 1]); |
+ i += 2; |
+ } else { |
+ i++; |
+ } |
+ } |
+ if (outputLines.length > 0) { |
+ outputLines.insert(0, r"\begin{verbatim}"); |
+ outputLines.add(r"\end{verbatim}"); |
+ } |
+ for (String line in outputLines) { |
+ outputFile.writeAsStringSync("$line\n", mode: FileMode.APPEND); |
+ } |
+ } |
+ |
+ //LATEX-NEXT |
+ void extractOneLineComments() { |
+ int endIndex = input.indexOf(commentBegin); |
+ while (endIndex != -1 && |
+ !input.startsWith(commentBegin + latexMarker, endIndex)) { |
+ endIndex = findCommentEnd(endIndex); |
+ if (endIndex != -1) { |
+ endIndex = input.indexOf(commentBegin, endIndex); |
+ } |
+ } |
+ if (endIndex == -1) { |
+ endIndex = input.length; |
+ } |
+ extractOneLineCommentsFrom(input.substring(0, endIndex)); |
+ input = input.substring(endIndex); |
+ } |
+ |
+ //LATEX-NEXT |
+ void extractBlock() { |
+ int startIndex = input.indexOf(commentBegin); |
+ while (startIndex != -1 && |
+ !input.startsWith(commentBegin + latexMarker, startIndex)) { |
+ startIndex = findCommentEnd(startIndex); |
+ if (startIndex != -1) { |
+ startIndex = input.indexOf(commentBegin, startIndex); |
+ } |
+ } |
+ if (startIndex == -1) { |
+ startIndex = input.length; |
+ } |
+ input = input.substring(startIndex); |
+ |
+ if (input.startsWith(commentBegin + latexMarker)) { |
+ int endIndex = findCommentEnd(0); |
+ if (endIndex == -1) { |
+ endIndex = input.length; |
+ } |
+ int latexBeginIndex = (commentBegin + latexMarker).length; |
+ int latexEndIndex = input.substring(0, endIndex).endsWith(commentEnd) |
+ ? endIndex - commentEnd.length |
+ : endIndex; |
+ outputFile.writeAsStringSync( |
+ input.substring(latexBeginIndex, latexEndIndex) + "\n", |
+ mode: FileMode.APPEND); |
+ input = input.substring(endIndex); |
+ } |
+ } |
+ |
+ //LATEX-NEXT |
+ void run() { |
+ input = inputFile.readAsStringSync(); |
+ while (input.length > 0) { |
+ extractOneLineComments(); |
+ if (input.length > 0) extractBlock(); |
+ } |
+ } |
+} // class Extractor //LATEX |
+ |
+/*LATEX |
+Finally, the entrance point of the program is defined. |
+After some trivial arguments check it creates an extractor instance and runs the |
+extraction. |
+ */ |
+//LATEX-NEXT |
+main(List<String> arguments) { |
+ // Arguments checks... //LATEX |
+ if (arguments.length != 2) { |
+ stderr.writeln("usage: dart dart_to_latex.dart input.dart output.tex"); |
+ exit(1); |
+ } |
+ String inputFilename = arguments[0]; |
+ String outputFilename = arguments[1]; |
+ |
+ Extractor parser = new Extractor(inputFilename, outputFilename); //LATEX |
+ parser.run(); //LATEX |
+} //LATEX |
+ |
+/*LATEX |
+\section{User Manual} |
+ |
+\begin{enumerate} |
+\item \lstinline!dart dart_to_latex.dart input.dart output.tex! |
+\item \lstinline!pdflatex output.tex! |
+\end{enumerate} |
+ */ |
+ |
+/*LATEX |
+\section*{Conclusion} |
+ |
+The presented program may have been written better. |
+It reads the entire input file into a \lstinline!String! variable and creates |
+sub-strings of the input during extraction. |
+A better approach would be to read the input program partially into a buffer, |
+maintain a set of indexes on it, and analyze it on the fly. |
+ |
+The \LaTeX{} part of the program can also be improved. |
+For example, there is probably a better way to format the code fragmeents |
+inlined into paragraphs than using \lstinline1\lstinline!...!1. |
+ |
+As a side note, one may use this tool to extract \LaTeX{} comments from programs |
+in some other languages like C++ and Java. |
+ */ |
+ |
+/*LATEX |
+\end{document} |
+ */ |