Sven Slootweg 1 year ago
parent
commit
344a75b7a1
  1. 84
      src/expression.pegjs
  2. 1
      test/fail-list-if.nix
  3. 1
      test/fail-plus-if.nix
  4. 1
      test/let-inherit.nix
  5. 1
      test/with-if.nix

84
src/expression.pegjs

@ -1,4 +1,6 @@
{
/* FIXME: `or` operator */
let operators = [{
associativity: "left",
operators: ["call"]
@ -101,7 +103,7 @@ escapableCharacter
/ "t"
/ "r"
commentCharacter
inlineCommentCharacter
= [^\n\r]
// Literals
@ -129,14 +131,20 @@ homePath
storePath
= "<" path:([a-zA-Z0-9\.\_\-\+]+ ("/" [a-zA-Z0-9\.\_\-\+]+)*) ">" { return {type: "path", pathType: "store", storePath: path}; }
uri
= [a-zA-Z][a-zA-Z0-9+\-.]* ":" [a-zA-Z0-9%/?:@&=+$,\-_.!~*']+
// Utilities
_
= (whitespace / comment)* {}
= (whitespace / inlineComment)* {}
__
= whitespace+ {}
reservedWord // FIXME: Missing reserved words?
reservedWord
= name:reservedWordName (& [^a-zA-Z0-9._-]) { return name; } // FIXME: Unify identifier character set definition
reservedWordName // FIXME: Missing reserved words?
= "if"
/ "then"
/ "else"
@ -171,11 +179,13 @@ nonOperatorExpression
/ withStatement
/ conditional
/ path
/ identifier
/ uri
/ attributePathAlternate
comment
= "#" chars:commentCharacter* _ { return {type: "comment", text: chars.join("")} }
inlineComment
= "#" chars:inlineCommentCharacter* _ { return {type: "inlineComment", text: chars.join("")} }
/* FIXME: Where else to allow blockComments? Needs to be allowed everywhere, not just in expressions. */
blockComment
= "/*" segments:(! "*/" . [^*]*)* "*/" { return {type: "blockComment", text: joinBlockText(segments)} }
@ -187,7 +197,7 @@ functionCallOperatorExpression
hasAttributeOperatorExpression
= left:nonOperatorExpression
_ "?"
_ right:identifier { return {type: "operatorExpression", operator: "?", left: left, right: right} } // FIXME: attribute path
_ right:identifier { return {type: "operatorExpression", operator: "?", left: left, right: right} } /* FIXME: Is an attribute path allowed here? */
binaryOperatorExpression
= left:nonOperatorExpression
@ -197,22 +207,49 @@ binaryOperatorExpression
divisionOperatorExpression
= left:nonOperatorExpression
_ "/"
_ right:expression { return {type: "operatorExpression", operator: "/", left: left, right: right} }
_ right:expression {
return {type: "operatorExpression", operator: "/", left: left, right: right};
}
numericallyNegatedOperatorExpression
= "-"
_ right:expression { return {type: "operatorExpression", operator: "numericalNegate", right: right} }
_ right:expression {
return {type: "operatorExpression", operator: "numericalNegate", right: right};
}
booleanNegatedOperatorExpression
= "!"
_ right:expression { return {type: "operatorExpression", operator: "booleanNegate", right: right} }
_ right:expression {
return {type: "operatorExpression", operator: "booleanNegate", right: right};
}
attributePathAlternate
= attributePath:attributePath alternate:(_ "or" _ attributePathAlternate)? {
if (alternate != null) {
return {type: "attributePathAlternate", path: attributePath, alternate: alternate};
} else {
return attributePath;
}
}
attributePath
= firstIdentifier:attributeItem nextIdentifiers:("." attributeItem)* {
return {type: "attributePath", items: [firstIdentifier].concat(nextIdentifiers.map(item => item[1]))};
}
attributeItem
= "\"" identifier:identifier "\"" { return identifier; } /* FIXME: What characters should be allowed here? */
/ identifier:identifier { return identifier; }
identifier
= identifier:(! (reservedWord [^a-z0-9._-]) identifierValue) { return {type: "identifier", identifier: identifier[1]} }
= identifier:(! reservedWord identifierValue) {
return {type: "identifier", identifier: identifier[1]};
}
/* FIXME: Quoted attributes? */
identifierValue
= literal:stringLiteral { return literal.value; }
/ chars:[a-z_]i [a-z0-9._-]i+ { return text(); }
/ chars:[a-z_]i [a-z0-9_-]i+ { return text(); }
group
= "("
@ -233,17 +270,18 @@ functionDefinitionArgument
= identifier
/ setPattern
/* FIXME: Is `"foo" = "bar"` valid in an assignment list? */
assignment
= identifier:identifier
= attributePath:attributePath
_ "="
_ expression:reorderedExpression
_ ";" { return {type: "assignment", identifier: identifier, expression: expression} }
_ ";" { return {type: "assignment", attributePath: attributePath, expression: expression} }
assignmentList
= _ items:((assignment / inheritStatement) _)* { return items.map(item => item[0]); }
= _ items:((assignment / inheritStatement / blockComment) _)* { return items.map(item => item[0]); }
bindingList
= items:(assignment _)* { return {type: "bindings", assignments: items.map(item => item[0])} }
bindingList // FIXME: Allow inherit - point at assignmentList instead?
= items:((assignment / blockComment) _)* { return {type: "bindings", assignments: items.map(item => item[0])} }
set
= "{"
@ -279,18 +317,20 @@ elseClause
= "else"
_ alternative:expression { return alternative; }
/* FIXME: What to return here? */
withStatement
= "with"
_ identifier:identifier
_ withExpression:expression
_ ";"
_ expression
inheritStatement // FIXME: Distinguish between identifiers and attribute paths?
inheritStatement /* FIXME: Distinguish between identifiers and attribute paths? */
= "inherit"
_ namespace:("(" identifier ")")?
_ identifiers:(identifier _)+
_ ";" { return {type: "inheritStatement", identifiers: identifiers.map(item => item[0]), namespace: maybe(namespace, 1)} }
_ namespace:("(" reorderedExpression ")")?
_ attributePaths:(attributePathAlternate _)+ /* FIXME: Is attributePathAlternate allowed here, or just attributePath? */
_ ";" { return {type: "inheritStatement", attributePaths: attributePaths.map(item => item[0]), namespace: maybe(namespace, 1)} }
/* FIXME: Are attribute paths allowed in set patterns? */
setPattern
= "{"
_ args:setPatternVariableList

1
test/fail-list-if.nix

@ -0,0 +1 @@
[if a then b else c]

1
test/fail-plus-if.nix

@ -0,0 +1 @@
1 + if true then 1 else 2

1
test/let-inherit.nix

@ -0,0 +1 @@
let inherit bar; in {}

1
test/with-if.nix

@ -0,0 +1 @@
with if false then {} else {x = 2;}; x
Loading…
Cancel
Save