224 lines
7.7 KiB
BNF
224 lines
7.7 KiB
BNF
|
!whitespace : ' ' | '\t' | '\n' | '\r' ;
|
||
|
|
||
|
_letter : 'a'-'z' 'A'-'Z' ;
|
||
|
_digit : '0'-'9' ;
|
||
|
|
||
|
number : _digit {_digit} ;
|
||
|
word /*BAD*/ : _letter {_letter | '_'} ;
|
||
|
nothing : . ;
|
||
|
|
||
|
name : ( _letter | '_' ) { _letter | '_' | _digit } ;
|
||
|
|
||
|
<< import "github.com/localhots/penny/ast" >>
|
||
|
|
||
|
/* Tokens */
|
||
|
|
||
|
Word
|
||
|
: word << ast.NewWord($0) >>
|
||
|
;
|
||
|
IoNumber
|
||
|
: number << ast.NewIoNumber($0) >>
|
||
|
;
|
||
|
|
||
|
/* Commands */
|
||
|
|
||
|
/*
|
||
|
CompleteCommand
|
||
|
: List Separator
|
||
|
| List
|
||
|
;
|
||
|
*/
|
||
|
AssignmentWord
|
||
|
: Word "=" Word << ast.NewAssignment($0, $2) >>
|
||
|
;
|
||
|
List
|
||
|
: List SeparatorOp AndOr << ast.AppendToList($0, $2) >>
|
||
|
| AndOr << ast.NewList($0) >>
|
||
|
;
|
||
|
AndOr
|
||
|
: Pipeline << ast.NewAndOr($0) >>
|
||
|
| AndOr "&&" Linebreak Pipeline << ast.AppendAnd($0, $3) >>
|
||
|
| AndOr "||" Linebreak Pipeline << ast.AppendOr($0, $3) >>
|
||
|
;
|
||
|
Pipeline
|
||
|
: PipeSequence << ast.NewPipeline($1, false) >>
|
||
|
| "!" PipeSequence << ast.NewPipeline($1, true) >>
|
||
|
;
|
||
|
PipeSequence
|
||
|
: Command << ast.NewPipeSequence($0) >>
|
||
|
| PipeSequence "|" Linebreak Command << ast.AppendToPipeSequence($0, $3) >>
|
||
|
;
|
||
|
Command
|
||
|
: SimpleCommand << ast.NewCommand($0, nil) >>
|
||
|
| CompoundCommand << ast.NewCommand($0, nil) >>
|
||
|
| CompoundCommand RedirectList << ast.NewCommand($0, $1) >>
|
||
|
| FunctionDefinition << ast.NewCommand($0, nil) >>
|
||
|
;
|
||
|
CompoundCommand
|
||
|
: BraceGroup << ast.NewCompoundCommand($0) >>
|
||
|
| Subshell << ast.NewCompoundCommand($0) >>
|
||
|
| ForClause << ast.NewCompoundCommand($0) >>
|
||
|
| CaseClause << ast.NewCompoundCommand($0) >>
|
||
|
| IfClause << ast.NewCompoundCommand($0) >>
|
||
|
| WhileClause << ast.NewCompoundCommand($0) >>
|
||
|
| UntilClause << ast.NewCompoundCommand($0) >>
|
||
|
;
|
||
|
Subshell
|
||
|
: "(" CompoundList ")" << ast.NewSubshell($1) >>
|
||
|
;
|
||
|
CompoundList
|
||
|
: Term << ast.NewCompoundList($0, nil) >>
|
||
|
| NewlineList Term << ast.NewCompoundList($1, $2) >>
|
||
|
| Term Separator << ast.NewCompoundList($0, $1) >>
|
||
|
| NewlineList Term Separator << ast.NewCompoundList($1, $2) >>
|
||
|
;
|
||
|
Term
|
||
|
: Term Separator AndOr << ast.AppendToTerm($0, $2, $1) >>
|
||
|
| AndOr << ast.NewTerm($0) >>
|
||
|
;
|
||
|
ForClause
|
||
|
: "for" Name Linebreak DoGroup << ast.NewForClause($1, ast.Wordlist{}, $3) >>
|
||
|
| "for" Name Linebreak "in" SequentialSep DoGroup << ast.NewForClause($1, ast.Wordlist{}, $5) >>
|
||
|
| "for" Name Linebreak "in" Wordlist SequentialSep DoGroup << ast.NewForClause($1, $4, $6) >>
|
||
|
;
|
||
|
Name
|
||
|
: name << ast.NewName($0) >> /* Apply rule 5 */
|
||
|
;
|
||
|
Wordlist
|
||
|
: Wordlist Word << ast.AppendToWordlist($0, $1) >>
|
||
|
| Word << ast.NewWordlist($0) >>
|
||
|
;
|
||
|
CaseClause
|
||
|
: "case" Word Linebreak "in" Linebreak CaseList "esac" << ast.NewCaseClause($1, $5) >>
|
||
|
| "case" Word Linebreak "in" Linebreak CaseListNs "esac" << ast.NewCaseClause($1, $5) >>
|
||
|
| "case" Word Linebreak "in" Linebreak "esac" << ast.NewCaseClause($1, ast.CaseList{}) >>
|
||
|
;
|
||
|
CaseListNs
|
||
|
: CaseList CaseItemNs << ast.AppendToCaseList($0, $1) >>
|
||
|
| CaseItemNs << ast.NewCaseList($0) >>
|
||
|
;
|
||
|
CaseList
|
||
|
: CaseList CaseItem << ast.AppendToCaseList($0, $1) >>
|
||
|
| CaseItem << ast.NewCaseList($0) >>
|
||
|
;
|
||
|
CaseItemNs
|
||
|
: Pattern ")" Linebreak << ast.NewCaseItem($0, nil) >>
|
||
|
| Pattern ")" CompoundList Linebreak << ast.NewCaseItem($0, $2) >>
|
||
|
| "(" Pattern ")" Linebreak << ast.NewCaseItem($1, nil) >>
|
||
|
| "(" Pattern ")" CompoundList Linebreak << ast.NewCaseItem($1, $3) >>
|
||
|
;
|
||
|
CaseItem
|
||
|
: Pattern ")" Linebreak ";;" Linebreak << ast.NewCaseItem($0, nil) >>
|
||
|
| Pattern ")" CompoundList ";;" Linebreak << ast.NewCaseItem($0, $2) >>
|
||
|
| "(" Pattern ")" Linebreak ";;" Linebreak << ast.NewCaseItem($1, nil) >>
|
||
|
| "(" Pattern ")" CompoundList ";;" Linebreak << ast.NewCaseItem($1, $3) >>
|
||
|
;
|
||
|
Pattern
|
||
|
: Word << ast.NewPattern($0) >> /* Apply rule 4 */
|
||
|
| Pattern "|" Word << ast.AppendToPattern($0, $2) >> /* Do not apply rule 4 */
|
||
|
;
|
||
|
IfClause
|
||
|
: "if" CompoundList "then" CompoundList ElsePart "fi" << ast.NewIfClause($1, $3, $4) >>
|
||
|
| "if" CompoundList "then" CompoundList "fi" << ast.NewIfClause($1, $3, nil) >>
|
||
|
;
|
||
|
ElsePart
|
||
|
: "elif" CompoundList "then" ElsePart << ast.NewIfClause($1, nil, $3) >>
|
||
|
| "else" CompoundList << ast.NewIfClause(nil, $1, nil) >>
|
||
|
;
|
||
|
WhileClause
|
||
|
: "while" CompoundList DoGroup << ast.NewWhileClause($1, $2) >>
|
||
|
;
|
||
|
UntilClause
|
||
|
: "until" CompoundList DoGroup << ast.NewUntilClause($1, $2) >>
|
||
|
;
|
||
|
FunctionDefinition
|
||
|
: FunctionName "(" ")" Linebreak FunctionBody << ast.NewFunctionDefinition($0, $4) >>
|
||
|
;
|
||
|
FunctionBody
|
||
|
: CompoundCommand << ast.NewFunctionBody($0, ast.RedirectList{}) >> /* Apply rule 9 */
|
||
|
| CompoundCommand RedirectList << ast.NewFunctionBody($0, $1) >> /* Apply rule 9 */
|
||
|
;
|
||
|
FunctionName
|
||
|
: Word << ast.NewFunctionName($0) >> /* Apply rule 8 */
|
||
|
;
|
||
|
BraceGroup
|
||
|
: "{" CompoundList "}" << ast.NewBraceGroup($1) >>
|
||
|
;
|
||
|
DoGroup
|
||
|
: "do" CompoundList "done" << ast.NewDoGroup($1) >> /* Apply rule 6 */
|
||
|
;
|
||
|
SimpleCommand
|
||
|
: CmdPrefix CmdWord CmdSuffix << ast.NewSimpleCommand($0, nil, $1, $2) >>
|
||
|
| CmdPrefix CmdWord << ast.NewSimpleCommand($0, nil, $1, nil) >>
|
||
|
| CmdPrefix << ast.NewSimpleCommand($0, nil, nil, nil) >>
|
||
|
| CmdName CmdSuffix << ast.NewSimpleCommand(nil, $0, nil, $1) >>
|
||
|
| CmdName << ast.NewSimpleCommand(nil, $0, nil, nil) >>
|
||
|
;
|
||
|
CmdName
|
||
|
: Word << ast.NewCmdName($0) >> /* Apply rule 7a */
|
||
|
;
|
||
|
CmdWord
|
||
|
: Word << ast.NewCmdWord($0) >> /* Apply rule 7b */
|
||
|
;
|
||
|
CmdPrefix
|
||
|
: IoRedirect << ast.NewCmdPrefix(nil, $0, nil) >>
|
||
|
| CmdPrefix IoRedirect << ast.NewCmdPrefix(nil, $1, $0) >>
|
||
|
| AssignmentWord << ast.NewCmdPrefix($0, nil, nil) >>
|
||
|
| CmdPrefix AssignmentWord << ast.NewCmdPrefix($1, nil, $0) >>
|
||
|
;
|
||
|
CmdSuffix
|
||
|
: IoRedirect << ast.NewCmdSuffix(ast.Word(""), $0, nil) >>
|
||
|
| CmdSuffix IoRedirect << ast.NewCmdSuffix(ast.Word(""), $1, $0) >>
|
||
|
| Word << ast.NewCmdSuffix($0, nil, nil) >>
|
||
|
| CmdSuffix Word << ast.NewCmdSuffix($1, nil, $0) >>
|
||
|
;
|
||
|
RedirectList
|
||
|
: IoRedirect << ast.NewRedirectList($0) >>
|
||
|
| RedirectList IoRedirect << ast.AppendToRedirectList($0, $1) >>
|
||
|
;
|
||
|
IoRedirect
|
||
|
: IoFile << ast.NewIoRedirect($0, ast.IoNumber(0), nil) >>
|
||
|
| IoNumber IoFile << ast.NewIoRedirect($1, $0, nil) >>
|
||
|
| IoHere << ast.NewIoRedirect(nil, ast.IoNumber(0), $0) >>
|
||
|
| IoNumber IoHere << ast.NewIoRedirect(nil, $0, $1) >>
|
||
|
;
|
||
|
IoFile
|
||
|
: "<" Filename << ast.NewIoFile($1, ast.R_STDIN) >>
|
||
|
| "<&" Filename << ast.NewIoFile($1, ast.R_INFD) >>
|
||
|
| ">" Filename << ast.NewIoFile($1, ast.R_STDOUT) >>
|
||
|
| ">&" Filename << ast.NewIoFile($1, ast.R_OUTFD) >>
|
||
|
| ">>" Filename << ast.NewIoFile($1, ast.R_APPEND) >>
|
||
|
| "<>" Filename << ast.NewIoFile($1, ast.R_ORWFD) >>
|
||
|
| ">|" Filename << ast.NewIoFile($1, ast.R_OUTSP) >>
|
||
|
;
|
||
|
Filename
|
||
|
: Word << ast.NewFilename($0) >> /* Apply rule 2 */
|
||
|
;
|
||
|
IoHere
|
||
|
: "<<" HereEnd << ast.NewIoHere($1, false) >>
|
||
|
| "<<-" HereEnd << ast.NewIoHere($1, true) >>
|
||
|
;
|
||
|
HereEnd
|
||
|
: Word << ast.NewHereEnd($0) >> /* Apply rule 3 */
|
||
|
;
|
||
|
NewlineList
|
||
|
: "\n"
|
||
|
| NewlineList "\n"
|
||
|
;
|
||
|
Linebreak
|
||
|
: NewlineList
|
||
|
| nothing
|
||
|
;
|
||
|
SeparatorOp
|
||
|
: "&" << ast.S_AMP, nil >>
|
||
|
| ";" << ast.S_SEMICOLON, nil >>
|
||
|
;
|
||
|
Separator
|
||
|
: SeparatorOp Linebreak << ast.NewSeparator($0) >>
|
||
|
| NewlineList
|
||
|
;
|
||
|
SequentialSep
|
||
|
: ";" Linebreak
|
||
|
| NewlineList
|
||
|
;
|