Skip to content

Instantly share code, notes, and snippets.

@pmakholm
Created November 23, 2013 11:24
Show Gist options
  • Save pmakholm/7613450 to your computer and use it in GitHub Desktop.
Save pmakholm/7613450 to your computer and use it in GitHub Desktop.
Compiler for a very simple language
#!/usr/bin/env nqp-p
use NQPHLL;
grammar Expressive::Grammar is HLL::Grammar {
token TOP {
:my $*CUR_BLOCK := QAST::Block.new(QAST::Stmts.new());
<statementlist>
}
rule statementlist { :s
[ <statement> [ ';' || $ ] ]*
}
proto token statement {*}
token statement:sym<EXPR> { <EXPR> }
token statement:sym<const> { :s
<sym> <varname> ':=' <EXPR>
}
# Simple expressions
INIT {
Expressive::Grammar.O(':prec<w=>, :assoc<left>', '%exponentiation');
Expressive::Grammar.O(':prec<u=>, :assoc<left>', '%multiplicative');
Expressive::Grammar.O(':prec<t=>, :assoc<left>', '%additive');
}
token infix:sym<**> { <sym> <O('%exponentiation, :op<pow_n>')> }
token infix:sym<*> { <sym> <O('%multiplicative, :op<mul_n>')> }
token infix:sym<%> { <sym> <O('%multiplicative, :op<mod_n>')> }
token infix:sym<+> { <sym> <O('%additive, :op<add_n>')> }
token infix:sym<-> { <sym> <O('%additive, :op<sub_n>')> }
token circumfix:sym<( )> { :s '(' ~ ')' <EXPR> }
# Simple values
token term:sym<value> { '-'? \d+ }
token term:sym<variable> { <varname> }
# Names et al
token varname { '$' <[A..Za..z_]> <[A..Za..z0..9_]>* }
}
class Expressive::Actions is HLL::Actions {
method TOP($/) {
$*CUR_BLOCK.push($<statementlist>.ast);
make $*CUR_BLOCK;
}
method statementlist($/) {
my $stmts := QAST::Stmts.new( :node($/) );
for $<statement> {
$stmts.push($_.ast)
}
make $stmts;
}
method statement:sym<EXPR>($/) { make $<EXPR>.ast; }
method statement:sym<const>($/) {
my $name := ~$<varname>;
my $var := QAST::Var.new( :name($name), :scope('lexical'), :decl('var') );
$*CUR_BLOCK.symbol($name, :declared(1) );
make QAST::Op.new(
:op('bind'),
$var,
$<EXPR>.ast
);
}
method term:sym<value>($/) {
make QAST::IVal.new( :value(+$/.Str) )
}
method term:sym<variable>($/) {
my $name := ~$<varname>;
make QAST::Var.new( :name($name), :scope('lexical') );
}
method circumfix:sym<( )>($/) { make $<EXPR>.ast }
}
class Expressive::Compiler is HLL::Compiler {
}
sub MAIN(*@ARGS) {
my $comp := Expressive::Compiler.new();
$comp.language('expressive');
$comp.parsegrammar(Expressive::Grammar);
$comp.parseactions(Expressive::Actions);
$comp.command_line(@ARGS, :encoding('utf8'));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment