// ================================================================ // LEXER !whitespace : ' ' | '\t' | '\n' | '\r' ; !comment : '#' {.} '\n' ; _letter : 'a'-'z' | 'A'-'Z' ; _decdig : '0'-'9' ; _idchar : _letter | _decdig | '_' ; emitf : 'e' 'm' 'i' 't' 'f'; emit : 'e' 'm' 'i' 't' ; stdout : 's' 't' 'd' 'o' 'u' 't' ; stderr : 's' 't' 'd' 'e' 'r' 'r' ; // ================================================================ // IMPORT << import "two/src/dsl" >> // ================================================================ // PARSER // ---------------------------------------------------------------- Root : EmitFStatement << dsl.NewAST($0) >> | EmitStatement << dsl.NewAST($0) >> ; // ---------------------------------------------------------------- Redirector : ">" RedirectTarget << dsl.NewASTNodeUnary($0, $1, dsl.NodeTypeRedirectWrite) >> | ">>" RedirectTarget << dsl.NewASTNodeUnary($0, $1, dsl.NodeTypeRedirectAppend) >> | "|" RedirectTarget << dsl.NewASTNodeUnary($0, $1, dsl.NodeTypeRedirectPipe) >> ; RedirectTarget : stdout << dsl.NewASTNodeZary($0, dsl.NodeTypeRedirectTargetStdout) >> | stderr << dsl.NewASTNodeZary($0, dsl.NodeTypeRedirectTargetStderr) >> | Rvalue ; // ---------------------------------------------------------------- EmitStatement : emit Emittable << dsl.NewASTNodeTernary( $0, $1, dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), dsl.NodeTypeEmitStatement, ) >> | emit Redirector "," Emittable << dsl.NewASTNodeTernary( $0, $3, dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), $1, dsl.NodeTypeEmitStatement, ) >> | emit "(" EmittableList ")" << dsl.NewASTNodeTernary( $0, $2, dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), dsl.NodeTypeEmitStatement, ) >> | emit Redirector "," "(" EmittableList ")" << dsl.NewASTNodeTernary( $0, $4, dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), $1, dsl.NodeTypeEmitStatement, ) >> | emit Emittable "," EmitKeys << dsl.NewASTNodeTernary( $0, $1, $3, dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), dsl.NodeTypeEmitStatement, ) >> | emit Redirector "," Emittable "," EmitKeys << dsl.NewASTNodeTernary( $0, $3, $5, $1, dsl.NodeTypeEmitStatement, ) >> | emit "(" EmittableList ")" "," EmitKeys << dsl.NewASTNodeTernary( $0, $2, $5, dsl.NewASTNodeNestable(nil, dsl.NodeTypeNoOp), dsl.NodeTypeEmitStatement, ) >> | emit Redirector "," "(" EmittableList ")" "," EmitKeys << dsl.NewASTNodeTernary( $0, $4, $7, $1, dsl.NodeTypeEmitStatement, ) >> ; // ---------------------------------------------------------------- // Examples: // emitf @a // emitf @a, b, $c // Each argument must be a non-indexed oosvar/localvar/fieldname, so we can use // their names as keys in the emitted record. EmitFStatement : emitf EmittableList << dsl.AdoptChildren( dsl.NewASTNodeNestable( $0, dsl.NodeTypeEmitFStatement, ), $1, ) >> | emitf Redirector "," EmittableList // TODO ; // ---------------------------------------------------------------- EmittableList : Emittable << dsl.NewASTNodeUnary( nil, $0, dsl.NodeTypeEmittableList, ) >> // Allow trailing final comma, especially for multiline statements | Emittable "," EmittableList << dsl.PrependChild( $2, $0, ) >> ; Emittable : Literal ; // ---------------------------------------------------------------- EmitKeys : Rvalue << dsl.NewASTNodeUnary( nil, $0, dsl.NodeTypeEmitKeys, ) >> | Rvalue "," EmitKeys << dsl.PrependChild( $2, $0, ) >> ; // ---------------------------------------------------------------- Rvalue : Literal << dsl.NewASTNodeUnary(nil, $0, dsl.NodeTypeStringLiteral) >> | "(" Literal ")" << dsl.NewASTNodeUnary(nil, $1, dsl.NodeTypeStringLiteral) >> | "[" Literal "]" << dsl.NewASTNodeUnary(nil, $1, dsl.NodeTypeStringLiteral) >> | "[" Literal "," Literal "]" << dsl.NewASTNodeBinary(nil, $1, $2, dsl.NodeTypeStringLiteral) >> ; Literal : "x" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >> | "y" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >> | "z" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >> ;