github.com/madlambda/nash@v0.2.2-0.20230113003044-f2284521680b/spec.ebnf (about) 1 /* Nash program */ 2 program = { statement } . 3 4 /* Statement */ 5 statement = varDecl | command | fnInv | builtin | comment . 6 7 /* Variable declaration */ 8 varDecl = assignValue | assignCmdOut . 9 assignValue = identifierList "=" varSpecList . 10 identifierList = identifier [ "," identifierList ] . 11 varSpecList = varSpec [ "," varSpecList ] . 12 varSpec = ( list | string ) . 13 string = stringLit | ( stringConcat { stringConcat } ) . 14 assignCmdOut = identifier "<=" ( command | fnInv ) . 15 16 /* Command */ 17 command = ( [ "(" ] cmdpart [ ")" ] | pipe ) . 18 cmdpart = [ "-" ] ( cmdname | abscmd ) { argument } { redirect } . 19 cmdname = identifier . 20 abscmd = filename . 21 argument = ( unicode_char { unicode_char } ) | stringLit . 22 pipe = [ "(" ] cmdpart "|" cmdpart [ { "|" cmdpart } ] [ ")" ] . 23 redirect = ( ">" ( filename | uri | variable ) | 24 ">" "[" unicode_digit "]" ( filename | uri | variable ) | 25 ">" "[" unicode_digit "=" ( unicode_digit | identifier ) "]" | 26 ">" "[" unicode_digit "=" "]" ) . 27 28 /* Builtin */ 29 builtin = importDecl | rforkDecl | ifDecl | forDecl | setenvDecl | 30 fnDecl | bindfn | dump . 31 32 /* Import statement */ 33 importDecl = "import" ( filename | stringLit ) . 34 35 /* Rfork scope */ 36 rforkDecl = "rfork" rforkFlags "{" program "}" . 37 rforkFlags = { identifier } . 38 39 /* If-else-if */ 40 ifDecl = "if" ( variable | string ) comparison 41 ( variable | string ) "{" program "}" 42 [ "else" "{" program "}" ] 43 [ "else" ifDecl ] . 44 45 /* For loop */ 46 forDecl = "for" [ identifier "in" ( list | variable | fnInv) ] "{" program "}" . 47 48 /* Function declaration */ 49 fnDecl = "fn" identifier "(" fnArgs ")" "{" 50 program [ returnDecl ] 51 "}" . 52 fnArgs = { fnArg [ "," ] } . 53 fnArg = identifier [ "..." ] . 54 55 /* return declaration */ 56 returnDecl = "return" [ ( variable | stringLit | list | fnInv ) ] . 57 58 /* Function invocation */ 59 fnInv = ( variable | identifier ) "(" fnArgValues ")" . 60 61 fnArgValues = { fnArgValue [ "," ] } . 62 fnArgValue = [ stringLit | stringConcat | list | (variable [ "..." ]) | (list [ "..." ]) fnInv ] . 63 64 /* Function binding */ 65 bindfn = "bindfn" identifier identifier . 66 67 /* dump shell state */ 68 dump = "dump" [ filename ] . 69 70 /* Set environment variable */ 71 setenvDecl = "setenv" ( identifier | varDecl ) . 72 73 /* Comment */ 74 comment = "#" { unicode_char } . 75 76 /* Lists */ 77 list = "(" { argument } ")" . 78 79 letter = unicode_letter | "_" . 80 filename = { [ "/" ] { unicode_letter } } . 81 ipaddr = unicode_digit { unicode_digit } "." 82 unicode_digit { unicode_digit } "." 83 unicode_digit { unicode_digit } "." 84 unicode_digit { unicode_digit } "." . 85 port = unicode_digit { unicode_digit } . 86 networkaddr = ipaddr ":" port . 87 location = filename | networkaddr . 88 schema = "file" | "tcp" | "udp" | "unix" . 89 uri = schema "://" location . 90 91 identifier = letter { letter | unicode_digit } . 92 variable = "$" identifier . 93 94 comparison = "==" | "!=" . 95 96 stringLit = "\"" { unicode_char | newline } "\"" . 97 98 stringConcat = ( stringLit | variable ) "+" (stringLit | variable ) . 99 100 /* terminals */ 101 newline = /* the Unicode code point U+000A */ . 102 unicode_char = /* an arbitrary Unicode code point except newline */ . 103 unicode_letter = /* a Unicode code point classified as "Letter" */ . 104 unicode_digit = /* a Unicode code point classified as "Number, decimal digit" */ .