484 lines
8.6 KiB
Plaintext
484 lines
8.6 KiB
Plaintext
{
|
|
package parser
|
|
|
|
// DO NOT EDIT: This file is auto generated by the pigeon PEG parser generator.
|
|
|
|
}
|
|
|
|
Start
|
|
= __ program:Program __ EOF {
|
|
return program, nil
|
|
}
|
|
|
|
Program
|
|
= body:SourceElements {
|
|
return program(body, c.text, c.pos)
|
|
}
|
|
|
|
SourceElements
|
|
= head:SourceElement tail:(__ SourceElement __)* {
|
|
return srcElems(head, tail)
|
|
}
|
|
|
|
SourceElement
|
|
= Statement
|
|
|
|
Statement
|
|
= VariableStatement
|
|
/ ReturnStatement
|
|
/ ExpressionStatement
|
|
/ BlockStatement
|
|
|
|
|
|
VariableStatement
|
|
= declaration:VariableDeclaration {
|
|
return varstmt(declaration, c.text, c.pos)
|
|
}
|
|
|
|
ReturnStatement
|
|
= "return" __ argument:Expr {
|
|
return returnstmt(argument, c.text, c.pos)
|
|
}
|
|
|
|
ExpressionStatement
|
|
= expr:Expr {
|
|
return exprstmt(expr, c.text, c.pos)
|
|
}
|
|
|
|
BlockStatement
|
|
= "{" __ body:( __ Statement __ )* __ "}" {
|
|
return blockstmt(body, c.text, c.pos)
|
|
}
|
|
|
|
VariableDeclaration
|
|
= id:Identifier __ "=" __ init:Expr {
|
|
return vardecl(id, init, c.text, c.pos)
|
|
}
|
|
|
|
|
|
MemberExpressions
|
|
= head:Identifier // TODO: should be primary
|
|
tail:(
|
|
__ property:MemberExpressionProperty {
|
|
return property, nil
|
|
}
|
|
)*
|
|
{
|
|
return memberexprs(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
MemberExpressionProperty
|
|
= "." __ property:Identifier {
|
|
return property, nil
|
|
}
|
|
/ "[" __ property:Primary __ "]" __ {
|
|
return property, nil
|
|
}
|
|
|
|
CallExpression
|
|
= head:(
|
|
callee:MemberExpressions __ args:Arguments {
|
|
return callexpr(callee, args, c.text, c.pos)
|
|
}
|
|
)
|
|
tail:(
|
|
__ args:Arguments {
|
|
return callexpr(nil, args, c.text, c.pos)
|
|
}
|
|
/ __ property:MemberExpressionProperty {
|
|
return memberexpr(nil, property, c.text, c.pos)
|
|
}
|
|
)*
|
|
{
|
|
return callexprs(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
PipeExpression
|
|
= head:PipeExpressionHead __ tail:(__ PipeExpressionPipe __)+ {
|
|
return pipeExprs(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
PipeExpressionHead
|
|
= CallExpression // TODO(nathanielc): Allow for more expressions as pipe heads. Cannot use Expr because it causes infinite left recursion.
|
|
/ Literal
|
|
/ Array
|
|
/ MemberExpressions
|
|
/ Identifier
|
|
/ ObjectExpression
|
|
/ ArrowFunctionExpression
|
|
/ Parens
|
|
|
|
PipeExpressionPipe
|
|
= "|>" __ call:CallExpression {
|
|
return incompletePipeExpr(call, c.text, c.pos)
|
|
}
|
|
|
|
Arguments
|
|
= "(" __ args:(ObjectProperties)? __ ")" {
|
|
return args, nil
|
|
}
|
|
|
|
ArrowFunctionExpression
|
|
= "(" __ params:ArrowFunctionParams? __ ")" __ "=>" __ body:ArrowFunctionBody __ {
|
|
return arrowfunc(params, body, c.text, c.pos), nil
|
|
}
|
|
|
|
ArrowFunctionParams
|
|
= first:ArrowFunctionParam __ rest:ArrowFunctionParamsRest* ","? {
|
|
return append([]interface{}{first}, toIfaceSlice(rest)...), nil
|
|
}
|
|
|
|
ArrowFunctionParamsRest
|
|
= "," __ arg:ArrowFunctionParam __ {
|
|
return arg, nil
|
|
}
|
|
|
|
ArrowFunctionParam
|
|
= key:Identifier __ "=" __ value:Primary __ {
|
|
return property(key, value, c.text, c.pos)
|
|
}
|
|
/ key:Identifier __ {
|
|
return property(key, nil, c.text, c.pos)
|
|
}
|
|
|
|
|
|
ArrowFunctionBody
|
|
= body:Expr {
|
|
return body, nil
|
|
}
|
|
/ body:BlockStatement {
|
|
return body, nil
|
|
}
|
|
|
|
ObjectExpression
|
|
= "{" __ object:(ObjectProperties)? __ "}" {
|
|
return object, nil
|
|
}
|
|
|
|
ObjectProperties
|
|
= first:Property __ rest:PropertiesRest* __ ","? {
|
|
return objectexpr(first, rest, c.text, c.pos)
|
|
}
|
|
|
|
PropertiesRest
|
|
= "," __ arg:Property {
|
|
return arg, nil
|
|
}
|
|
|
|
Property
|
|
= key:Identifier __ ":" __ value:Expr {
|
|
return property(key, value, c.text, c.pos)
|
|
}
|
|
|
|
// + -
|
|
// <= < >= > startsWith IN NOT EMPTY EMPTY
|
|
// == !=
|
|
// and or
|
|
// Lowest to Highest Priority.
|
|
// Highest Priority includes the valid primary
|
|
// primary contains the Lowest Priority
|
|
Expr
|
|
= LogicalExpression
|
|
|
|
LogicalOperators
|
|
= ("or"i / "and"i) {
|
|
return logicalOp(c.text)
|
|
}
|
|
|
|
LogicalExpression
|
|
= head:Equality tail:( __ LogicalOperators __ Equality )* {
|
|
return logicalExpression(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
EqualityOperators
|
|
= ("==" / "!=" / "=~" / "!~") {
|
|
return operator(c.text)
|
|
}
|
|
|
|
Equality
|
|
= head:Relational tail:( __ EqualityOperators __ Relational )* {
|
|
return binaryExpression(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
RelationalOperators
|
|
= ( "<="
|
|
/ "<"
|
|
/ ">="
|
|
/ ">"
|
|
/ "startswith"i
|
|
/ "in"i
|
|
/ "not empty"i
|
|
/ "empty"i
|
|
) {
|
|
return operator(c.text)
|
|
}
|
|
|
|
Relational
|
|
= head:Additive tail:( __ RelationalOperators __ Additive )* {
|
|
return binaryExpression(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
AdditiveOperator
|
|
= ("+" / "-") {
|
|
return operator(c.text)
|
|
}
|
|
|
|
Additive
|
|
= head:Multiplicative tail:( __ AdditiveOperator __ Multiplicative )* {
|
|
return binaryExpression(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
MultiplicativeOperator
|
|
= ("*" / "/") {
|
|
return operator(c.text)
|
|
}
|
|
|
|
Multiplicative
|
|
= head:UnaryExpression tail:( __ MultiplicativeOperator __ UnaryExpression )* {
|
|
return binaryExpression(head, tail, c.text, c.pos)
|
|
}
|
|
|
|
UnaryOperator
|
|
= ("-" / "not") {
|
|
return operator(c.text)
|
|
}
|
|
|
|
UnaryExpression
|
|
= __ op:UnaryOperator __ argument:Primary __ {
|
|
return unaryExpression(op, argument, c.text, c.pos)
|
|
}
|
|
/ Primary
|
|
|
|
Primary
|
|
= PipeExpression
|
|
/ Array
|
|
/ Literal
|
|
/ CallExpression
|
|
/ MemberExpressions
|
|
/ Identifier
|
|
/ ObjectExpression
|
|
/ ArrowFunctionExpression
|
|
/ Parens
|
|
|
|
Literal
|
|
= StringLiteral
|
|
/ BooleanLiteral
|
|
/ RegexpLiteral
|
|
/ PipeLiteral
|
|
/ DurationLiteral
|
|
/ DateTimeLiteral
|
|
/ NumberLiteral
|
|
/ IntegerLiteral
|
|
|
|
Parens
|
|
= "(" __ expr:Expr __ ")" {
|
|
return expr, nil
|
|
}
|
|
|
|
Array
|
|
= "[" __ elements:ArrayElements? __ "]" {
|
|
return elements, nil
|
|
}
|
|
|
|
ArrayElements
|
|
= first:Primary __ rest:ArrayRest* {
|
|
return array(first, rest, c.text, c.pos), nil
|
|
}
|
|
|
|
ArrayRest
|
|
= "," __ element:Primary {
|
|
return element, nil
|
|
}
|
|
|
|
DateFullYear
|
|
= Digit Digit Digit Digit
|
|
|
|
DateMonth
|
|
// 01-12
|
|
= Digit Digit
|
|
|
|
DateMDay
|
|
// 01-28, 01-29, 01-30, 01-31 based on
|
|
// month/year
|
|
= Digit Digit
|
|
|
|
TimeHour
|
|
// 00-23
|
|
= Digit Digit
|
|
|
|
TimeMinute
|
|
// 00-59
|
|
= Digit Digit
|
|
|
|
TimeSecond
|
|
// 00-58, 00-59, 00-60 based on leap second
|
|
// rules
|
|
= Digit Digit
|
|
|
|
TimeSecFrac
|
|
= "." Digit+
|
|
|
|
TimeNumOffset
|
|
= ("+" / "-") TimeHour ":" TimeMinute
|
|
|
|
TimeOffset
|
|
= ("Z" / TimeNumOffset)
|
|
|
|
PartialTime
|
|
= TimeHour ":" TimeMinute ":" TimeSecond TimeSecFrac?
|
|
|
|
FullDate
|
|
= DateFullYear "-" DateMonth "-" DateMDay
|
|
|
|
FullTime
|
|
= PartialTime TimeOffset
|
|
|
|
DateTimeLiteral
|
|
= FullDate "T" FullTime {
|
|
return datetime(c.text, c.pos)
|
|
}
|
|
|
|
NanoSecondUnits
|
|
= "ns"
|
|
|
|
MicroSecondUnits
|
|
= ("us" / "µs" / "μs")
|
|
|
|
MilliSecondUnits
|
|
= "ms"
|
|
|
|
SecondUnits
|
|
= "s"
|
|
|
|
MinuteUnits
|
|
= "m"
|
|
|
|
HourUnits
|
|
= "h"
|
|
|
|
DurationUnits
|
|
= (
|
|
NanoSecondUnits
|
|
/ MicroSecondUnits
|
|
/ MilliSecondUnits
|
|
/ SecondUnits
|
|
/ MinuteUnits
|
|
/ HourUnits
|
|
)
|
|
|
|
SingleDuration
|
|
= Integer DurationUnits
|
|
|
|
DurationLiteral
|
|
= SingleDuration+ {
|
|
return durationLiteral(c.text, c.pos)
|
|
}
|
|
|
|
StringLiteral
|
|
= ( '"' DoubleStringChar* '"' ) {
|
|
return stringLiteral(c.text, c.pos)
|
|
}
|
|
/ ( '"' DoubleStringChar* ( EOL / EOF ) ) {
|
|
return "", errors.New("string literal not terminated")
|
|
}
|
|
|
|
DoubleStringChar
|
|
= !( '"' / "\\" / EOL ) SourceChar
|
|
/ "\\" DoubleStringEscape
|
|
|
|
DoubleStringEscape
|
|
= '"'
|
|
/ ( SourceChar / EOL / EOF ) {
|
|
return nil, errors.New("invalid escape character")
|
|
}
|
|
|
|
|
|
RegexpLiteral
|
|
= "/" pattern:RegexpBody "/" {
|
|
return pattern, nil
|
|
}
|
|
|
|
RegexpBody
|
|
= chars:RegexpChar+ {
|
|
return regexLiteral(chars, c.text, c.pos)
|
|
}
|
|
|
|
RegexpChar
|
|
= ![\\/] re:RegexpNonTerminator {
|
|
return re, nil
|
|
}
|
|
/ RegexpBackslashSequence
|
|
|
|
RegexpBackslashSequence
|
|
= "\\/" {
|
|
return []byte{'/'}, nil
|
|
}
|
|
/ "\\" RegexpNonTerminator {
|
|
return c.text, nil
|
|
}
|
|
|
|
RegexpNonTerminator
|
|
= !LineTerminator SourceChar {
|
|
return c.text, nil
|
|
}
|
|
|
|
BooleanLiteral
|
|
= __ "true" __ {
|
|
return booleanLiteral(true, c.text, c.pos)
|
|
}
|
|
/ __ "false" __ {
|
|
return booleanLiteral(false, c.text, c.pos)
|
|
}
|
|
|
|
NumberLiteral
|
|
= Integer "." Digit+ {
|
|
return numberLiteral(c.text, c.pos)
|
|
}
|
|
|
|
Integer
|
|
= ("0" / NonZeroDigit Digit*)
|
|
|
|
IntegerLiteral
|
|
= Integer {
|
|
return integerLiteral(c.text, c.pos)
|
|
}
|
|
|
|
NonZeroDigit
|
|
= [1-9]
|
|
|
|
Digit
|
|
= [0-9]
|
|
|
|
PipeLiteral
|
|
= "<-" {
|
|
return pipeLiteral(c.text, c.pos), nil
|
|
}
|
|
|
|
|
|
Identifier
|
|
// Allow any unicode letter possibly followed by any number of unicode letters, underscores and numbers.
|
|
= [_\pL][_0-9\pL]* {
|
|
return identifier(c.text, c.pos)
|
|
}
|
|
|
|
|
|
SourceChar
|
|
= .
|
|
__
|
|
= ( ws / EOL / Comment )*
|
|
|
|
Comment
|
|
= "//" [^\r\n]* EOL
|
|
|
|
ws
|
|
= [ \t\r\n]
|
|
|
|
LineTerminator
|
|
= [\n\r]
|
|
|
|
EOL
|
|
= "\n"
|
|
|
|
EOF
|
|
= !.
|