Skip to content

Commit

Permalink
nixd/Syntax: add basic actions for expr_function
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Sep 16, 2023
1 parent 3f25548 commit 9abaf00
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 80 deletions.
33 changes: 1 addition & 32 deletions nixd/include/nixd/Support/Position.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include "nixd/Nix/PosAdapter.h"
#include "nixd/Parser/Parser.h"
#include "nixd/Syntax/Range.h"

#include "lspserver/Protocol.h"

Expand All @@ -13,37 +13,6 @@ struct Range;

inline lspserver::Range toLSPRange(const Range &R);

struct RangeIdx {
nix::PosIdx Begin;
nix::PosIdx End;

RangeIdx(nix::PosIdx Begin, nix::PosIdx End) : Begin(Begin), End(End) {}
RangeIdx(nix::PosIdx Begin, const decltype(ParseData::end) &End)
: RangeIdx(Begin, End.at(Begin)) {}
RangeIdx(const void *Ptr, const decltype(ParseData::locations) &Loc,
const decltype(ParseData::end) &End)
: RangeIdx(Loc.at(Ptr), End) {}
};

struct Range {
nix::Pos Begin;
nix::Pos End;
Range(nix::Pos Begin, nix::Pos End)
: Begin(std::move(Begin)), End(std::move(End)) {}
Range(RangeIdx Idx, const nix::PosTable &Table) {
Begin = Table[Idx.Begin];
End = Table[Idx.End];
}
Range(nix::PosIdx Begin, const decltype(ParseData::end) &End,
const nix::PosTable &Table)
: Range(RangeIdx(Begin, End), Table) {}
Range(const void *Ptr, const decltype(ParseData::locations) &Loc,
const decltype(ParseData::end) &End, const nix::PosTable &Table)
: Range(RangeIdx(Ptr, Loc, End), Table) {}

operator lspserver::Range() const { return toLSPRange(*this); }
};

inline lspserver::Position toLSPPos(const nix::AbstractPos &P) {
return {static_cast<int>(std::max(1U, P.line) - 1),
static_cast<int>(std::max(1U, P.column) - 1)};
Expand Down
52 changes: 37 additions & 15 deletions nixd/include/nixd/Syntax/Nodes.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,54 @@
/// FIXME: comment for this file.
#pragma once

#include "Range.h"

#include <nix/nixexpr.hh>

namespace nixd::syntax {

/// Syntax nodes
/// TODO: the comment
struct Node {
nix::PosIdx Start;
nix::PosIdx End;
nixd::RangeIdx Range;
};

struct Function : Node {};

struct Identifier : Node {};

struct Formal : Node {
Identifier ID;
/// The default argument.
Node *Default;
};

struct Formals : Node {
std::vector<Formal> Formals;
bool Elipsis;
};

struct Function : Node {
Identifier *Arg;
Formals *Formals;
Node *Body;
};

struct Assert : Node {
Node *Cond;
Node *Body;
};

struct With : Node {
Node *Attrs;
Node *Body;
};

struct Binds : Node {};

struct Let : Node {
Binds *Binds;
Node *Body;
};

struct If : Node {};

struct ExprOp : Node {};
Expand Down Expand Up @@ -50,15 +83,4 @@ struct StringAttr : Node {};

struct AttrPath : Node {};

struct Formal : Node {
Identifier ID;
/// The default argument.
Node *Default;
};

struct Formals : Node {
std::vector<Formal> Formals;
bool Elipsis;
};

} // namespace nixd::syntax
13 changes: 9 additions & 4 deletions nixd/include/nixd/Syntax/Parser/Require.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "nixd/Expr/Expr.h"
#include "nixd/Syntax/Nodes.h"

#include <cstddef>
Expand All @@ -11,12 +12,16 @@ namespace nixd::syntax {
/// The symbols & positions should be mapped to nix::EvalState::state
/// Or owned by "ParseData"
struct ParseState {
nix::SymbolTable &symbols;
nix::PosTable &positions;
nix::SymbolTable &Symbols;
nix::PosTable &Positions;
};

struct ParseData {
ParseState state;
ParseState State;

nix::PosTable::Origin Origin;

Context<Node> Nodes;
};

// Note: copied from
Expand All @@ -35,4 +40,4 @@ struct StringToken {

#define YY_DECL \
int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner, \
nixd::syntax::ParseData *data)
nixd::syntax::ParseData *Data)
23 changes: 23 additions & 0 deletions nixd/include/nixd/Syntax/Range.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <nix/nixexpr.hh>

namespace nixd {

struct RangeIdx {
nix::PosIdx Begin;
nix::PosIdx End;
};

struct Range {
nix::Pos Begin;
nix::Pos End;
Range(nix::Pos Begin, nix::Pos End)
: Begin(std::move(Begin)), End(std::move(End)) {}
Range(RangeIdx Idx, const nix::PosTable &Table) {
Begin = Table[Idx.Begin];
End = Table[Idx.End];
}
};

} // namespace nixd
1 change: 0 additions & 1 deletion nixd/lib/Support/meson.build
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
libnixdSupportDeps = [ nix_all
, llvm
, nixdParser
, nixd_lsp_server
]

Expand Down
4 changes: 2 additions & 2 deletions nixd/lib/Syntax/Lexer/Lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ or { return OR_KW; }
/* It is impossible to match strings ending with '$' with one
regex because trailing contexts are only valid at the end
of a rule. (A sane but undocumented limitation.) */
yylval->STR = unescapeStr(data->state.symbols, yytext, yyleng);
yylval->STR = unescapeStr(Data->State.Symbols, yytext, yyleng);
return STR;
}
<STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
Expand Down Expand Up @@ -135,7 +135,7 @@ or { return OR_KW; }
return IND_STR;
}
<IND_STRING>\'\'\\{ANY} {
yylval->STR = unescapeStr(data->state.symbols, yytext + 2, yyleng - 2);
yylval->STR = unescapeStr(Data->State.Symbols, yytext + 2, yyleng - 2);
return IND_STR;
}
<IND_STRING>\$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; }
Expand Down
23 changes: 11 additions & 12 deletions nixd/lib/Syntax/Lexer/Prologue.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#pragma once

#ifdef __clang__
#pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
#endif

#include <boost/lexical_cast.hpp>

#include "Parser.tab.h"

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

#include <nix/nixexpr.hh>
#include <nix/symbol-table.hh>

using namespace nix;
#include <boost/lexical_cast.hpp>

#ifdef __clang__
#pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
#endif

// backup to recover from yyless(0)
thread_local YYLTYPE prev_yylloc;
Expand Down Expand Up @@ -46,7 +47,7 @@ static void adjustLoc(YYLTYPE *loc, const char *s, size_t len) {

// we make use of the fact that the parser receives a private copy of the input
// string and can munge around in it.
static nixd::syntax::StringToken unescapeStr(SymbolTable &symbols, char *s,
static nixd::syntax::StringToken unescapeStr(nix::SymbolTable &symbols, char *s,
size_t length) {
char *result = s;
char *t = s;
Expand Down Expand Up @@ -81,5 +82,3 @@ static nixd::syntax::StringToken unescapeStr(SymbolTable &symbols, char *s,

#define PUSH_STATE(state) yy_push_state(state, yyscanner)
#define POP_STATE() yy_pop_state(yyscanner)

#define CUR_POS makeCurPos(*yylloc, data)
72 changes: 60 additions & 12 deletions nixd/lib/Syntax/Parser/Parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
%define parse.error verbose
%defines
/* %no-lines */
%parse-param { void * scanner }
%parse-param { nixd::syntax::ParseData * data }
%lex-param { void * scanner }
%lex-param { nixd::syntax::ParseData * data }
%parse-param { void * Scanner }
%parse-param { nixd::syntax::ParseData * Data }
%lex-param { void * Scanner }
%lex-param { nixd::syntax::ParseData * Data }

%code requires {
#include "nixd/Syntax/Parser/Require.h"
Expand All @@ -21,6 +21,8 @@
nixd::syntax::Node *Node;
nixd::syntax::Identifier *Identifier;
nixd::syntax::If *If;
nixd::syntax::Formals *Formals;
nixd::syntax::Binds *Binds;

// Tokens
nixd::syntax::StringToken STR;
Expand All @@ -32,9 +34,10 @@
}


%type <Node> start expr expr_function
%type <Node> start expr expr_function expr_if expr_op
%type <Identifier> identifier
%type <If> expr_if
%type <Formals> formals
%type <Binds> binds
%token <Identifier> ID
%token <N> INT
%token <NF> FLOAT
Expand Down Expand Up @@ -66,12 +69,57 @@ start: expr;
expr: expr_function;

expr_function
: identifier ':' expr_function
| '{' formals '}' ':' expr_function
| '{' formals '}' '@' identifier ':' expr_function
| ASSERT expr ';' expr_function
| WITH expr ';' expr_function
| LET binds IN expr_function
: identifier ':' expr_function {
auto Func = new nixd::syntax::Function {
.Arg = $1,
.Formals = nullptr,
.Body = $3
};
Func->Range = mkRange(yylloc, *Data);
$$ = Func;
}
| '{' formals '}' ':' expr_function {
auto Func = new nixd::syntax::Function {
.Arg = nullptr,
.Formals = $2,
.Body = $5
};
Func->Range = mkRange(yylloc, *Data);
$$ = Func;
}
| '{' formals '}' '@' identifier ':' expr_function {
auto Func = new nixd::syntax::Function {
.Arg = $5,
.Formals = $2,
.Body = $7
};
Func->Range = mkRange(yylloc, *Data);
$$ = Func;
}
| ASSERT expr ';' expr_function {
auto Assert = new nixd::syntax::Assert {
.Cond = $2,
.Body = $4
};
Assert->Range = mkRange(yylloc, *Data);
$$ = Assert;
}
| WITH expr ';' expr_function {
auto With = new nixd::syntax::With {
.Attrs = $2,
.Body = $4
};
With->Range = mkRange(yylloc, *Data);
$$ = With;
}
| LET binds IN expr_function {
auto Let = new nixd::syntax::Let {
.Binds = $2,
.Body = $4
};
Let->Range = mkRange(yylloc, *Data);
$$ = Let;
}
| expr_if
;

Expand Down
13 changes: 13 additions & 0 deletions nixd/lib/Syntax/Parser/Prologue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,16 @@ YY_DECL;

void yyerror(YYLTYPE *loc, yyscan_t scanner, nixd::syntax::ParseData *data,
const char *error) {}

/// Convert a yacc location (yylloc) to nix::PosIdx
/// Store in the pos table
static nixd::RangeIdx mkRange(YYLTYPE YL, nix::PosTable &T,
const nix::PosTable::Origin &Origin) {
auto Begin = T.add(Origin, YL.first_line, YL.first_column);
auto End = T.add(Origin, YL.last_line, YL.last_column);
return {Begin, End};
}

static nixd::RangeIdx mkRange(YYLTYPE YL, nixd::syntax::ParseData &Data) {
return mkRange(YL, Data.State.Positions, Data.Origin);
}
2 changes: 1 addition & 1 deletion nixd/lib/Syntax/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ parser = custom_target('parser'
)

#------------------------------------------------------------------------------#
libnixdParserDeps = [ nix_all, nixdExpr ]
libnixdParserDeps = [ nix_all, nixdExpr, nixdSupport ]

libnixdParser = library('nixdParser'
, lexer
Expand Down
2 changes: 1 addition & 1 deletion nixd/lib/meson.build
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
subdir('Expr')
subdir('Nix')
subdir('Support')
subdir('Syntax')
subdir('AST')
subdir('Support')
subdir('Sema')
subdir('Server')

0 comments on commit 9abaf00

Please sign in to comment.