From cda61161f7addeef5a80809176afe8f3d4cd6390 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Sat, 16 Sep 2023 22:33:18 +0800 Subject: [PATCH] nixd/Syntax: binary op actions --- nixd/include/nixd/Syntax/BinaryOps.inc | 17 +++++ nixd/include/nixd/Syntax/Nodes.h | 21 ++++-- nixd/lib/Syntax/Parser/Parser.y | 95 ++++++++++++-------------- nixd/lib/Syntax/Parser/Prologue.cpp | 16 +++++ 4 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 nixd/include/nixd/Syntax/BinaryOps.inc diff --git a/nixd/include/nixd/Syntax/BinaryOps.inc b/nixd/include/nixd/Syntax/BinaryOps.inc new file mode 100644 index 000000000..4daa3f387 --- /dev/null +++ b/nixd/include/nixd/Syntax/BinaryOps.inc @@ -0,0 +1,17 @@ +#ifdef BIN_OP +BIN_OP(OpEq, "==") +BIN_OP(OpNEq, "!=") +BIN_OP(OpAnd, "&&") +BIN_OP(OpOr, "||") +BIN_OP(OpImpl, "->") +BIN_OP(OpUpdate, "//") +BIN_OP(OpConcatLists, "++") +BIN_OP(OpLe, "<") +BIN_OP(OpLeq, "<=") +BIN_OP(OpGe, ">") +BIN_OP(OpGeq, ">=") +BIN_OP(OpAdd, "+") +BIN_OP(OpSub, "-") +BIN_OP(OpMul, "*") +BIN_OP(OpDiv, "/") +#endif diff --git a/nixd/include/nixd/Syntax/Nodes.h b/nixd/include/nixd/Syntax/Nodes.h index cf2bb832d..4b5935f36 100644 --- a/nixd/include/nixd/Syntax/Nodes.h +++ b/nixd/include/nixd/Syntax/Nodes.h @@ -57,10 +57,6 @@ struct If : Node { struct ExprOp : Node {}; -struct UnaryOp : ExprOp {}; - -struct BinaryOp : ExprOp {}; - struct Apply : Node {}; struct Select : Node {}; @@ -87,4 +83,21 @@ struct StringAttr : Node {}; struct AttrPath : Node {}; +struct OpNot : Node { + Node *Body; +}; + +struct OpNegate : Node { + Node *Body; +}; + +// Binary operators +#define BIN_OP(NAME, OP) \ + struct NAME : Node { \ + Node *LHS; \ + Node *RHS; \ + }; +#include "BinaryOps.inc" +#undef BIN_OP + } // namespace nixd::syntax diff --git a/nixd/lib/Syntax/Parser/Parser.y b/nixd/lib/Syntax/Parser/Parser.y index 8ed4d90bc..f0db11bd7 100644 --- a/nixd/lib/Syntax/Parser/Parser.y +++ b/nixd/lib/Syntax/Parser/Parser.y @@ -70,61 +70,43 @@ expr: expr_function; expr_function : identifier ':' expr_function { - auto Func = new nixd::syntax::Function { + $$ = decorateNode(new Function { .Arg = $1, .Formals = nullptr, .Body = $3 - }; - Data->Nodes.record(Func); - Func->Range = mkRange(yylloc, *Data); - $$ = Func; + }, yylloc, *Data); } | '{' formals '}' ':' expr_function { - auto Func = new nixd::syntax::Function { + $$ = decorateNode(new Function { .Arg = nullptr, .Formals = $2, .Body = $5 - }; - Data->Nodes.record(Func); - Func->Range = mkRange(yylloc, *Data); - $$ = Func; + }, yylloc, *Data); } | '{' formals '}' '@' identifier ':' expr_function { - auto Func = new nixd::syntax::Function { + $$ = decorateNode(new Function { .Arg = $5, .Formals = $2, .Body = $7 - }; - Data->Nodes.record(Func); - Func->Range = mkRange(yylloc, *Data); - $$ = Func; + }, yylloc, *Data); } | ASSERT expr ';' expr_function { - auto Assert = new nixd::syntax::Assert { + $$ = decorateNode(new Assert { .Cond = $2, .Body = $4 - }; - Data->Nodes.record(Assert); - Assert->Range = mkRange(yylloc, *Data); - $$ = Assert; + }, yylloc, *Data); } | WITH expr ';' expr_function { - auto With = new nixd::syntax::With { + $$ = decorateNode(new With { .Attrs = $2, .Body = $4 - }; - Data->Nodes.record(With); - With->Range = mkRange(yylloc, *Data); - $$ = With; + }, yylloc, *Data); } | LET binds IN expr_function { - auto Let = new nixd::syntax::Let { + $$ = decorateNode(new Let { .Binds = $2, .Body = $4 - }; - Data->Nodes.record(Let); - Let->Range = mkRange(yylloc, *Data); - $$ = Let; + }, yylloc, *Data); } | expr_if ; @@ -132,37 +114,44 @@ expr_function expr_if : IF expr THEN expr ELSE expr { - auto If = new nixd::syntax::If { + $$ = decorateNode(new If { .Cond = $2, .Then = $4, .Else = $6 - }; - Data->Nodes.record(If); - If->Range = mkRange(yylloc, *Data); - $$ = If; + }, yylloc, *Data); } | expr_op ; expr_op - : '!' expr_op %prec NOT - | '-' expr_op %prec NEGATE - | expr_op EQ expr_op - | expr_op NEQ expr_op - | expr_op '<' expr_op - | expr_op LEQ expr_op - | expr_op '>' expr_op - | expr_op GEQ expr_op - | expr_op AND expr_op - | expr_op OR expr_op - | expr_op IMPL expr_op - | expr_op UPDATE expr_op - | expr_op '?' attrpath - | expr_op '+' expr_op - | expr_op '-' expr_op - | expr_op '*' expr_op - | expr_op '/' expr_op - | expr_op CONCAT expr_op + : '!' expr_op %prec NOT { + $$ = decorateNode(new OpNot { + .Body = $2 + }, yylloc, *Data); + } + | '-' expr_op %prec NEGATE { + $$ = decorateNode(new OpNot { + .Body = $2 + }, yylloc, *Data); + } + | expr_op EQ expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op NEQ expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op '<' expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op LEQ expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op '>' expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op GEQ expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op AND expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op OR expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op IMPL expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op UPDATE expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op '+' expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op '-' expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op '*' expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op '/' expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op CONCAT expr_op { $$ = mkBinOp($1, $3, yylloc, *Data); } + | expr_op '?' attrpath { + + } | expr_app ; diff --git a/nixd/lib/Syntax/Parser/Prologue.cpp b/nixd/lib/Syntax/Parser/Prologue.cpp index f66f93c23..4a6d426b8 100644 --- a/nixd/lib/Syntax/Parser/Prologue.cpp +++ b/nixd/lib/Syntax/Parser/Prologue.cpp @@ -3,6 +3,7 @@ #include "Lexer.tab.h" #include "nixd/Syntax/Nodes.h" +#include "nixd/Syntax/Parser/Require.h" YY_DECL; @@ -21,3 +22,18 @@ static nixd::RangeIdx mkRange(YYLTYPE YL, nix::PosTable &T, static nixd::RangeIdx mkRange(YYLTYPE YL, nixd::syntax::ParseData &Data) { return mkRange(YL, Data.State.Positions, Data.Origin); } + +template +T *decorateNode(T *Node, YYLTYPE YL, nixd::syntax::ParseData &Data) { + Data.Nodes.record(Node); + Node->Range = mkRange(YL, Data); + return Node; +} + +template +T *mkBinOp(nixd::syntax::Node *LHS, nixd::syntax::Node *RHS, YYLTYPE YL, + nixd::syntax::ParseData &Data) { + return decorateNode(new T{.LHS = LHS, .RHS = RHS}, YL, Data); +} + +using namespace nixd::syntax;