OLD | NEW |
---|---|
1 \documentclass{article} | 1 \documentclass{article} |
2 \usepackage{epsfig} | 2 \usepackage{epsfig} |
3 \usepackage{color} | 3 \usepackage{color} |
4 \usepackage{dart} | 4 \usepackage{dart} |
5 \usepackage{bnf} | 5 \usepackage{bnf} |
6 \usepackage{hyperref} | 6 \usepackage{hyperref} |
7 \usepackage{lmodern} | 7 \usepackage{lmodern} |
8 \usepackage[T1]{fontenc} | 8 \usepackage[T1]{fontenc} |
9 \newcommand{\code}[1]{{\sf #1}} | 9 \newcommand{\code}[1]{{\sf #1}} |
10 \title{Dart Programming Language Specification \\ | 10 \title{Dart Programming Language Specification \\ |
11 {5th edition draft}\\ | 11 {5th edition draft}\\ |
12 {\large Version 1.15.0}} | 12 {\large Version 1.15.0}} |
13 | 13 |
14 % For information about Location Markers (and in particular the | 14 % For information about Location Markers (and in particular the |
15 % commands \LMHash and \LMLabel), see the long comment at the | 15 % commands \LMHash and \LMLabel), see the long comment at the |
16 % end of this file. | 16 % end of this file. |
17 | 17 |
18 % CHANGES | 18 % CHANGES |
19 % ======= | 19 % ======= |
20 % Significant changes to the specification. | 20 % Significant changes to the specification. |
21 % | 21 % |
22 % 1.15 | 22 % 1.15 |
23 % - Change how language specification describes control flow. | 23 % - Change how language specification describes control flow. |
24 % - Object initialization now specifies initialization order correctly. | 24 % - Object initialization now specifies initialization order correctly. |
25 % - Specifies that leaving an await-for loop must wait for the subscription | 25 % - Specifies that leaving an await-for loop must wait for the subscription |
26 % to be canceled. | 26 % to be canceled. |
27 % - An await-for loop only pauses the subscription if it does something async. | 27 % - An await-for loop only pauses the subscription if it does something async. |
28 % - Assert statements may now also include a "message" operand. | 28 % - Assert statements may now also include a "message" operand. |
29 % - The Null type is now considered a subtype of all types in most cases. | 29 % - The Null type is now considered a subtype of all types in most cases. |
30 % - Specify what NEWLINE means in multiline strings. | |
30 % | 31 % |
31 % 1.14 | 32 % 1.14 |
32 % - The call "C()" where "C" is a class name, is a now compile-time error. | 33 % - The call "C()" where "C" is a class name, is a now compile-time error. |
33 % - Changed description of rewrites that depended on a function literal. | 34 % - Changed description of rewrites that depended on a function literal. |
34 % In many cases, the rewrite wasn't safe for asynchronous code. | 35 % In many cases, the rewrite wasn't safe for asynchronous code. |
35 % - Removed generalized tear-offs. | 36 % - Removed generalized tear-offs. |
36 % - Allow "rethrow" to also end a switch case. Allow braces around switch cases. | 37 % - Allow "rethrow" to also end a switch case. Allow braces around switch cases. |
37 % - Allow using '=' as default-value separator for named parameters. | 38 % - Allow using '=' as default-value separator for named parameters. |
38 % - Make it a compile-time error if a library includes the same part twice. | 39 % - Make it a compile-time error if a library includes the same part twice. |
39 % - Now more specific about the return types of sync*/async/async* functions | 40 % - Now more specific about the return types of sync*/async/async* functions |
(...skipping 2760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2800 \rationale{ | 2801 \rationale{ |
2801 This decision was made for compatibility with web browsers and Javascript. Earli er versions of the specification required a string to be a sequence of valid Uni code code points. Programmers should not depend on this distinction. | 2802 This decision was made for compatibility with web browsers and Javascript. Earli er versions of the specification required a string to be a sequence of valid Uni code code points. Programmers should not depend on this distinction. |
2802 } | 2803 } |
2803 | 2804 |
2804 \begin{grammar} | 2805 \begin{grammar} |
2805 {\bf stringLiteral:}(multilineString $|$ singleLineString)+ | 2806 {\bf stringLiteral:}(multilineString $|$ singleLineString)+ |
2806 . | 2807 . |
2807 \end{grammar} | 2808 \end{grammar} |
2808 | 2809 |
2809 \LMHash{} | 2810 \LMHash{} |
2810 A string can be either a sequence of single line strings or a multiline string. | 2811 A string can be a sequence of single line strings and multiline strings. |
2811 | 2812 |
2812 \begin{grammar} | 2813 \begin{grammar} |
2813 {\bf singleLineString:}`{\escapegrammar \code{"}}' stringContentDQ* `{\escapegr ammar \code{"}}'; | 2814 {\bf singleLineString:}`{\escapegrammar \code{"}}' stringContentDQ* `{\escapegr ammar \code{"}}'; |
2814 `{\escapegrammar \code{'}}' stringContentSQ* `{\escapegrammar \code{'}}'; | 2815 `{\escapegrammar \code{'}}' stringContentSQ* `{\escapegrammar \code{'}}'; |
2815 `r' `{\escapegrammar \code{'}}' (\~{}( `{\escapegrammar \code{'}}' $|$ NEW LINE ))* `{\escapegrammar \code{'}}'; | 2816 `r' `{\escapegrammar \code{'}}' (\~{}( `{\escapegrammar \code{'}}' $|$ NEW LINE ))* `{\escapegrammar \code{'}}'; |
2816 `r' `{\escapegrammar \code{"}}' (\~{}( `{\escapegrammar \code{"}}' $|$ NEW LINE ))* `{\escapegrammar \code{"}}' | 2817 `r' `{\escapegrammar \code{"}}' (\~{}( `{\escapegrammar \code{"}}' $|$ NEW LINE ))* `{\escapegrammar \code{"}}' |
2817 . | 2818 . |
2818 \end{grammar} | 2819 \end{grammar} |
2819 | 2820 |
2820 \LMHash{} | 2821 \LMHash{} |
2821 A single line string is delimited by either matching single quotes or matching d ouble quotes. | 2822 A single line string is delimited by either matching single quotes or matching d ouble quotes. |
2822 | 2823 |
2823 \commentary{ | 2824 \commentary{ |
2824 Hence, `abc' and ``abc'' are both legal strings, as are `He said ``To be or not to be'' did he not?' and ``He said `To be or not to be' didn't he''. However ` `This ` is not a valid string, nor is `this''. | 2825 Hence, `abc' and ``abc'' are both legal strings, as are `He said ``To be or not to be'' did he not?' and ``He said `To be or not to be' didn't he''. However ` `This ` is not a valid string, nor is `this''. |
2825 } | 2826 } |
2826 | 2827 |
2827 \commentary{The grammar ensures that a single line string cannot span more than one line of source code, unless it includes an interpolated expression that span s multiple lines. | 2828 \commentary{The grammar ensures that a single line string cannot span more than one line of source code, unless it includes an interpolated expression that span s multiple lines. |
2828 } | 2829 } |
2829 | 2830 |
2830 \LMHash{} | 2831 \LMHash{} |
2831 Adjacent | 2832 Adjacent strings are implicitly concatenated to form a single string literal. |
2832 %single line | |
2833 strings are implicitly concatenated to form a single string literal. | |
2834 %, and so are adjacent multiline strings, but the two forms may not be mixed. | |
2835 | 2833 |
2836 | 2834 |
2837 \commentary{Here is an example} | 2835 \commentary{Here is an example} |
2838 | 2836 |
2839 \begin{dartCode} | 2837 \begin{dartCode} |
2840 print("A string" "and then another"); // prints: A stringand then another | 2838 print("A string" "and then another"); // prints: A stringand then another |
2841 \end{dartCode} | 2839 \end{dartCode} |
2842 | 2840 |
2843 \rationale{Dart also supports the operator + for string concatenation. | 2841 \rationale{Dart also supports the operator + for string concatenation. |
2844 | 2842 |
2845 The + operator on Strings requires a String argument. It does not coerce its arg ument into a string. This helps avoid puzzlers such as | 2843 The + operator on Strings requires a String argument. It does not coerce its arg ument into a string. This helps avoid puzzlers such as |
2846 } | 2844 } |
2847 | 2845 |
2848 \begin{dartCode} | 2846 \begin{dartCode} |
2849 print("A simple sum: 2 + 2 = " + | 2847 print("A simple sum: 2 + 2 = " + |
2850 2 + 2); | 2848 2 + 2); |
2851 \end{dartCode} | 2849 \end{dartCode} |
2852 | 2850 |
2853 \rationale{ which this prints 'A simple sum: 2 + 2 = 22' rather than 'A simple sum: 2 + 2 = 4'. | 2851 \rationale{ which this prints 'A simple sum: 2 + 2 = 22' rather than 'A simple sum: 2 + 2 = 4'. |
2854 However, the use the concatenation operation is still discouraged for efficienc y reasons. Instead, the recommended Dart idiom is to use string interpolation. | 2852 However, the use the concatenation operation is still discouraged for efficiency reasons. Instead, the recommended Dart idiom is to use string interpolation. |
eernst
2017/01/31 08:52:47
'the use [of?] the'
Lasse Reichstein Nielsen
2017/01/31 09:23:41
Done.
| |
2855 } | 2853 } |
2856 | 2854 |
2857 \begin{dartCode} | 2855 \begin{dartCode} |
2858 print("A simple sum: 2 + 2 = \$\{2+2\}"); | 2856 print("A simple sum: 2 + 2 = \$\{2+2\}"); |
2859 \end{dartCode} | 2857 \end{dartCode} |
2860 | 2858 |
2861 | 2859 |
2862 \rationale{String interpolation works well for most cases. The main situation wh ere it is not fully satisfactory is for string literals that are too large to fi t on a line. Multiline strings can be useful, but in some cases, we want to visu ally align the code. This can be expressed by writing smaller strings separated by whitespace, as shown here:} | 2860 \rationale{String interpolation works well for most cases. The main situation wh ere it is not fully satisfactory is for string literals that are too large to fi t on a line. Multiline strings can be useful, but in some cases, we want to visu ally align the code. This can be expressed by writing smaller strings separated by whitespace, as shown here:} |
2863 | 2861 |
2864 | 2862 |
2865 | 2863 |
2866 | 2864 |
2867 \begin{dartCode} | 2865 \begin{dartCode} |
2868 'Imagine this is a very long string that does not fit on a line. What shall we d o? ' | 2866 'Imagine this is a very long string that does not fit on a line. What shall we d o? ' |
2869 'Oh what shall we do? ' | 2867 'Oh what shall we do? ' |
2870 'We shall split it into pieces ' | 2868 'We shall split it into pieces ' |
2871 'like so'. | 2869 'like so'. |
2872 \end{dartCode} | 2870 \end{dartCode} |
2873 | 2871 |
2874 | 2872 |
2875 | 2873 |
2876 | 2874 |
2877 | 2875 |
2878 \begin{grammar} | 2876 \begin{grammar} |
2879 {\bf multilineString:}`{\escapegrammar \texttt{"""}}' stringContentTDQ* `{\es capegrammar \texttt{"""}}'; | 2877 {\bf multilineString:}`{\escapegrammar \texttt{"""}}' stringContentTDQ* `{\esc apegrammar \texttt{"""}}'; |
2880 `{\escapegrammar \code{'}\code{'}\code{'}}' stringContentTSQ* `{\escapegra mmar \code{'}\code{'}\code{'}}'; | 2878 `{\escapegrammar \code{'}\code{'}\code{'}}' stringContentTSQ* `{\escapegramm ar \code{'}\code{'}\code{'}}'; |
2881 `r' `{\escapegrammar \texttt{"""}}' (\~{} `{\escapegrammar \texttt{"""}}' )* `{\escapegrammar \texttt{"""}}'; | 2879 `r' `{\escapegrammar \texttt{"""}}' (\~{} `{\escapegrammar \texttt{"""}}')* `{\escapegrammar \texttt{"""}}'; |
2882 `r' `{\escapegrammar \code{'}\code{'}\code{'}}' (\~{} `{\escapegrammar \co de{'}\code{'}\code{'}}')* `{\escapegrammar \code{'}\code{'}\code{'}}' | 2880 `r' `{\escapegrammar \code{'}\code{'}\code{'}}' (\~{} `{\escapegrammar \code {'}\code{'}\code{'}}')* `{\escapegrammar \code{'}\code{'}\code{'}}' |
2883 . | 2881 . |
2884 | 2882 |
2885 | 2883 |
2886 {\bf ESCAPE\_SEQUENCE:} `$\backslash$ n'; | 2884 {\bf ESCAPE\_SEQUENCE:}`$\backslash$ n'; |
2887 `$\backslash$ r'; | 2885 `$\backslash$ r'; |
2888 `$\backslash$ f'; | 2886 `$\backslash$ f'; |
2889 `$\backslash$ b'; | 2887 `$\backslash$ b'; |
2890 `$\backslash$ t'; | 2888 `$\backslash$ t'; |
2891 `$\backslash$ v'; | 2889 `$\backslash$ v'; |
2892 `$\backslash$ x' HEX\_DIGIT HEX\_DIGIT; | 2890 `$\backslash$ x' HEX\_DIGIT HEX\_DIGIT; |
2893 `$\backslash$ u' HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT; | 2891 `$\backslash$ u' HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT; |
2894 `$\backslash$ u\{' HEX\_DIGIT\_SEQUENCE `\}' | 2892 `$\backslash$ u\{' HEX\_DIGIT\_SEQUENCE `\}' |
2895 . | 2893 . |
2896 | 2894 |
2897 {\bf HEX\_DIGIT\_SEQUENCE:} | 2895 {\bf HEX\_DIGIT\_SEQUENCE:} |
2898 HEX\_DIGIT HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? | 2896 HEX\_DIGIT HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? |
2899 . | 2897 . |
2900 | 2898 |
2901 \end{grammar} | 2899 \end{grammar} |
2902 | 2900 |
2903 \LMHash{} | 2901 \LMHash{} |
2904 Multiline strings are delimited by either matching triples of single quotes or m atching triples of double quotes. If the first line of a multiline string consis ts solely of the whitespace characters defined by the production {\em WHITESPACE } \ref{lexicalRules}), possibly prefixed by $\backslash$, then that line is ign ored, including the new line at its end. | 2902 Multiline strings are delimited by either matching triples of single quotes or m atching triples of double quotes. If the first line of a multiline string consis ts solely of the whitespace characters defined by the production {\em WHITESPACE } \ref{lexicalRules}), possibly prefixed by $\backslash$, then that line is igno red, including the line break at its end. |
2905 | 2903 |
2906 | 2904 \rationale{ |
2907 \rationale{ | 2905 The idea is to ignore a whitespace-only first line of a multiline string, where whitespace is defined as tabs, spaces and the final line break. These can be rep resented directly, but since for most characters prefixing by backslash is an id entity in a non-raw string, we allow those forms as well. |
2908 The idea is to ignore whitespace, where whitespace is defined as tabs, spaces a nd newlines. These can be represented directly, but since for most characters pr efixing by backslash is an identity, we allow those forms as well. | 2906 } |
2909 } | |
2910 | 2907 |
2911 % could be clearer. Is the first line in """\t | 2908 % could be clearer. Is the first line in """\t |
2912 % """ ignored not. It depends if we mean whitespace before escapes are inter preted, | 2909 % """ ignored not. It depends if we mean whitespace before escapes are inter preted, |
2913 % or after, or both. See https://code.google.com/p/dart/issues/detail?id=23020 | 2910 % or after, or both. See https://code.google.com/p/dart/issues/detail?id=23020 |
2914 | 2911 |
2915 \LMHash{} | 2912 \LMHash{} |
2916 Strings support escape sequences for special characters. The escapes are: | 2913 Strings support escape sequences for special characters. The escapes are: |
2917 \begin{itemize} | 2914 \begin{itemize} |
2918 \item $\backslash$n for newline, equivalent to $\backslash$x0A. | 2915 \item $\backslash$n for newline, equivalent to $\backslash$x0A. |
2919 \item $\backslash$r for carriage return, equivalent to $\backslash$x0D. | 2916 \item $\backslash$r for carriage return, equivalent to $\backslash$x0D. |
2920 \item $\backslash$f for form feed, equivalent to $\backslash$x0C. | 2917 \item $\backslash$f for form feed, equivalent to $\backslash$x0C. |
2921 \item $\backslash$b for backspace, equivalent to $\backslash$x08. | 2918 \item $\backslash$b for backspace, equivalent to $\backslash$x08. |
2922 \item $\backslash$t for tab, equivalent to $\backslash$x09. | 2919 \item $\backslash$t for tab, equivalent to $\backslash$x09. |
2923 \item $\backslash$v for vertical tab, equivalent to $\backslash$x0B | 2920 \item $\backslash$v for vertical tab, equivalent to $\backslash$x0B |
2924 \item $\backslash$x $HEX\_DIGIT_1$ $HEX\_DIGIT_2$, equivalent to | 2921 \item $\backslash$x $HEX\_DIGIT_1$ $HEX\_DIGIT_2$, equivalent to |
2925 | 2922 |
2926 $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$\}. | 2923 $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$\}. |
2927 \item $\backslash$u $HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\_DIGIT_4$, equivalent to $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\ _DIGIT_4$\}. | 2924 \item $\backslash$u $HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\_DIGIT_4$, equivalent to $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\ _DIGIT_4$\}. |
2928 \item $\backslash$u\{$HEX\_DIGIT\_SEQUENCE$\} is the Unicode code point represen ted by the $HEX\_DIGIT\_SEQUENCE$. It is a compile-time error if the value of th e $HEX\_DIGIT\_SEQUENCE$ is not a valid Unicode code point. | 2925 \item $\backslash$u\{$HEX\_DIGIT\_SEQUENCE$\} is the Unicode code point represen ted by the $HEX\_DIGIT\_SEQUENCE$. It is a compile-time error if the value of th e $HEX\_DIGIT\_SEQUENCE$ is not a valid Unicode code point. |
2929 \item \$ indicating the beginning of an interpolated expression. | 2926 \item \$ indicating the beginning of an interpolated expression. |
2930 \item Otherwise, $\backslash k$ indicates the character $k$ for any $k$ not in $ \{n, r, f, b, t, v, x, u\}$. | 2927 \item Otherwise, $\backslash k$ indicates the character $k$ for any $k$ not in $ \{n, r, f, b, t, v, x, u\}$. |
2931 \end{itemize} | 2928 \end{itemize} |
2932 | 2929 |
2933 \LMHash{} | 2930 \LMHash{} |
2934 Any string may be prefixed with the character `r', indicating that it is a {\em raw string}, in which case no escapes or interpolations are recognized. | 2931 Any string may be prefixed with the character `r', indicating that it is a {\em raw string}, in which case no escapes or interpolations are recognized. |
2935 | 2932 |
2936 \LMHash{} | 2933 \LMHash{} |
2934 Line breaks in a multiline string are represented by the {\em NEWLINE} productio n. | |
2935 A line break introduces a single newline character into the string value. | |
2936 | |
2937 \LMHash{} | |
2937 It is a compile-time error if a non-raw string literal contains a character sequ ence of the form $\backslash$x that is not followed by a sequence of two hexadec imal digits. It is a compile-time error if a non-raw string literal contains a character sequence of the form $\backslash$u that is not followed by either a se quence of four hexadecimal digits, or by curly brace delimited sequence of hexad ecimal digits. | 2938 It is a compile-time error if a non-raw string literal contains a character sequ ence of the form $\backslash$x that is not followed by a sequence of two hexadec imal digits. It is a compile-time error if a non-raw string literal contains a character sequence of the form $\backslash$u that is not followed by either a se quence of four hexadecimal digits, or by curly brace delimited sequence of hexad ecimal digits. |
2938 | 2939 |
2939 | 2940 |
2940 | 2941 |
2941 \begin{grammar} | 2942 \begin{grammar} |
2942 {\bf stringContentDQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \texttt{"}}' $| $ `\$' $|$ NEWLINE ); | 2943 {\bf stringContentDQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \texttt{"}}' $| $ `\$' $|$ NEWLINE ); |
2943 `$\backslash$' \~{}( NEWLINE ); | 2944 `$\backslash$' \~{}( NEWLINE ); |
2944 stringInterpolation | 2945 stringInterpolation |
2945 . | 2946 . |
2946 | 2947 |
2947 {\bf stringContentSQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \texttt{'}}' $| $ `\$' $|$ NEWLINE ); | 2948 {\bf stringContentSQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \texttt{'}}' $| $ `\$' $|$ NEWLINE ); |
2948 `$\backslash$' \~{}( NEWLINE ); | 2949 `$\backslash$' \~{}( NEWLINE ); |
2949 stringInterpolation | 2950 stringInterpolation |
2950 . | 2951 . |
2951 | 2952 |
2952 | 2953 |
2953 {\bf stringContentTDQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \texttt{"""}} ' $|$ `\$'); | 2954 {\bf stringContentTDQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \texttt{"""}} ' $|$ `\$'); |
2954 stringInterpolation | 2955 stringInterpolation |
2955 . | 2956 . |
2956 | 2957 |
2957 {\bf stringContentTSQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \code{'}\code{ '}\code{'}}' $|$ `\$'); | 2958 {\bf stringContentTSQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \code{'}\code{ '}\code{'}}' $|$ `\$'); |
2958 stringInterpolation | 2959 stringInterpolation |
2959 . | 2960 . |
2960 | 2961 |
2961 {\bf NEWLINE:}$\backslash$ n; | 2962 {\bf NEWLINE:}$\backslash$ n; |
2962 $\backslash$ r | 2963 $\backslash$ r; |
2964 $\backslash$ r $\backslash$ n | |
2963 . | 2965 . |
2964 | 2966 |
2965 \end{grammar} | 2967 \end{grammar} |
2966 | 2968 |
2967 \LMHash{} | 2969 \LMHash{} |
2968 All string literals evaluate to instances of the built-in class \code{String}. | 2970 All string literals evaluate to instances of the built-in class \code{String}. |
2969 It is a compile-time error for a class to extend, mix in or implement \code{Stri ng}. | 2971 It is a compile-time error for a class to extend, mix in or implement \code{Stri ng}. |
2970 The static type of a string literal is \code{String}. | 2972 The static type of a string literal is \code{String}. |
2971 | 2973 |
2972 \subsubsection{String Interpolation} | 2974 \subsubsection{String Interpolation} |
(...skipping 5114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8087 | 8089 |
8088 The invariant that each normative paragraph is associated with a line | 8090 The invariant that each normative paragraph is associated with a line |
8089 containing the text \LMHash{} should be maintained. Extra occurrences | 8091 containing the text \LMHash{} should be maintained. Extra occurrences |
8090 of \LMHash{} can be added if needed, e.g., in order to make | 8092 of \LMHash{} can be added if needed, e.g., in order to make |
8091 individual \item{}s in itemized lists addressable. Each \LM.. command | 8093 individual \item{}s in itemized lists addressable. Each \LM.. command |
8092 must occur on a separate line. \LMHash{} must occur immediately | 8094 must occur on a separate line. \LMHash{} must occur immediately |
8093 before the associated paragraph, and \LMLabel must occur immediately | 8095 before the associated paragraph, and \LMLabel must occur immediately |
8094 after the associated \section{}, \subsection{} etc. | 8096 after the associated \section{}, \subsection{} etc. |
8095 | 8097 |
8096 ---------------------------------------------------------------------- | 8098 ---------------------------------------------------------------------- |
OLD | NEW |