diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/cmd/CommandLine.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/cmd/CommandLineParser.scala | 72 | ||||
-rw-r--r-- | src/compiler/scala/tools/cmd/Parser.scala | 52 | ||||
-rw-r--r-- | src/compiler/scala/tools/cmd/package.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/settings/MutableSettings.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/CommandLine.scala (renamed from src/compiler/scala/tools/nsc/util/CommandLineParser.scala) | 49 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/DirectTest.scala | 3 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/ConsoleRunner.scala | 4 | ||||
-rw-r--r-- | src/scaladoc/scala/tools/partest/ScaladocModelTest.scala | 2 |
9 files changed, 84 insertions, 104 deletions
diff --git a/src/compiler/scala/tools/cmd/CommandLine.scala b/src/compiler/scala/tools/cmd/CommandLine.scala index e8ac882ee6..e44752eb6e 100644 --- a/src/compiler/scala/tools/cmd/CommandLine.scala +++ b/src/compiler/scala/tools/cmd/CommandLine.scala @@ -16,7 +16,7 @@ trait CommandLineConfig { /** An instance of a command line, parsed according to a Spec. */ class CommandLine(val spec: Reference, val originalArgs: List[String]) extends CommandLineConfig { - def this(spec: Reference, line: String) = this(spec, Parser tokenize line) + def this(spec: Reference, line: String) = this(spec, CommandLineParser tokenize line) def this(spec: Reference, args: Array[String]) = this(spec, args.toList) import spec.{ isUnaryOption, isBinaryOption, isExpandOption } diff --git a/src/compiler/scala/tools/cmd/CommandLineParser.scala b/src/compiler/scala/tools/cmd/CommandLineParser.scala new file mode 100644 index 0000000000..ef55178594 --- /dev/null +++ b/src/compiler/scala/tools/cmd/CommandLineParser.scala @@ -0,0 +1,72 @@ +/* NEST (New Scala Test) + * Copyright 2007-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools +package cmd + +import scala.annotation.tailrec + +/** A simple (overly so) command line parser. + * !!! This needs a thorough test suite to make sure quoting is + * done correctly and portably. + */ +object CommandLineParser { + // splits a string into a quoted prefix and the rest of the string, + // taking escaping into account (using \) + // `"abc"def` will match as `DoubleQuoted(abc, def)` + private class QuotedExtractor(quote: Char) { + def unapply(in: String): Option[(String, String)] = { + val del = quote.toString + if (in startsWith del) { + var escaped = false + val (quoted, next) = (in substring 1) span { + case `quote` if !escaped => false + case '\\' if !escaped => escaped = true; true + case _ => escaped = false; true + } + // the only way to get out of the above loop is with an empty next or !escaped + // require(next.isEmpty || !escaped) + if (next startsWith del) Some((quoted, next substring 1)) + else None + } else None + } + } + private object DoubleQuoted extends QuotedExtractor('"') + private object SingleQuoted extends QuotedExtractor('\'') + private val Word = """(\S+)(.*)""".r + + // parse `in` for an argument, return it and the remainder of the input (or an error message) + // (argument may be in single/double quotes, taking escaping into account, quotes are stripped) + private def argument(in: String): Either[String, (String, String)] = in match { + case DoubleQuoted(arg, rest) => Right(arg, rest) + case SingleQuoted(arg, rest) => Right(arg, rest) + case Word(arg, rest) => Right(arg, rest) + case _ => Left("Illegal argument: "+ in) + } + + // parse a list of whitespace-separated arguments (ignoring whitespace in quoted arguments) + @tailrec private def commandLine(in: String, accum: List[String] = Nil): Either[String, (List[String], String)] = { + val trimmed = in.trim + if (trimmed.isEmpty) Right(accum.reverse, "") + else argument(trimmed) match { + case Right((arg, next)) => + (next span Character.isWhitespace) match { + case("", rest) if rest.nonEmpty => Left("Arguments should be separated by whitespace.") // TODO: can this happen? + case(ws, rest) => commandLine(rest, arg :: accum) + } + case Left(msg) => Left(msg) + } + } + + class ParseException(msg: String) extends RuntimeException(msg) + + def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x)) + def tokenize(line: String, errorFn: String => Unit): List[String] = { + commandLine(line) match { + case Right((args, _)) => args + case Left(msg) => errorFn(msg) ; Nil + } + } +} diff --git a/src/compiler/scala/tools/cmd/Parser.scala b/src/compiler/scala/tools/cmd/Parser.scala deleted file mode 100644 index 6e2afa41c4..0000000000 --- a/src/compiler/scala/tools/cmd/Parser.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* NEST (New Scala Test) - * Copyright 2007-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools -package cmd - -import scala.util.parsing.combinator._ -import scala.util.parsing.input.CharArrayReader.EofCh - -/** A simple (overly so) command line parser. - * !!! This needs a thorough test suite to make sure quoting is - * done correctly and portably. - */ -trait ParserUtil extends Parsers { - class ParserPlus[+T](underlying: Parser[T]) { - def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b } - def <~![U](p: => Parser[U]): Parser[T] = (underlying ~! p) ^^ { case a~b => a } - } - protected implicit def parser2parserPlus[T](p: Parser[T]): ParserPlus[T] = new ParserPlus(p) -} - -object Parser extends RegexParsers with ParserUtil { - override def skipWhitespace = false - - def elemExcept(xs: Elem*): Parser[Elem] = elem("elemExcept", x => x != EofCh && !(xs contains x)) - def elemOf(xs: Elem*): Parser[Elem] = elem("elemOf", xs contains _) - def escaped(ch: Char): Parser[String] = "\\" + ch - def mkQuoted(ch: Char): Parser[String] = ( - elem(ch) !~> rep(escaped(ch) | elemExcept(ch)) <~ ch ^^ (_.mkString) - | failure("Unmatched %s in input." format ch) - ) - - /** Apparently windows can't deal with the quotes sticking around. */ - lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x) - lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"") - lazy val token: Parser[String] = """\S+""".r - - lazy val argument: Parser[String] = squoted | dquoted | token - lazy val commandLine: Parser[List[String]] = phrase(repsep(argument, whiteSpace)) - - class ParseException(msg: String) extends RuntimeException(msg) - - def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x)) - def tokenize(line: String, errorFn: String => Unit): List[String] = { - parse(commandLine, line.trim) match { - case Success(args, _) => args - case NoSuccess(msg, rest) => errorFn(msg) ; Nil - } - } -} diff --git a/src/compiler/scala/tools/cmd/package.scala b/src/compiler/scala/tools/cmd/package.scala index c62a977950..7d67fa738b 100644 --- a/src/compiler/scala/tools/cmd/package.scala +++ b/src/compiler/scala/tools/cmd/package.scala @@ -22,7 +22,7 @@ package object cmd { def toOpt(s: String) = if (s startsWith "--") s else "--" + s def fromOpt(s: String) = s stripPrefix "--" - def toArgs(line: String) = Parser tokenize line + def toArgs(line: String) = CommandLineParser tokenize line def fromArgs(args: List[String]) = args mkString " " def stripQuotes(s: String) = { diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index cd23ad74e4..b5cc89c0c8 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -107,7 +107,7 @@ class MutableSettings(val errorFn: String => Unit) /** Split the given line into parameters. */ - def splitParams(line: String) = cmd.Parser.tokenize(line, errorFn) + def splitParams(line: String) = cmd.CommandLineParser.tokenize(line, errorFn) /** Returns any unprocessed arguments. */ diff --git a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala b/src/compiler/scala/tools/nsc/util/CommandLine.scala index e8f962a9e2..ef28f6dc53 100644 --- a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala +++ b/src/compiler/scala/tools/nsc/util/CommandLine.scala @@ -3,27 +3,16 @@ * @author Paul Phillips */ -package scala.tools.nsc -package util +package scala.tools +package nsc.util -import scala.util.parsing.combinator._ -import scala.util.parsing.input.CharArrayReader.EofCh import scala.collection.mutable.ListBuffer -/** A simple command line parser to replace the several different - * simple ones spread around trunk. - * +/** * XXX Note this has been completely obsolesced by scala.tools.cmd. * I checked it back in as part of rolling partest back a month * rather than go down the rabbit hole of unravelling dependencies. */ - -trait ParserUtil extends Parsers { - protected implicit class ParserPlus[+T](underlying: Parser[T]) { - def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b } - } -} - case class CommandLine( args: List[String], unaryArguments: List[String], @@ -31,7 +20,7 @@ case class CommandLine( ) { def this(args: List[String]) = this(args, Nil, Nil) def this(args: Array[String]) = this(args.toList, Nil, Nil) - def this(line: String) = this(CommandLineParser tokenize line, Nil, Nil) + def this(line: String) = this(cmd.CommandLineParser tokenize line, Nil, Nil) def withUnaryArgs(xs: List[String]) = copy(unaryArguments = xs) def withBinaryArgs(xs: List[String]) = copy(binaryArguments = xs) @@ -107,33 +96,3 @@ case class CommandLine( override def toString() = "CommandLine(\n%s)\n" format (args map (" " + _ + "\n") mkString) } - -object CommandLineParser extends RegexParsers with ParserUtil { - override def skipWhitespace = false - - def elemExcept(xs: Elem*): Parser[Elem] = elem("elemExcept", x => x != EofCh && !(xs contains x)) - def escaped(ch: Char): Parser[String] = "\\" + ch - def mkQuoted(ch: Char): Parser[String] = ( - elem(ch) !~> rep(escaped(ch) | elemExcept(ch)) <~ ch ^^ (_.mkString) - | failure("Unmatched %s in input." format ch) - ) - - /** Apparently windows can't deal with the quotes sticking around. */ - lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x) - lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"") - lazy val token: Parser[String] = """\S+""".r - - lazy val argument: Parser[String] = squoted | dquoted | token - lazy val commandLine: Parser[List[String]] = phrase(repsep(argument, whiteSpace)) - - class ParseException(msg: String) extends RuntimeException(msg) - - def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x)) - def tokenize(line: String, errorFn: String => Unit): List[String] = { - parse(commandLine, line.trim) match { - case Success(args, _) => args - case NoSuccess(msg, rest) => errorFn(msg) ; Nil - } - } - def apply(line: String) = new CommandLine(tokenize(line)) -} diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 953b5e5535..2e6c3baa02 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -7,8 +7,9 @@ package scala.tools.partest import scala.tools.nsc._ import settings.ScalaVersion -import util.{ SourceFile, BatchSourceFile, CommandLineParser } +import util.{ SourceFile, BatchSourceFile } import reporters.{Reporter, ConsoleReporter} +import scala.tools.cmd.CommandLineParser /** A class for testing code which is embedded as a string. * It allows for more complete control over settings, compiler diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala index 8161e53bf9..33bf836a7b 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala @@ -9,7 +9,7 @@ package nest import utils.Properties._ import scala.tools.nsc.Properties.{ versionMsg, setProp } -import scala.tools.nsc.util.CommandLineParser +import scala.tools.nsc.util.CommandLine import scala.collection.{ mutable, immutable } import PathSettings.srcDir import TestKinds._ @@ -97,7 +97,7 @@ class ConsoleRunner extends DirectRunner { ) def main(argstr: String) { - val parsed = CommandLineParser(argstr) withUnaryArgs unaryArgs withBinaryArgs binaryArgs + val parsed = (new CommandLine(argstr)) withUnaryArgs unaryArgs withBinaryArgs binaryArgs if (parsed isSet "--debug") NestUI.setDebug() if (parsed isSet "--verbose") NestUI.setVerbose() diff --git a/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala b/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala index f0a9caac15..70423cc7dc 100644 --- a/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala +++ b/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala @@ -7,7 +7,7 @@ package scala.tools.partest import scala.tools.nsc import scala.tools.nsc._ -import scala.tools.nsc.util.CommandLineParser +import scala.tools.cmd.CommandLineParser import scala.tools.nsc.doc.{ DocFactory, Universe } import scala.tools.nsc.doc.model._ import scala.tools.nsc.doc.model.diagram._ |