summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2013-07-17 00:28:52 -0400
committerJesse Luehrs <doy@tozt.net>2013-07-17 00:28:52 -0400
commit2d777b055b750c40d2698422202c4d3950822a0c (patch)
tree6850351691843d83db44593a0e2d9475ee4b9a78
parente371e62327f22039cbede6d4c40312ab046098f6 (diff)
downloadparse-keyword-2d777b055b750c40d2698422202c4d3950822a0c.tar.gz
parse-keyword-2d777b055b750c40d2698422202c4d3950822a0c.zip
initial sketch of the framework
now, just need to expose the parser functions to perl
-rw-r--r--Keyword.xs64
-rw-r--r--dist.ini3
-rw-r--r--lib/Parse/Keyword.pm30
3 files changed, 97 insertions, 0 deletions
diff --git a/Keyword.xs b/Keyword.xs
new file mode 100644
index 0000000..4531169
--- /dev/null
+++ b/Keyword.xs
@@ -0,0 +1,64 @@
+#include "EXTERN.h"
+#include "perl.h"
+#include "callparser1.h"
+#include "XSUB.h"
+
+static OP *parser_callback(pTHX_ GV *namegv, SV *psobj, U32 *flagsp)
+{
+ dSP;
+ SV *args_generator;
+
+ // call the parser callback
+ // it should take no arguments and return a coderef which, when called,
+ // produces the arguments to the keyword function
+ // the optree we want to generate is for something like
+ // mykeyword($code->())
+ // where $code is the thing returned by the parser function
+
+ PUSHMARK(SP);
+ call_sv(psobj, G_SCALAR);
+ SPAGAIN;
+ args_generator = SvREFCNT_inc(POPs);
+ PUTBACK;
+
+ if (!SvROK(args_generator) || SvTYPE(SvRV(args_generator)) != SVt_PVCV) {
+ croak("The parser function for %s must return a coderef, not %"SVf,
+ GvNAME(namegv), args_generator);
+ }
+
+ return newUNOP(OP_ENTERSUB, OPf_STACKED,
+ newCVREF(0,
+ Perl_scalar(newSVOP(OP_CONST, 0,
+ args_generator))));
+}
+
+// we will need helper functions for
+// - lexer functions
+// - lex_read_space
+// - lex_peek_unichar
+// - lex_stuff_sv
+// - parser functions (OP* return values should become coderefs)
+// - parse_arithexpr
+// - parse_barestmt
+// - parse_block
+// - parse_fullexpr
+// - parse_fullstmt
+// - parse_label
+// - parse_listexpr
+// - parse_stmtseq
+// - parse_termexpr
+// - random other things
+// - "read a variable name"
+// - "read a quoted string"
+// - "create a new lexical variable" (should return a reference to it)
+
+MODULE = Parse::Keyword PACKAGE = Parse::Keyword
+
+PROTOTYPES: DISABLE
+
+void
+install_keyword_handler(keyword, handler)
+ SV *keyword
+ SV *handler
+ CODE:
+ cv_set_call_parser((CV*)SvRV(keyword), parser_callback, handler);
diff --git a/dist.ini b/dist.ini
index a58d238..1482b99 100644
--- a/dist.ini
+++ b/dist.ini
@@ -9,7 +9,10 @@ dist = Parse-Keyword
repository = github
bugtracker_web = https://github.com/doy/parse-keyword/issues
bugtracker_mailto =
+awesome = =inc::MakeMaker
[AutoPrereqs]
+[Prereqs / ConfigureRequires]
+Devel::CallParser = 0
[ContributorsFromGit]
diff --git a/lib/Parse/Keyword.pm b/lib/Parse/Keyword.pm
index e69de29..b2e2709 100644
--- a/lib/Parse/Keyword.pm
+++ b/lib/Parse/Keyword.pm
@@ -0,0 +1,30 @@
+package Parse::Keyword;
+use strict;
+use warnings;
+use 5.014;
+# ABSTRACT: write syntax extensions in perl
+
+use Devel::CallParser;
+use XSLoader;
+
+XSLoader::load(
+ __PACKAGE__,
+ exists $Parse::Keyword::{VERSION} ? ${ $Parse::Keyword::{VERSION} } : (),
+);
+
+sub import {
+ my $package = shift;
+ my ($keywords) = @_;
+
+ my $caller = caller;
+
+ for my $keyword (keys %$keywords) {
+ my $sub = do {
+ no strict 'refs';
+ \&{ $caller . '::' . $keyword };
+ };
+ install_keyword_handler($sub, $keywords->{$keyword});
+ }
+}
+
+1;