Skip to content

Commit

Permalink
nixd/Syntax: binary op actions
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Sep 16, 2023
1 parent e782f19 commit cda6116
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 57 deletions.
17 changes: 17 additions & 0 deletions nixd/include/nixd/Syntax/BinaryOps.inc
Original file line number Diff line number Diff line change
@@ -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
21 changes: 17 additions & 4 deletions nixd/include/nixd/Syntax/Nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ struct If : Node {

struct ExprOp : Node {};

struct UnaryOp : ExprOp {};

struct BinaryOp : ExprOp {};

struct Apply : Node {};

struct Select : Node {};
Expand All @@ -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
95 changes: 42 additions & 53 deletions nixd/lib/Syntax/Parser/Parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -70,99 +70,88 @@ 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
;


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<OpEq>($1, $3, yylloc, *Data); }
| expr_op NEQ expr_op { $$ = mkBinOp<OpNEq>($1, $3, yylloc, *Data); }
| expr_op '<' expr_op { $$ = mkBinOp<OpLe>($1, $3, yylloc, *Data); }
| expr_op LEQ expr_op { $$ = mkBinOp<OpLe>($1, $3, yylloc, *Data); }
| expr_op '>' expr_op { $$ = mkBinOp<OpGe>($1, $3, yylloc, *Data); }
| expr_op GEQ expr_op { $$ = mkBinOp<OpGeq>($1, $3, yylloc, *Data); }
| expr_op AND expr_op { $$ = mkBinOp<OpAnd>($1, $3, yylloc, *Data); }
| expr_op OR expr_op { $$ = mkBinOp<OpOr>($1, $3, yylloc, *Data); }
| expr_op IMPL expr_op { $$ = mkBinOp<OpImpl>($1, $3, yylloc, *Data); }
| expr_op UPDATE expr_op { $$ = mkBinOp<OpUpdate>($1, $3, yylloc, *Data); }
| expr_op '+' expr_op { $$ = mkBinOp<OpAdd>($1, $3, yylloc, *Data); }
| expr_op '-' expr_op { $$ = mkBinOp<OpSub>($1, $3, yylloc, *Data); }
| expr_op '*' expr_op { $$ = mkBinOp<OpMul>($1, $3, yylloc, *Data); }
| expr_op '/' expr_op { $$ = mkBinOp<OpDiv>($1, $3, yylloc, *Data); }
| expr_op CONCAT expr_op { $$ = mkBinOp<OpConcatLists>($1, $3, yylloc, *Data); }
| expr_op '?' attrpath {

}
| expr_app
;

Expand Down
16 changes: 16 additions & 0 deletions nixd/lib/Syntax/Parser/Prologue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Lexer.tab.h"

#include "nixd/Syntax/Nodes.h"
#include "nixd/Syntax/Parser/Require.h"

YY_DECL;

Expand All @@ -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 <class T>
T *decorateNode(T *Node, YYLTYPE YL, nixd::syntax::ParseData &Data) {
Data.Nodes.record(Node);
Node->Range = mkRange(YL, Data);
return Node;
}

template <class T>
T *mkBinOp(nixd::syntax::Node *LHS, nixd::syntax::Node *RHS, YYLTYPE YL,
nixd::syntax::ParseData &Data) {
return decorateNode<T>(new T{.LHS = LHS, .RHS = RHS}, YL, Data);
}

using namespace nixd::syntax;

0 comments on commit cda6116

Please sign in to comment.