Steven Haryanto > Language-Expr > Language::Expr

Download:
Language-Expr-0.23.tar.gz

Dependencies

Annotate this POD

Website

CPAN RT

Open  0
View/Report Bugs
Module Version: 0.23   Source  

NAME ^

Language::Expr - Simple minilanguage for use in expression

VERSION ^

This document describes version 0.23 of module Language::Expr (in distribution Language-Expr), released on 2014-05-01.

SYNOPSIS ^

    use 5.010;
    use strict;
    use warnings;
    use Language::Expr;
    my $le = Language::Expr->new;

    # evaluate expressions
    say $le->eval('1 + 2*3 + [4, 5][-1]'); # 12
    say $le->eval(q("i" . " love " .
                    {lang=>"perl", food=>"rujak"}["lang"])); # "i love perl"

    # convert Expr to Perl (string Perl code)
    say $le->perl('1 ^^ 2'); # "(1 xor 2)"

    # convert Expr to JavaScript
    say $le->js('1 . 2'); # "'' + 1 + 2"

    # convert Expr to PHP
    say $le->php('"x" x 10'); # "str_repeat(('x'), 10)"

    # convert Expr to compiled Perl code
    my $sub = $le->compile('($_[0]**2 + $_[1]**2)**0.5');
    say $sub->(3, 4); # 5

    # use variables & functions in expression (interpreted mode)
    $le->interpreted(1);
    $le->var('a' => 3, 'b' => 4);
    $le->func(pyth => sub { ($_[0]**2 + $_[1]**2)**0.5 });
    say $le->eval('pyth($a, $b)'); # 5

    # use variables & functions in expression (compiled mode, by default the Perl
    # compiler translates variables and function call as-is and runs it in
    # Language::Expr::Compiler::Perl namespace, but you can customize this, see
    # below)
    $le->interpreted(0);
    package Language::Expr::Compiler::Perl;
    sub pyth { ($_[0]**2 + $_[1]**2)**0.5 }
    our $a = 3;
    our $b = 4;
    package main;
    say $le->perl('pyth($a, $b)'); # "pyth($a, $b)"
    say $le->eval('pyth($a, $b)'); # 5

    # tell compiler to use My namespace, translate 'func()' to 'My::func()' and
    # '$var' to '$My::var'
    package My;
    sub pyth { sprintf("%.03f", ($_[0]**2 + $_[1]**2)**0.5) }
    our $a = 3;
    our $b = 4;
    package main;
    $le->compiler->hook_var (sub { '$My::'.$_[0] });
    $le->compiler->hook_func(sub { 'My::'.(shift)."(".join(", ", @_).")" });
    say $le->perl('pyth($a, $b)'); # "My::pyth($My::a, $My::b)"
    say $le->eval('pyth($a, $b)'); # "5.000"

    # enumerate variables
    use Data::Dump;
    dd $le->enum_vars('$a*$a + sqr($b)'); # ['a', 'b']

DESCRIPTION ^

Language::Expr defines a simple, Perl-like expression minilanguage. It supports mathematical and string operators, arrays, hashes, variables, and functions. See Language::Expr::Manual::Syntax for description of the language syntax.

This distribution consists of the language parser (Language::Expr::Parser), some interpreters (Language::Expr::Interpreter::*), and some compilers (Language::Expr::Compiler::*).

ATTRIBUTES (MANUAL) ^

interpreted => BOOL

Whether to use the interpreter. By default is 0 (use the compiler, which means Language::Expr expression will be compiled to Perl code first before executed).

Note: The compiler is used by default because the interpreter currently lacks subexpression (map/grep/sort) support. But the compiler cannot by default directly use variables and functions defined by var() and func(). This slight inconvenience might be rectified in the future.

interpreter => OBJ

Store the Language::Expr::Interpreter::Default instance.

compiler => OBJ

Store the Language::Expr::Compiler::Perl instance.

js_compiler => OBJ

Store the Language::Expr::Compiler::JS instance.

php_compiler => OBJ

Store the Language::Expr::Compiler::PHP instance.

varenumer => OBJ

Store the Language::Expr::Interpreter::VarEnumer instance.

METHODS ^

new()

Construct a new Language::Expr object, which is just a convenient front-end of the Expr parser, compilers, and interpreters. You can also use the parser/compiler/interpreter independently.

var(NAME => VALUE, ...)

Define variables. Note that variables are only directly usable in interpreted mode (see SYNOPSIS for example on how to use variables in compiled mode).

func(NAME => CODEREF, ...)

Define functions. Dies if function is defined multiple times. Note that functions are only directly usable in interpreted mode (see SYNOPSIS for example on how to use functions in compiled mode).

eval(STR) => RESULT

Evaluate expression in STR (either using the compiler or interpreter) and return the result. Will die if there is a parsing or runtime error. By default it uses the compiler unless you set interpreted to 1.

Also see compile() which will always use the compiler regardless of interpreted setting, and will save compilation result into a Perl subroutine (thus is more efficient if you need to evaluate an expression repeatedly).

perl(STR) => STR

Convert expression in STR and return a string Perl code. Dies on error. Internally just call $le->compiler->perl().

js(STR) => STR

Convert expression in STR and return a string JavaScript code. Dies on error. Internally just call $le->js_compiler->js().

php(STR) => STR

Convert expression in STR and return a string PHP code. Dies on error. Internally just call $le->php_compiler->php().

compile(STR) => CODEREF

Compile expression in STR into Perl subroutine. Dies on error. See also eval().

Inside the expression, you can use '$_[0]', '$_[1]', etc to access the subroutine's arguments, because compile() sets $_ to @_. Example:

 my $sub = $le->compile('($_[0]**2 + $_[1]**2)**0.5');
 say $sub->(3, 4); # 5

enum_vars(STR) => ARRAYREF

Enumerate variables mentioned in expression STR. Return empty arrayref if no variables are mentioned.

FAQ ^

Why yet another simplistic (restricted, etc) language? Why not just Perl?

When first adding expression support to Data::Schema (now Data::Sah), I want a language that is simple enough so I can easily convert it to Perl, PHP, JavaScript, and others. I do not need a fully-fledged programming language. In fact, Expr is not even Turing-complete, it does not support assignment or loops. Nor does it allow function definition (though it allows anonymous function in grep/map/usort). Instead, I just need some basic stuffs like mathematical/string/logical operators, arrays, hashes, functions, map/grep/usort. This language will mostly be used inside templates and schemas.

Why don't you use Language::Farnsworth, or Math::Expression, or Math::Expression::Evaluator, or $FOO?

I need several compilers and interpreters (some even with different semantics), so it's easier to start with a simple parser of my own. And of course there is personal preference of language syntax.

What is the difference between a compiler and interpreter?

An interpreter evaluates expression as it is being parsed, while a compiler generates a complete Perl (or whatever) code first. Thus, if you $le->eval() repeatedly using the interpreter mode (setting $le->interpreted(1)), you will repeatedly parse the expression each time. This can be one or more orders of magnitude slower compared to compiling into Perl once and then directly executing the Perl code repeatedly.

Note that if you use $le->eval() using the default compiler mode, you do not reap the benefits of compilation because the expression will be compiled each time you call $le->eval(). To save the compilation result, use $le->compile() or $le->perl() and compile the Perl code yourself using Perl's eval().

I want different syntax for (variables, foo operator, etc)!

Create your own language :-) Fork this distribution and start modifying the Language::Expr::Parser module.

How to show details of errors in expression?

This is a TODO item.

KNOWN BUGS ^

Due to possible bugs in Perl's RE engine or Regexp::Grammars or my grammar, some syntax errors will cause further parsing to fail.

SEE ALSO ^

Syntax reference: Language::Expr::Manual::Syntax

Modules that are using Language::Expr: Data::Sah (not yet released), Data::Template::Expr (not yet released).

Other related modules: Math::Expression, Math::Expression::Evaluator, Language::Farnsworth

HOMEPAGE ^

Please visit the project's homepage at https://metacpan.org/release/Language-Expr.

SOURCE ^

Source repository is at https://github.com/sharyanto/perl-Language-Expr.

BUGS ^

Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Language-Expr

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

AUTHOR ^

Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE ^

This software is copyright (c) 2014 by Steven Haryanto.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

syntax highlighting: