module lang::paths::Unix
rascal-0.40.16
Defines the syntax of filesystem and network drive paths on DOS and Windows Systems.
Usage
import lang::paths::Unix;
Dependencies
import ParseTree;
Description
This syntax definition of POSIX paths and file names, including some of the conventions with ~ for the home folder and . and .. for relative directories.
The main function of this module, Parse Unix Path:
- faithfully maps any syntactically correctly Unix paths to syntactically correct
loc
values. - throws a ParseError if the path does not comply.
- ensures that if the file exists on system A, then the
loc
representation resolves to the same file on system A via any IO function. - and nothing more. No normalization, no interpretatioon of
.
and..
, no changing of cases. This is left to downstream processors ofloc
values, if necessary. The current transformation is purely syntactical, and tries to preserve the semantics of the path as much as possible.
Pitfalls
- the
~
notation is typically a feature of the shell and not of system paths. However it is so commonly used to refer to the home directories of users that we've added an interpretation here with thehome:///
scheme. - otherwise, the path syntax may be different from what you have to type in bash or zsh. This is because shells need to reserve characters, like spaces, for different purposes (commandline argument separation). The current definition is about the path notation that shells like zsh and bash, and other programs, have to pass into the string arguments of OS features, after their own concatenation, splicing, variable expansion, de-escaping and unquoting routines have finished..
syntax UnixPath
lexical UnixPath
= absolute: Slashes UnixFilePath?
| relative: UnixFilePath
| home : "~" (Slashes UnixFilePath)?
| user : "~" UserName uname (Slashes UnixFilePath)?
;
syntax UserName
lexical UserName = ![/~]+;
syntax PathChar
lexical PathChar = ![/];
syntax PathSegment
lexical PathSegment
= current: "."
| parent : ".."
| pname : (PathChar \ "~" PathChar*) \ ".." \ "." \ "~"
;
syntax Slashes
lexical Slashes = Slash+ !>> [/];
syntax Slash
lexical Slash = [/];
syntax UnixFilePath
lexical UnixFilePath = {PathSegment Slashes}+ segments Slashes?;
function parseUnixPath
Convert a Unix path literal to a source location URI.
loc parseUnixPath(str input, loc src=|unknown:///|)
- parses the path using the grammar for Unix Path
- takes the literal name components using string interpolation
"<segment>"
. This means no decoding/encoding happens at all while extracting hostname, share name and path segment names. Also all superfluous path separators are skipped. - uses
loc + str
path concatenation with its builtin character encoding to construct the URI. Also the right path separators are introduced.
function mapPathToLoc
Root is a special case.
loc mapPathToLoc((UnixPath) `<Slashes _>`)
function mapPathToLoc
Absolute: given the drive and relative to its root.
loc mapPathToLoc((UnixPath) `<Slashes _><UnixFilePath path>`)
function mapPathToLoc
Relative: relative to the current working directory.
loc mapPathToLoc((UnixPath) `<UnixFilePath path>`)
function mapPathToLoc
Home relative: relative to the current users home directory.
loc mapPathToLoc((UnixPath) `~<Slash _><UnixFilePath path>`)
function mapPathToLoc
Home relative: relative to the current users home directory.
loc mapPathToLoc((UnixPath) `~`)
function mapPathToLoc
User relative: relative to any specific user's home directory.
loc mapPathToLoc((UnixPath) `~<UserName uname><Slash _><UnixFilePath path>`)
function mapPathToLoc
User relative: relative to any specific user's home directory.
loc mapPathToLoc((UnixPath) `~<UserName uname>`)
function appendPath
loc appendPath(loc root, UnixFilePath path)
Tests
test root
test bool root()
= parseUnixPath("/") == |file:///|;
test absolutePath
test bool absolutePath()
= parseUnixPath("/usr/local/bin")
== |file:///usr/local/bin|;
test relativePath
test bool relativePath()
= parseUnixPath(".bash_rc")
== |cwd:///.bash_rc|;
test homePath
test bool homePath()
= parseUnixPath("~/.bash_profile")
== |home:///.bash_profile|;
test userPath
test bool userPath()
= parseUnixPath("~root/.bash_profile")
== |home:///../root/.bash_profile|;