Initial commit
parent
2335e1740c
commit
a9e16640ca
@ -1,5 +1,2 @@
|
||||
# https://git-scm.com/docs/gitignore
|
||||
# https://help.github.com/articles/ignoring-files
|
||||
# Example .gitignore files: https://github.com/github/gitignore
|
||||
/bower_components/
|
||||
/node_modules/
|
||||
/node_modules/
|
||||
/lib/
|
||||
|
@ -0,0 +1 @@
|
||||
/node_modules/
|
@ -0,0 +1,29 @@
|
||||
# nix-parser
|
||||
|
||||
TODO
|
||||
|
||||
## License
|
||||
|
||||
[WTFPL](http://www.wtfpl.net/txt/copying/) or [CC0](https://creativecommons.org/publicdomain/zero/1.0/), whichever you prefer. A donation and/or attribution are appreciated, but not required.
|
||||
|
||||
## Donate
|
||||
|
||||
My income consists largely of donations for my projects. If this module is useful to you, consider [making a donation](http://cryto.net/~joepie91/donate.html)!
|
||||
|
||||
You can donate using Bitcoin, PayPal, Flattr, cash-in-mail, SEPA transfers, and pretty much anything else.
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests welcome. Please make sure your modifications are in line with the overall code style, and ensure that you're editing the files in `src/`, not those in `lib/`.
|
||||
|
||||
Build tool of choice is `gulp`; simply run `gulp` while developing, and it will watch for changes.
|
||||
|
||||
Be aware that by making a pull request, you agree to release your modifications under the licenses stated above.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO
|
||||
|
||||
## API
|
||||
|
||||
TODO
|
@ -0,0 +1,31 @@
|
||||
var gulp = require("gulp");
|
||||
var presetES2015 = require("@joepie91/gulp-preset-es2015");
|
||||
var presetPegjs = require("@joepie91/gulp-preset-pegjs");
|
||||
|
||||
var sources = {
|
||||
babel: ["src/**/*.js"],
|
||||
pegjs: ["src/**/*.pegjs"]
|
||||
}
|
||||
|
||||
gulp.task('babel', function() {
|
||||
return gulp.src(sources.babel)
|
||||
.pipe(presetES2015({
|
||||
basePath: __dirname
|
||||
}))
|
||||
.pipe(gulp.dest("lib/"));
|
||||
});
|
||||
|
||||
gulp.task('pegjs', function() {
|
||||
return gulp.src(sources.pegjs)
|
||||
.pipe(presetPegjs({
|
||||
basePath: __dirname
|
||||
}))
|
||||
.pipe(gulp.dest("lib/"));
|
||||
});
|
||||
|
||||
gulp.task("watch", function () {
|
||||
gulp.watch(sources.babel, ["babel"]);
|
||||
gulp.watch(sources.pegjs, ["pegjs"]);
|
||||
});
|
||||
|
||||
gulp.task("default", ["babel", "pegjs", "watch"]);
|
@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require("./lib");
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "nix-parser",
|
||||
"version": "1.0.0",
|
||||
"description": "Parser for Nix expressions",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://git.cryto.net/joepie91/node-nix-parser.git"
|
||||
},
|
||||
"keywords": [
|
||||
"nix",
|
||||
"parser",
|
||||
"nixos"
|
||||
],
|
||||
"author": "Sven Slootweg",
|
||||
"license": "WTFPL",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@joepie91/gulp-preset-es2015": "^1.0.1",
|
||||
"@joepie91/gulp-preset-pegjs": "^1.0.0",
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"gulp": "^3.9.1"
|
||||
}
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
{
|
||||
function concatRepeat(first, rest, restIndex) {
|
||||
return [first].concat(rest.map(function(item) {
|
||||
return item[restIndex];
|
||||
}));
|
||||
}
|
||||
|
||||
function unnestFunctionCalls(first, nested, last) {
|
||||
var callStack = nested.concat([last]);
|
||||
|
||||
function createFunctionCall(i) {
|
||||
var func;
|
||||
|
||||
if (i === 0) {
|
||||
func = first;
|
||||
} else {
|
||||
func = createFunctionCall(i - 1);
|
||||
}
|
||||
|
||||
return {
|
||||
type: "functionCall",
|
||||
argument: callStack[i],
|
||||
function: func
|
||||
};
|
||||
}
|
||||
|
||||
return createFunctionCall(callStack.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
start
|
||||
= _ expression:expression* _ { return expression; }
|
||||
|
||||
// Character classes
|
||||
whitespace
|
||||
= "\t"
|
||||
/ "\n"
|
||||
/ "\r"
|
||||
/ " "
|
||||
|
||||
stringLiteralCharacter
|
||||
= !('"' / "\\") char:. { return char; }
|
||||
/ "\\" escapableCharacter
|
||||
|
||||
numberLiteralCharacter
|
||||
= [0-9.]
|
||||
|
||||
escapableCharacter
|
||||
= '"'
|
||||
/ "n"
|
||||
/ "t"
|
||||
/ "r"
|
||||
|
||||
commentCharacter
|
||||
= [^\n\r]
|
||||
|
||||
// Literals
|
||||
stringLiteral
|
||||
= '"' chars:stringLiteralCharacter+ '"' { return {type: "stringLiteral", value: chars.join("")} }
|
||||
|
||||
numberLiteral
|
||||
= chars:numberLiteralCharacter+ { return {type: "numberLiteral", value: chars.join("")} }
|
||||
|
||||
// Utilities
|
||||
_
|
||||
= (whitespace / comment)* {}
|
||||
|
||||
// Language constructs
|
||||
expression
|
||||
= additive
|
||||
/ operand
|
||||
|
||||
comment
|
||||
= "#" chars:commentCharacter* _ { return {type: "comment", text: chars.join("")} }
|
||||
|
||||
operand
|
||||
= group
|
||||
/ letBlock
|
||||
/ stringLiteral
|
||||
/ numberLiteral
|
||||
/ functionDefinition
|
||||
/ recursiveSet
|
||||
/ set
|
||||
/ possiblyNestedFunctionCall
|
||||
/ identifier
|
||||
|
||||
additive
|
||||
= left:subtractive
|
||||
_ "+"
|
||||
_ right:additive { return {type: "operation", operator: "+", left: left, right: right} }
|
||||
/ subtractive
|
||||
|
||||
subtractive
|
||||
= left:multiplicative
|
||||
_ "-"
|
||||
_ right:subtractive { return {type: "operation", operator: "-", left: left, right: right} }
|
||||
/ multiplicative
|
||||
|
||||
multiplicative
|
||||
= left:operand
|
||||
_ "*"
|
||||
_ right:multiplicative { return {type: "operation", operator: "*", left: left, right: right} }
|
||||
/ operand
|
||||
|
||||
identifier
|
||||
= literal:stringLiteral { return {type: "identifier", identifier: literal.value} }
|
||||
/ chars:[a-z.]i+ { return {type: "identifier", identifier: text()} }
|
||||
|
||||
group
|
||||
= "("
|
||||
_ expression:expression
|
||||
_ ")" { return {type: "group", expression: expression} }
|
||||
|
||||
functionDefinition
|
||||
= argument:functionDefinitionArgument
|
||||
_ ":"
|
||||
_ body:expression { return {type: "functionDefinition", argument: argument, body: body} }
|
||||
|
||||
functionDefinitionArgument
|
||||
= identifier
|
||||
/ setPattern
|
||||
|
||||
//functionCallWithParens
|
||||
// = functionName:expression "("
|
||||
// _ arg:expression
|
||||
// _ ")" {return {type: "functionCall", name: functionName, argument: arg} }
|
||||
//
|
||||
//functionCallWithoutParens
|
||||
// = functionName:expression " "
|
||||
// _ arg:expression {return {type: "functionCall", name: functionName, argument: arg} }
|
||||
//
|
||||
//functionCall
|
||||
// = functionCallWithParens
|
||||
// / functionCallWithoutParens
|
||||
|
||||
possiblyNestedFunctionCall
|
||||
= first:expression nested:expression* last:expression { return unnestFunctionCalls(first, nested, last); }
|
||||
|
||||
assignment
|
||||
= _ identifier:identifier
|
||||
_ "="
|
||||
_ expression:expression
|
||||
_ ";" { return {type: "assignment", identifier: identifier, expression: expression} }
|
||||
|
||||
assignmentList
|
||||
= items:assignment* { return items; }
|
||||
|
||||
bindingList
|
||||
= items:assignment* { return {type: "bindings", assignments: items} }
|
||||
|
||||
set
|
||||
= "{"
|
||||
_ items:assignmentList
|
||||
_ "}" { return {type: "set", assignments: items} }
|
||||
|
||||
recursiveSet
|
||||
= "rec"
|
||||
_ setData:set { return {type: "recursiveSet", assignments: setData.assignments} }
|
||||
|
||||
letBlock
|
||||
= "let"
|
||||
_ bindingList:bindingList
|
||||
_ "in"
|
||||
_ expression:expression { return {type: "letBlock", bindings: bindingList.assignments, expression: expression} }
|
||||
|
||||
setPattern
|
||||
= "{"
|
||||
_ args:setPatternVariableList
|
||||
_ "}" { return {type: "setPattern", variables: args} }
|
||||
|
||||
setPatternVariableList
|
||||
= firstItem:setPatternVariable otherItems:(_ "," _ setPatternVariable)* { return concatRepeat(firstItem, otherItems, 3); }
|
||||
|
||||
setPatternVariable
|
||||
= restParameter
|
||||
/ identifier
|
||||
|
||||
restParameter
|
||||
= "..." { return {type: "restParameter"} }
|
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const expressionParser = require("./expression");
|
||||
|
||||
module.exports = function(body) {
|
||||
return expressionParser.parse(body);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const util = require("util");
|
||||
const fs = require("fs");
|
||||
const parse = require("./");
|
||||
|
||||
function fullInspect(obj) {
|
||||
return util.inspect(obj, {colors: true, depth: null, customInspect: false})
|
||||
}
|
||||
|
||||
try {
|
||||
let contents = fs.readFileSync(process.argv[2]).toString();
|
||||
console.log(fullInspect(parse(contents)));
|
||||
} catch (err) {
|
||||
console.log(fullInspect(err))
|
||||
}
|
@ -0,0 +1 @@
|
||||
builtins.isInt 4
|
@ -0,0 +1 @@
|
||||
builtins.isInt(4)
|
@ -0,0 +1,7 @@
|
||||
let
|
||||
h = "Hello";
|
||||
w = "World";
|
||||
in
|
||||
{
|
||||
helloWorld = h + X + X;
|
||||
}
|
@ -0,0 +1 @@
|
||||
builtins.isInt 4 10 12
|
@ -0,0 +1,7 @@
|
||||
{ system, bootStdenv, noSysDirs, gccWithCC, gccWithProfiling
|
||||
, config, crossSystem, platform, lib
|
||||
, pkgsWithOverrides
|
||||
, ... }:
|
||||
rec {
|
||||
thing = config;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
# code goes here
|
||||
{
|
||||
v="understood"; # Another comment
|
||||
b=2;
|
||||
}
|
Loading…
Reference in New Issue