My personal project and infrastructure archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nomicon/prototypes/craftlang/craftlangc

88 lines
2.5 KiB

#!/usr/bin/env raku
grammar FileGrammar {
# The top-level file is a list of lines
token TOP { ^ <line>* %% \v* $ }
# A line is either a statement or scope
token line { <statement> | <scope> }
# A statement is a simple keyword-payload mapping
token statement { <keyword> \s <payload> }
# The set of simple key-value keywords
token keyword { < ANCHOR BG COUNT ENV MODE SPACING > }
# A simple payload
token payload { \S+ %% \h* }
# A scope is a scope-word + list of scope-lines
token scope { <scope-word> <scope-line>+ }
# The set of scope-opening keywords
token scope-word { < INPUTS OUTPUTS > }
# A scope is 2-space indented and either a statement or payload
token scope-line { \v+ \h \h [ <statement> | <payload> ] }
}
class Actions {
method TOP($/) {
make $<line>>>.made
}
method line($/) {
make .made with $<statement> || $<scope>;
}
method statement($/) {
make { Keyword => $<keyword>.made, Payload => $<payload>.made }
}
method scope($/) {
make { Keyword => $<scope-word>.made, Payload => $<scope-line>>>.made }
}
method scope-line($/) {
make $<statement> ?? $<statement>.made !! { Payload => $<payload>.made }
}
method keyword($/) { make ~$/ }
method payload($/) { make ~$/ }
method scope-word($/) { make ~$/ }
}
sub load_env($path, $env, $verbose) {
unless "$path/$env.craftenv".IO.e {
say "Required environment '$env' not found in search path '$path'!";
exit 2;
}
my $input = slurp "$path/$env.craftenv";
say "Parsing input: $input" if $verbose;
my @parsed = FileGrammar.parse($input, actions => Actions.new).made;
@parsed.map({ if $_<Payload> ~~ Str:D {
$_<Keyword> => $_<Payload>
} else {
$_<Keyword> => $_<Payload>.map({ $_<Keyword> => $_<Payload>}).Hash
}
}).Hash
}
sub MAIN($file, Str :$env="/dev/null", Str :$assets, Bool :$verbose) {
# Load and parse the main input file
my $input = slurp $file;
say "Parsing input: $input" if $verbose;
my @parsed = FileGrammar.parse($input, actions => Actions.new).made;
my %tree = @parsed.map({ $_<Keyword> => $_<Payload> ~~ Str:D ?? $_<Payload> !! $_<Payload>.map({ $_<Payload> }) }).Hash;
# Load and parse the environment tree from the loaded input
my %env = load_env($env, %tree<ENV>, $verbose);
# Print both for good measure
%tree.say;
%env.say;
}