diff --git a/src/usexp/lexer.mll b/src/usexp/lexer.mll index 521ac18b..8e6a032b 100644 --- a/src/usexp/lexer.mll +++ b/src/usexp/lexer.mll @@ -56,6 +56,10 @@ type escape_sequence = | Other let escaped_buf = Buffer.create 256 + +type block_string_line_kind = + | With_escape_sequences + | Raw } let comment = ';' [^ '\n' '\r']* @@ -143,7 +147,8 @@ and quoted_string_after_escaped_newline strict = parse and escape_sequence strict = parse | newline - { Newline } + { Lexing.new_line lexbuf; + Newline } | ['\\' '\'' '"' 'n' 't' 'b' 'r'] as c { let c = match c with @@ -223,7 +228,7 @@ and token = parse | '"' { Buffer.clear escaped_buf; let start = Lexing.lexeme_start_p lexbuf in - let s = quoted_string true lexbuf in + let s = dune_quoted_string lexbuf in lexbuf.lex_start_p <- start; Quoted_string s } @@ -231,3 +236,71 @@ and token = parse { Token.Atom (A s) } | eof { Eof } + +and dune_quoted_string = parse + | "\\|" + { block_string_start With_escape_sequences lexbuf } + | "\\>" + { block_string_start Raw lexbuf } + | "" + { quoted_string true lexbuf } + +and block_string_start kind = parse + | newline as s + { Lexing.new_line lexbuf; + Buffer.add_string escaped_buf s; + block_string_after_newline lexbuf + } + | ' ' + { match kind with + | With_escape_sequences -> block_string lexbuf + | Raw -> raw_block_string lexbuf + } + | eof + { Buffer.contents escaped_buf + } + | _ + { error lexbuf "There must be at least one space after \"\\|" + } + +and block_string = parse + | newline as s + { Lexing.new_line lexbuf; + Buffer.add_string escaped_buf s; + block_string_after_newline lexbuf + } + | '\\' + { match escape_sequence true lexbuf with + | Newline -> block_string_after_newline lexbuf + | Other -> block_string lexbuf + } + | _ as c + { Buffer.add_char escaped_buf c; + block_string lexbuf + } + | eof + { Buffer.contents escaped_buf + } + +and block_string_after_newline = parse + | blank* "\"\\|" + { block_string_start With_escape_sequences lexbuf } + | blank* "\"\\>" + { block_string_start Raw lexbuf } + | "" + { Buffer.contents escaped_buf + } + +and raw_block_string = parse + | newline as s + { Lexing.new_line lexbuf; + Buffer.add_string escaped_buf s; + block_string_after_newline lexbuf + } + | _ as c + { Buffer.add_char escaped_buf c; + raw_block_string lexbuf + } + | eof + { Buffer.contents escaped_buf + } diff --git a/test/blackbox-tests/dune.inc b/test/blackbox-tests/dune.inc index c569397a..89e6c0d8 100644 --- a/test/blackbox-tests/dune.inc +++ b/test/blackbox-tests/dune.inc @@ -14,6 +14,14 @@ test-cases/bad-alias-error (progn (run ${exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))) +(alias + ((name block-strings) + (deps ((package dune) (files_recursively_in test-cases/block-strings))) + (action + (chdir + test-cases/block-strings + (progn (run ${exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))) + (alias ((name byte-code-only) (deps ((package dune) (files_recursively_in test-cases/byte-code-only))) @@ -521,6 +529,7 @@ (deps ((alias aliases) (alias bad-alias-error) + (alias block-strings) (alias byte-code-only) (alias c-stubs) (alias configurator) @@ -583,6 +592,7 @@ (deps ((alias aliases) (alias bad-alias-error) + (alias block-strings) (alias byte-code-only) (alias c-stubs) (alias configurator) diff --git a/test/blackbox-tests/test-cases/block-strings/dune b/test/blackbox-tests/test-cases/block-strings/dune new file mode 100644 index 00000000..184b58dd --- /dev/null +++ b/test/blackbox-tests/test-cases/block-strings/dune @@ -0,0 +1,48 @@ +; Example script taken from re2 + +; With normal strings +(alias + ((name old) + (action (echo "\ +ARFLAGS=rsc +CXX=g++ +CXXFLAGS=\"-Wall -O3 -g -pthread\" +if ! ${.ARCH_SIXTYFOUR}; then + CXX=\"$CXX -m32\" +fi +${.MAKE} -s -C libre2 clean +${.MAKE} -s -C libre2 \\ + ARFLAGS=\"$ARFLAGS\" \\ + CXX=\"$CXX\" \\ + CXXFLAGS=\"$CXXFLAGS\" \\ + obj/libre2.a obj/so/libre2.so +cp libre2/obj/libre2.a libre2_c_stubs.a +cp libre2/obj/so/libre2.so dllre2_c_stubs.so +${.MAKE} -s -C libre2 clean +")))) + +; With block strings +(alias + ((name new) + (action (echo "\> ARFLAGS=rsc + "\> CXX=g++ + "\> CXXFLAGS="-Wall -O3 -g -pthread" + "\> if ! ${.ARCH_SIXTYFOUR}; then + "\> CXX="$CXX -m32" + "\> fi + "\> ${.MAKE} -s -C libre2 clean + "\> ${.MAKE} -s -C libre2 \ + "\> ARFLAGS="$ARFLAGS" \ + "\> CXX="$CXX" \ + "\> CXXFLAGS="$CXXFLAGS" \ + "\> obj/libre2.a obj/so/libre2.so + "\> cp libre2/obj/libre2.a libre2_c_stubs.a + "\> cp libre2/obj/so/libre2.so dllre2_c_stubs.so + "\> ${.MAKE} -s -C libre2 clean +)))) + +(alias + ((name quoting-test) + (action (echo "\| normal: \065 + "\> raw: \065 +)))) diff --git a/test/blackbox-tests/test-cases/block-strings/run.t b/test/blackbox-tests/test-cases/block-strings/run.t new file mode 100644 index 00000000..31be3a1e --- /dev/null +++ b/test/blackbox-tests/test-cases/block-strings/run.t @@ -0,0 +1,37 @@ + $ dune build @old + ARFLAGS=rsc + CXX=g++ + CXXFLAGS="-Wall -O3 -g -pthread" + if ! ${.ARCH_SIXTYFOUR}; then + CXX="$CXX -m32" + fi + ${.MAKE} -s -C libre2 clean + ${.MAKE} -s -C libre2 \ + ARFLAGS="$ARFLAGS" \ + CXX="$CXX" \ + CXXFLAGS="$CXXFLAGS" \ + obj/libre2$ext_lib obj/so/libre2$ext_dll + cp libre2/obj/libre2$ext_lib libre2_c_stubs$ext_lib + cp libre2/obj/so/libre2$ext_dll dllre2_c_stubs$ext_dll + ${.MAKE} -s -C libre2 clean + + $ dune build @new + ARFLAGS=rsc + CXX=g++ + CXXFLAGS="-Wall -O3 -g -pthread" + if ! ${.ARCH_SIXTYFOUR}; then + CXX="$CXX -m32" + fi + ${.MAKE} -s -C libre2 clean + ${.MAKE} -s -C libre2 \ + ARFLAGS="$ARFLAGS" \ + CXX="$CXX" \ + CXXFLAGS="$CXXFLAGS" \ + obj/libre2$ext_lib obj/so/libre2$ext_dll + cp libre2/obj/libre2$ext_lib libre2_c_stubs$ext_lib + cp libre2/obj/so/libre2$ext_dll dllre2_c_stubs$ext_dll + ${.MAKE} -s -C libre2 clean + + $ dune build @quoting-test + normal: A + raw: \065