15 changed files with 317 additions and 5 deletions
@ -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