Skip to main content

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 of loc 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 the home:/// 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:///|)
  1. parses the path using the grammar for Unix Path
  2. 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.
  3. 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|;