mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
93 lines
2.8 KiB
BNF
93 lines
2.8 KiB
BNF
// ================================================================
|
|
// LEXER
|
|
|
|
!whitespace : ' ' | '\t' | '\n' | '\r' ;
|
|
|
|
// ================================================================
|
|
// IMPORT
|
|
|
|
<< import "two/src/dsl" >>
|
|
|
|
// ================================================================
|
|
// PARSER
|
|
|
|
// ----------------------------------------------------------------
|
|
Root
|
|
: StatementBlock
|
|
<< dsl.NewAST($0) >>
|
|
;
|
|
|
|
// ================================================================
|
|
StatementBlock
|
|
|
|
// Empty statement. This allows for 'mlr put ""', as well as repeated semicolons.
|
|
: empty
|
|
<< dsl.NewASTNodeZary(nil, dsl.NodeTypeStatementBlock) >>
|
|
|
|
| NonEmptyStatementBlock
|
|
<< dsl.Wrap($0) >>
|
|
;
|
|
|
|
// ----------------------------------------------------------------
|
|
NonEmptyStatementBlock
|
|
// ---------------------- Terminal rules
|
|
|
|
// Things not ending in a curly brace, like assignments -- and also do-while.
|
|
: BracelessStatement
|
|
<< dsl.NewASTNodeUnary(nil, $0, dsl.NodeTypeStatementBlock) >>
|
|
|
|
// Things ending in a curly brace, like for/do/while, begin/end, and pattern-action blocks
|
|
| BracefulStatement
|
|
<< dsl.NewASTNodeUnary(nil, $0, dsl.NodeTypeStatementBlock) >>
|
|
|
|
// ---------------------- Recursive rules
|
|
|
|
// So statements can start with a semicolon
|
|
| ";" StatementBlock
|
|
<< dsl.Wrap($1) >>
|
|
|
|
// Normal case for sequential statements like '$x=1; $y=2'
|
|
| BracelessStatement ";" StatementBlock
|
|
<<dsl.PrependChild($2, $0) >>
|
|
|
|
// For 'begin {...} ; $x=1'
|
|
| BracefulStatement ";" StatementBlock
|
|
<<dsl.PrependChild($2, $0) >>
|
|
|
|
// These are for things like 'begin {...} begin {...} ...' -- where people
|
|
// shouldn't have to put semicolons after the closing curly braces.
|
|
//
|
|
// We get LR-1 conflicts with the following, so we need a pair of more
|
|
// explicit lookahead-by-more production rules instead. (By using ternaries
|
|
// we are effectively getting lookahead-by-two.)
|
|
//
|
|
// | BracefulStatement StatementBlock
|
|
// <<dsl.PrependChild($1, $0) >>
|
|
|
|
// E.g. 'begin {...} begin {...} $x=1'
|
|
| BracefulStatement BracefulStatement StatementBlock
|
|
<<dsl.PrependTwoChildren($2, $0, $1) >>
|
|
|
|
// E.g. 'begin {...} $x=1'
|
|
| BracefulStatement BracelessStatement
|
|
<< dsl.NewASTNodeBinary(nil, $0, $1, dsl.NodeTypeStatementBlock) >>
|
|
|
|
// E.g. 'begin {...} $x=1 ;'
|
|
| BracefulStatement BracelessStatement ";"
|
|
<< dsl.NewASTNodeBinary(nil, $0, $1, dsl.NodeTypeStatementBlock) >>
|
|
|
|
| BracefulStatement BracelessStatement ";" NonEmptyStatementBlock
|
|
<<dsl.PrependTwoChildren($3, $0, $1) >>
|
|
;
|
|
|
|
// ----------------------------------------------------------------
|
|
BracelessStatement
|
|
: "x"
|
|
<< dsl.NewASTNodeZary($0, dsl.NodeTypeBareBoolean) >>
|
|
;
|
|
|
|
// ----------------------------------------------------------------
|
|
BracefulStatement
|
|
: "{" StatementBlock "}"
|
|
<< dsl.Wrap($1) >>
|
|
;
|