[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
oct2mat script based on parse tree
From: |
Muthiah Annamalai |
Subject: |
oct2mat script based on parse tree |
Date: |
Tue, 08 Jan 2008 13:21:36 -0600 |
User-agent: |
Thunderbird 2.0.0.6 (X11/20071022) |
Hello there,
I have a oct2mat like the one Paul Kienzle mentions in his
README file based on the AST walker. Utilizing Octave's
parse tree to do the conversion is very helpful and accurate
to a larger degree. Its still a work in progress (my disclaimer).
Large parts of the code are directly derived from Octave
source written by JWE.
This script is essentially to help deploy code to your colleagues
who want to use it on Matlab systems for whatever reason. Primary
development is still expected to be based on an Octave based
environment.
You can invoke the script as,
octave:1> oct2mat("full/path/my_cool_octave_function.m",1)
octave:2> oct2mat("full/path/my_cool_octave_script.m")
and the code is output to stdout, where from you can use some shell
scripts to redirect the output to another matlab directory.
I have attached the files. Im waiting for JWE to accept some
global export patches to access some parser information. Once that is
done, I plan to add it to the extras branch of octave-forge.
This code works only on the cvs version of Octave, as a external add-on.
Limitations include
1. Can treat only function files or script files not both.
2. Pollutes your command history, as it pipes out to octave_stdout.
3. Cannot handle a script file with function definitions
4. Doesnot write to a separate directory or file, just all output on
stdout. So you need to create a driver program.
5. Not sure if it works correctly for all cases.
Best,
-Muthu
/*
Copyright (C) 1992-2007 John W. Eaton
Copyright (C) 2008, Muthiah Annamalai
Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.
Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>.
*/
#include<string>
#include <cstdio>
#include <cstring>
#include<vector>
#include <set>
#include <string>
#include<iostream>
#include<octave/oct.h>
#include<octave/dynamic-ld.h>
#include<octave/oct-map.h>
#include<octave/oct-stream.h>
#include<octave/parse.h>
#include <octave/file-stat.h>
#include <octave/oct-env.h>
#include <octave/Cell.h>
#include <octave/dirfns.h>
#include <octave/error.h>
#include <octave/lex.h>
#include <octave/load-path.h>
#include <octave/oct-map.h>
#include <octave/oct-obj.h>
#include <octave/ov.h>
#include <octave/ov-usr-fcn.h>
#include <octave/symtab.h>
#include <octave/toplev.h>
#include <octave/unwind-prot.h>
#include <octave/file-ops.h>
#include <octave/utils.h>
#include <octave/pt-all.h>
#include "pt-pr-mat.h"
DEFUN_DLD(oct2mat,args,,
"converts the given file to matlab compatible script.\
\n Useage: oct2mat(filename)")
{
/*
(copy from parse.y, parse_and_execute_file() function )
1. Invoke the parser.
2. Check status, and report errors. Reset parser.
3. Give AST (global_command) to the tree_print_matlab_code.
4. Cleanup.
*/
if ( args.length() < 1 ) {
print_usage();
error("usage: oct2mat(filename,is_a_function);");
return octave_value();
}
std::string fname = args(0).string_value();
bool is_a_function = false;
if ( args.length() >= 2 ) {
is_a_function = args(1).bool_value();
}
fname = file_ops::canonicalize_file_name( fname );
unwind_protect::begin_frame ("oct2mat");
unwind_protect_bool (reading_script_file);
unwind_protect_str (curr_fcn_file_full_name);
reading_script_file = true;
curr_fcn_file_full_name = fname;
FILE *f = get_input_from_file (fname, 0);
if ( !f ) {
error("cannot open file", fname.c_str());
return octave_value();
}
unwind_protect::begin_frame ("oct2mat_parse");
unwind_protect_ptr (global_command);
YY_BUFFER_STATE old_buf = current_buffer ();
YY_BUFFER_STATE new_buf = create_buffer (f);
unwind_protect::add (restore_input_buffer, old_buf);
unwind_protect::add (delete_input_buffer, new_buf);
switch_to_buffer (new_buf);
unwind_protect_bool (line_editing);
unwind_protect_bool (get_input_from_eval_string);
unwind_protect_bool (parser_end_of_input);
line_editing = false;
get_input_from_eval_string = false;
parser_end_of_input = false;
int retval;
// is_function_file( fname )
if (is_a_function )
{
tree_print_matlab_code o2mat(octave_stdout);
octave_function * fcn = NULL;
//works only in 3.0.x+ CVS version
//fcn = load_fcn_from_file ( fname, "" , "", "", false );
if ( fcn ) {
fcn->accept(o2mat);
octave_stdout<<"\n";
} else {
error(" cannot find handle to current parsed function! ");
}
} else {
do
{
reset_parser ();
retval = octave_parse ();
if (retval == 0)
{
tree_print_matlab_code o2mat(octave_stdout);
if (global_command)
{
//handle the user script
global_command->accept(o2mat);
octave_stdout<<"\n";
global_command = 0;
OCTAVE_QUIT;
bool quit = (tree_return_command::returning
|| tree_break_command::breaking);
if (tree_return_command::returning)
tree_return_command::returning = 0;
if (tree_break_command::breaking)
tree_break_command::breaking--;
if (error_state)
{
error ("near line %d of file `%s'", input_line_number,
curr_fcn_file_full_name.c_str ());
break;
}
if (quit)
break;
}
else if (parser_end_of_input)
{
break;
}
//
// FIXME: if functions are found in a file middle,
// generate new output file like Matlab respects, and
// then create a handle for that.
//
//else if ( current_parsed_function() ) {
// current_parsed_function()->accept(o2mat);
// octave_stdout<<"\n";
//}
//else {
// octave_stdout << "no matches; possibly function undetected \n";
//}
}
else
{
error("parse error!");
break;
}
} while ( retval == 0 );
}
unwind_protect::run_frame ("oct2mat_parse");
unwind_protect::run_frame ("oct2mat");
//successfully executed the functions.
return octave_value();
}
/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/
## test the various matlab conversion code.
sigma(0) + !alpha(0)
if ( sigma(0) + !alpha(0) )
if ( beta(0) || rand(2) ) #must change #-comment to %, and || to |
disp("hello world"); %must change the " quote to '
endif %change to if
if ( 0 && 1 )
% all that goo must be changed on rhs of the fprintf statement
fprintf('hello world %d', SEEK_CUR, __error_text__, SEEK_END, SEEK_SET);
end
x = 0 && 1 %must be 0 & 1
y = "muthu" || "phd" %must be |
z = (and || they) && 'and forever lived'
a = ! died %must be ~
end
must_show_this=1
%comment
%more comments
#function f ()
a = "muthu"
y = "a b" || "y"
#end
function f ()
a = "muthu"
y = "a b" || "y"
end
#function f ()
a = "muthu"
y = "a b" || "y"
#end
function f ()
a = "muthu"
y = "a b" || "y"
end
all: conversions.cc pt-pr-mat.cc
mkoctfile -o oct2mat.oct conversions.cc pt-pr-mat.cc
/*
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007 John W. Eaton
Copyright (C) 2008, Muthiah Annamalai
Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.
Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>.
*/
#include <octave/ov.h>
#include <octave/error.h>
#include <octave/comment-list.h>
#include <octave/pt-all.h>
#include "pt-pr-mat.h"
//define this to get debugging messages on.
#define O2M_DBG
#undef O2M_DBG
//
// how I rip code, shamelessly.
//
static std::string
__unary_op_as_string (octave_value::unary_op op)
{
std::string retval;
switch (op)
{
case octave_value::op_not:
retval = "~";
break;
case octave_value::op_uplus:
retval = "+";
break;
case octave_value::op_uminus:
retval = "-";
break;
case octave_value::op_transpose:
retval = ".'";
break;
case octave_value::op_hermitian:
retval = "'";
break;
case octave_value::op_incr:
retval = "++";
break;
case octave_value::op_decr:
retval = "--";
break;
default:
retval = "<unknown-unop>";
}
return retval;
}
static std::string
__binary_op_as_string (octave_value::binary_op op)
{
std::string retval;
switch (op)
{
case octave_value::op_add:
retval = "+";
break;
case octave_value::op_sub:
retval = "-";
break;
case octave_value::op_mul:
retval = "*";
break;
case octave_value::op_div:
retval = "/";
break;
case octave_value::op_pow:
retval = "^";
break;
case octave_value::op_ldiv:
retval = "\\";
break;
case octave_value::op_lshift:
retval = "<<";
break;
case octave_value::op_rshift:
retval = ">>";
break;
case octave_value::op_lt:
retval = "<";
break;
case octave_value::op_le:
retval = "<=";
break;
case octave_value::op_eq:
retval = "==";
break;
case octave_value::op_ge:
retval = ">=";
break;
case octave_value::op_gt:
retval = ">";
break;
case octave_value::op_ne:
retval = "~=";
break;
case octave_value::op_el_mul:
retval = ".*";
break;
case octave_value::op_el_div:
retval = "./";
break;
case octave_value::op_el_pow:
retval = ".^";
break;
case octave_value::op_el_ldiv:
retval = ".\\";
break;
case octave_value::op_el_and:
retval = "&";
break;
case octave_value::op_el_or:
retval = "|";
break;
case octave_value::op_struct_ref:
retval = ".";
break;
default:
retval = "<unknown-binop>";
}
return retval;
}
static void do_oct2mat_oper(std::ostream &os, tree_binary_expression &expr)
{
std::string oprval="<unknown-binary>";
// debugging
#ifdef O2M_DBG
os << "address@hidden" << expr.oper() << "address@hidden ";
#endif
// this converts code into whatever form
// oct2mat requires.
if ( expr.is_boolean_expression() )
{
const tree_boolean_expression & tbr
= dynamic_cast<tree_boolean_expression &> (expr);
oprval="<unknown-bool>";
switch ( tbr.op_type() )
{
case tree_boolean_expression::bool_and:
oprval = "&";
break;
case tree_boolean_expression::bool_or:
oprval = "|";
break;
defualt:
oprval = "<unknown-bool>";
}
}
else
{
oprval=__binary_op_as_string(expr.op_type());
}
os << " " << oprval << " ";
return;
}
static void do_oct2mat_oper(std::ostream &os, tree_unary_expression &expr)
{
std::string oprval="<unknown-unary>";
//debugging
#ifdef O2M_DBG
os << "address@hidden" << expr.oper() << "address@hidden ";
#endif
oprval=__unary_op_as_string(expr.op_type());
os << " " << oprval << " ";
return;
}
void
tree_print_matlab_code::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)
{
#ifdef O2M_DBG
os << "% visiting anon-fcn handle \n";
#endif
indent ();
print_parens (afh, "(");
os << "@(";
tree_parameter_list *param_list = afh.parameter_list ();
if (param_list)
param_list->accept (*this);
os << ") ";
tree_statement_list *body = afh.body ();
if (body)
body->accept (*this);
print_parens (afh, ")");
}
void
tree_print_matlab_code::visit_argument_list (tree_argument_list& lst)
{
#ifdef O2M_DBG
os << "% visiting argument list \n";
#endif
tree_argument_list::iterator p = lst.begin ();
while (p != lst.end ())
{
tree_expression *elt = *p++;
if (elt)
{
elt->accept (*this);
if (p != lst.end ())
os << ", ";
}
}
}
void
tree_print_matlab_code::visit_binary_expression (tree_binary_expression& expr)
{
#ifdef O2M_DBG
os << "% visiting binary expression \n";
#endif
indent();
print_parens (expr, "(");
tree_expression *op1 = expr.lhs ();
if (op1)
op1->accept (*this);
do_oct2mat_oper(os,expr);
tree_expression *op2 = expr.rhs ();
if (op2)
op2->accept (*this);
print_parens (expr, ")");
}
void
tree_print_matlab_code::visit_break_command (tree_break_command&)
{
#ifdef O2M_DBG
os << "% visiting break cmd \n";
#endif
indent ();
os << "break";
}
void
tree_print_matlab_code::visit_colon_expression (tree_colon_expression& expr)
{
#ifdef O2M_DBG
os << "% visiting colon expression \n";
#endif
indent ();
print_parens (expr, "(");
tree_expression *op1 = expr.base ();
if (op1)
op1->accept (*this);
// Stupid syntax.
tree_expression *op3 = expr.increment ();
if (op3)
{
os << ":";
op3->accept (*this);
}
tree_expression *op2 = expr.limit ();
if (op2)
{
os << ":";
op2->accept (*this);
}
print_parens (expr, ")");
}
void
tree_print_matlab_code::visit_continue_command (tree_continue_command&)
{
#ifdef O2M_DBG
os << "% visiting continue \n";
#endif
indent ();
os << "continue";
}
void
tree_print_matlab_code::visit_decl_command (tree_decl_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting decl cmd \n";
#endif
indent ();
os << cmd.name () << " ";
tree_decl_init_list *init_list = cmd.initializer_list ();
if (init_list)
init_list->accept (*this);
}
void
tree_print_matlab_code::visit_decl_elt (tree_decl_elt& cmd)
{
#ifdef O2M_DBG
os << "% visiting decl elt \n";
#endif
tree_identifier *id = cmd.ident ();
if (id)
id->accept (*this);
tree_expression *expr = cmd.expression ();
if (expr)
{
os << " = ";
expr->accept (*this);
}
}
void
tree_print_matlab_code::visit_decl_init_list (tree_decl_init_list& lst)
{
#ifdef O2M_DBG
os << "% visiting decl init list \n";
#endif
tree_decl_init_list::iterator p = lst.begin ();
while (p != lst.end ())
{
tree_decl_elt *elt = *p++;
if (elt)
{
elt->accept (*this);
if (p != lst.end ())
os << ", ";
}
}
}
void
tree_print_matlab_code::visit_simple_for_command (tree_simple_for_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting simple for cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "for ";
tree_expression *lhs = cmd.left_hand_side ();
if (lhs)
lhs->accept (*this);
os << " = ";
tree_expression *expr = cmd.control_expr ();
if (expr)
expr->accept (*this);
newline ();
tree_statement_list *list = cmd.body ();
if (list)
{
increment_indent_level ();
list->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.trailing_comment ());
indent ();
os << "end";
}
void
tree_print_matlab_code::visit_complex_for_command (tree_complex_for_command&
cmd)
{
#ifdef O2M_DBG
os << "% visiting complex for cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "for [";
nesting.push ('[');
tree_argument_list *lhs = cmd.left_hand_side ();
if (lhs)
lhs->accept (*this);
nesting.pop ();
os << "] = ";
tree_expression *expr = cmd.control_expr ();
if (expr)
expr->accept (*this);
newline ();
tree_statement_list *list = cmd.body ();
if (list)
{
increment_indent_level ();
list->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.trailing_comment ());
indent ();
os << "endfor";
}
void
tree_print_matlab_code::visit_octave_user_function (octave_user_function& fcn)
{
#ifdef O2M_DBG
os << "% visiting user fcn \n";
#endif
reset ();
visit_octave_user_function_header (fcn);
tree_statement_list *cmd_list = fcn.body ();
if (cmd_list)
{
increment_indent_level ();
cmd_list->accept (*this);
decrement_indent_level ();
}
visit_octave_user_function_trailer (fcn);
}
void
tree_print_matlab_code::visit_octave_user_function_header
(octave_user_function& fcn)
{
#ifdef O2M_DBG
os << "% visiting user fcn header \n";
#endif
octave_comment_list *leading_comment = fcn.leading_comment ();
if (leading_comment)
{
print_comment_list (leading_comment);
newline ();
}
indent ();
os << "function ";
tree_parameter_list *ret_list = fcn.return_list ();
if (ret_list)
{
bool takes_var_return = fcn.takes_var_return ();
int len = ret_list->length ();
if (len > 1 || takes_var_return)
{
os << "[";
nesting.push ('[');
}
ret_list->accept (*this);
if (takes_var_return)
{
if (len > 0)
os << ", ";
os << "varargout";
}
if (len > 1 || takes_var_return)
{
nesting.pop ();
os << "]";
}
os << " = ";
}
std::string fcn_name = fcn.name ();
os << (fcn_name.empty () ? std::string ("(empty)") : fcn_name) << " ";
tree_parameter_list *param_list = fcn.parameter_list ();
if (param_list)
{
bool takes_varargs = fcn.takes_varargs ();
int len = param_list->length ();
if (len > 0 || takes_varargs)
{
os << "(";
nesting.push ('(');
}
param_list->accept (*this);
if (takes_varargs)
{
if (len > 0)
os << ", ";
os << "varargin";
}
if (len > 0 || takes_varargs)
{
nesting.pop ();
os << ")";
newline ();
}
}
else
{
os << "()";
newline ();
}
}
void
tree_print_matlab_code::visit_octave_user_function_trailer
(octave_user_function& fcn)
{
#ifdef O2M_DBG
os << "% visiting user fcn trailer \n";
#endif
print_indented_comment (fcn.trailing_comment ());
indent ();
os << "% endfunction";
newline ();
}
void
tree_print_matlab_code::visit_identifier (tree_identifier& id)
{
#ifdef O2M_DBG
os << "% visiting identifier \n";
#endif
indent ();
print_parens (id, "(");
std::string nm = id.name ();
std::map<std::string,std::string>::iterator iter= identifier_lut.find(nm);
if ( iter != identifier_lut.end() )
os << iter->second ;
else
os << (nm.empty () ? std::string ("(empty)") : nm);
print_parens (id, ")");
}
void
tree_print_matlab_code::visit_if_clause (tree_if_clause& cmd)
{
#ifdef O2M_DBG
os << "% visiting if clause \n";
#endif
tree_expression *expr = cmd.condition ();
if (expr)
expr->accept (*this);
newline ();
tree_statement_list *list = cmd.commands ();
if (list)
{
increment_indent_level ();
list->accept (*this);
decrement_indent_level ();
}
}
void
tree_print_matlab_code::visit_if_command (tree_if_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting if cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "if ";
tree_if_command_list *list = cmd.cmd_list ();
if (list)
list->accept (*this);
print_indented_comment (cmd.trailing_comment ());
indent ();
os << "end";
}
void
tree_print_matlab_code::visit_if_command_list (tree_if_command_list& lst)
{
#ifdef O2M_DBG
os << "% visiting if cmd list \n";
#endif
tree_if_command_list::iterator p = lst.begin ();
bool first_elt = true;
while (p != lst.end ())
{
tree_if_clause *elt = *p++;
if (elt)
{
if (! first_elt)
{
print_indented_comment (elt->leading_comment ());
indent ();
if (elt->is_else_clause ())
os << "else";
else
os << "elseif ";
}
elt->accept (*this);
}
first_elt = false;
}
}
void
tree_print_matlab_code::visit_index_expression (tree_index_expression& expr)
{
#ifdef O2M_DBG
os << "% visiting index expression \n";
#endif
indent ();
print_parens (expr, "(");
bool expr_has_parens = false;
tree_expression *e = expr.expression ();
if (e)
{
e->accept (*this);
expr_has_parens = e->is_postfix_indexed ();
}
std::list<tree_argument_list *> arg_lists = expr.arg_lists ();
std::string type_tags = expr.type_tags ();
std::list<string_vector> arg_names = expr.arg_names ();
int n = type_tags.length ();
std::list<tree_argument_list *>::iterator p_arg_lists = arg_lists.begin ();
std::list<string_vector>::iterator p_arg_names = arg_names.begin ();
for (int i = 0; i < n; i++)
{
switch (type_tags[i])
{
case '(':
{
char nc = nesting.top ();
if ((nc == '[' || nc == '{') && expr.paren_count () == 0)
os << "(";
else
os << " (";
nesting.push ('(');
tree_argument_list *l = *p_arg_lists;
if (l)
l->accept (*this);
nesting.pop ();
os << ")";
}
break;
case '{':
{
char nc = nesting.top ();
if ((nc == '[' || nc == '{') && expr.paren_count () == 0)
os << "{";
else
os << " {";
// We only care about whitespace inside [] and {} when we
// are defining matrix and cell objects, not when indexing.
nesting.push ('(');
tree_argument_list *l = *p_arg_lists;
if (l)
l->accept (*this);
nesting.pop ();
os << "}";
}
break;
case '.':
{
string_vector nm = *p_arg_names;
assert (nm.length () == 1);
os << "." << nm(0);
}
break;
default:
panic_impossible ();
}
p_arg_lists++;
p_arg_names++;
}
print_parens (expr, ")");
}
void
tree_print_matlab_code::visit_matrix (tree_matrix& lst)
{
#ifdef O2M_DBG
os << "% visiting matrix \n";
#endif
indent ();
print_parens (lst, "(");
os << "[";
nesting.push ('[');
tree_matrix::iterator p = lst.begin ();
while (p != lst.end ())
{
tree_argument_list *elt = *p++;
if (elt)
{
elt->accept (*this);
if (p != lst.end ())
os << "; ";
}
}
nesting.pop ();
os << "]";
print_parens (lst, ")");
}
void
tree_print_matlab_code::visit_cell (tree_cell& lst)
{
#ifdef O2M_DBG
os << "% visiting cell \n";
#endif
indent ();
print_parens (lst, "(");
os << "{";
nesting.push ('{');
tree_cell::iterator p = lst.begin ();
while (p != lst.end ())
{
tree_argument_list *elt = *p++;
if (elt)
{
elt->accept (*this);
if (p != lst.end ())
os << "; ";
}
}
nesting.pop ();
os << "}";
print_parens (lst, ")");
}
void
tree_print_matlab_code::visit_multi_assignment (tree_multi_assignment& expr)
{
#ifdef O2M_DBG
os << "% visiting muti assignment \n";
#endif
indent ();
print_parens (expr, "(");
tree_argument_list *lhs = expr.left_hand_side ();
if (lhs)
{
int len = lhs->length ();
if (len > 1)
{
os << "[";
nesting.push ('[');
}
lhs->accept (*this);
if (len > 1)
{
nesting.pop ();
os << "]";
}
}
os << "" << expr.oper() << "";
tree_expression *rhs = expr.right_hand_side ();
if (rhs)
rhs->accept (*this);
print_parens (expr, ")");
}
void
tree_print_matlab_code::visit_no_op_command (tree_no_op_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting no_op command \n";
#endif
indent ();
os << cmd.original_command ();
}
void
tree_print_matlab_code::visit_constant (tree_constant& val)
{
#ifdef O2M_DBG
os << "% visiting constant \n";
#endif
indent ();
print_parens (val, "(");
octave_value sval=val.rvalue();
std::string buf_str;
if ( sval.is_string() )
{
buf_str=sval.string_value();
// see if you need to escape the string stxt.
os << "'";
for( int idx=0; idx < buf_str.length(); ) {
if ( buf_str[idx] == '"' || buf_str[idx] == '\'' ) {
os << "\\" ;
os << buf_str[idx];
} else if ( buf_str[idx] == '\"' ) {
os << "'";
} else {
os << buf_str[idx];
}
idx++;
}
os << "'";
}
else
{
std::ostringstream buf;
val.print_raw (buf , true, print_original_text);
buf_str = buf.str();
// string-escaped sequence need to be printed out.
for( int idx=0; idx < buf_str.length(); ) {
if ( buf_str[idx] == '\\' ) {
os << buf_str[idx];
idx++;
os << buf_str[idx];
} else if ( buf_str[idx] == '\"' ) {
os << "'";
} else {
os << buf_str[idx];
}
idx++;
}
}
print_parens (val, ")");
}
void
tree_print_matlab_code::visit_fcn_handle (tree_fcn_handle& fh)
{
#ifdef O2M_DBG
os << "% visiting fcn handle\n";
#endif
indent ();
print_parens (fh, "(");
fh.print_raw (os, true, print_original_text);
print_parens (fh, ")");
}
void
tree_print_matlab_code::visit_parameter_list (tree_parameter_list& lst)
{
#ifdef O2M_DBG
os << "% visiting param-list \n";
#endif
tree_parameter_list::iterator p = lst.begin ();
while (p != lst.end ())
{
tree_decl_elt *elt = *p++;
if (elt)
{
elt->accept (*this);
if (p != lst.end ())
os << ", ";
}
}
}
void
tree_print_matlab_code::visit_postfix_expression (tree_postfix_expression& expr)
{
#ifdef O2M_DBG
os << "visiting postfix expression\n";
#endif
indent ();
print_parens (expr, "(");
tree_expression *e = expr.operand ();
if (e)
e->accept (*this);
do_oct2mat_oper(os,expr);
print_parens (expr, ")");
}
void
tree_print_matlab_code::visit_prefix_expression (tree_prefix_expression& expr)
{
#ifdef O2M_DBG
os << "visiting prefix expression\n";
#endif
indent ();
print_parens (expr, "(");
do_oct2mat_oper(os,expr);
tree_expression *e = expr.operand ();
if (e)
e->accept (*this);
print_parens (expr, ")");
}
void
tree_print_matlab_code::visit_return_command (tree_return_command&)
{
#ifdef O2M_DBG
os << "% visiting return command \n";
#endif
indent ();
os << "return";
}
void
tree_print_matlab_code::visit_return_list (tree_return_list& lst)
{
#ifdef O2M_DBG
os << "% visiting return list \n";
#endif
tree_return_list::iterator p = lst.begin ();
while (p != lst.end ())
{
tree_index_expression *elt = *p++;
if (elt)
{
elt->accept (*this);
if (p != lst.end ())
os << ", ";
}
}
}
void
tree_print_matlab_code::visit_simple_assignment (tree_simple_assignment& expr)
{
#ifdef O2M_DBG
os << "% visiting simple assignment \n";
#endif
indent ();
print_parens (expr, "(");
tree_expression *lhs = expr.left_hand_side ();
if (lhs)
lhs->accept (*this);
// assignment is mostly OK. Just that we need to
// re-form the += , *= operators by transforming the
// parse tree.
os << " " << expr.oper () << " ";
tree_expression *rhs = expr.right_hand_side ();
if (rhs)
rhs->accept (*this);
print_parens (expr, ")");
}
void
tree_print_matlab_code::visit_statement (tree_statement& stmt)
{
#ifdef O2M_DBG
os << "% visiting statement \n";
#endif
print_comment_list (stmt.comment_text ());
tree_command *cmd = stmt.command ();
if (cmd)
{
cmd->accept (*this);
if (! stmt.print_result ())
{
os << ";";
newline (" ");
}
else
newline ();
}
else
{
tree_expression *expr = stmt.expression ();
if (expr)
{
expr->accept (*this);
if (! stmt.print_result ())
{
os << ";";
newline (" ");
}
else
newline ();
}
}
}
void
tree_print_matlab_code::visit_statement_list (tree_statement_list& lst)
{
#ifdef O2M_DBG
os << "% visiting statement list \n";
#endif
for (tree_statement_list::iterator p = lst.begin (); p != lst.end (); p++)
{
tree_statement *elt = *p;
std::cerr << "One more stmt \n";
if (elt)
elt->accept (*this);
}
}
void
tree_print_matlab_code::visit_switch_case (tree_switch_case& cs)
{
#ifdef O2M_DBG
os << "% visiting s/w case \n";
#endif
print_comment_list (cs.leading_comment ());
indent ();
if (cs.is_default_case ())
os << "otherwise";
else
os << "case ";
tree_expression *label = cs.case_label ();
if (label)
label->accept (*this);
newline ();
tree_statement_list *list = cs.commands ();
if (list)
{
increment_indent_level ();
list->accept (*this);
newline ();
decrement_indent_level ();
}
}
void
tree_print_matlab_code::visit_switch_case_list (tree_switch_case_list& lst)
{
#ifdef O2M_DBG
os << "% visiting s/w case list \n";
#endif
tree_switch_case_list::iterator p = lst.begin ();
while (p != lst.end ())
{
tree_switch_case *elt = *p++;
if (elt)
elt->accept (*this);
}
}
void
tree_print_matlab_code::visit_switch_command (tree_switch_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting s/w cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "switch ";
tree_expression *expr = cmd.switch_value ();
if (expr)
expr->accept (*this);
newline ();
tree_switch_case_list *list = cmd.case_list ();
if (list)
{
increment_indent_level ();
list->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.leading_comment ());
indent ();
os << "end";
}
void
tree_print_matlab_code::visit_try_catch_command (tree_try_catch_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting try-catch cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "try";
newline ();
tree_statement_list *try_code = cmd.body ();
if (try_code)
{
increment_indent_level ();
try_code->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.middle_comment ());
indent ();
os << "catch";
newline ();
tree_statement_list *catch_code = cmd.cleanup ();
if (catch_code)
{
increment_indent_level ();
catch_code->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.trailing_comment ());
indent ();
os << "end";
}
void
tree_print_matlab_code::visit_unwind_protect_command
(tree_unwind_protect_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting unwind-protect-cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "";
newline ();
tree_statement_list *unwind_protect_code = cmd.body ();
if (unwind_protect_code)
{
increment_indent_level ();
unwind_protect_code->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.middle_comment ());
indent ();
os << "";
newline ();
tree_statement_list *cleanup_code = cmd.cleanup ();
if (cleanup_code)
{
increment_indent_level ();
cleanup_code->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.trailing_comment ());
indent ();
os << "";
}
void
tree_print_matlab_code::visit_while_command (tree_while_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting while cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "while ";
tree_expression *expr = cmd.condition ();
if (expr)
expr->accept (*this);
newline ();
tree_statement_list *list = cmd.body ();
if (list)
{
increment_indent_level ();
list->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.trailing_comment ());
indent ();
os << "end";
}
void
tree_print_matlab_code::visit_do_until_command (tree_do_until_command& cmd)
{
#ifdef O2M_DBG
os << "% visiting do-until-cmd \n";
#endif
print_comment_list (cmd.leading_comment ());
indent ();
os << "do";
newline ();
tree_statement_list *list = cmd.body ();
if (list)
{
increment_indent_level ();
list->accept (*this);
decrement_indent_level ();
}
print_indented_comment (cmd.trailing_comment ());
indent ();
os << "until";
tree_expression *expr = cmd.condition ();
if (expr)
expr->accept (*this);
newline ();
}
// Each print_code() function should call this before printing
// anything.
//
// This doesn't need to be fast, but isn't there a better way?
void
tree_print_matlab_code::indent (void)
{
assert (curr_print_indent_level >= 0);
if (printing_newlines)
{
if (beginning_of_line)
{
os << prefix;
for (int i = 0; i < curr_print_indent_level; i++)
os << " ";
beginning_of_line = false;
}
}
}
// All print_code() functions should use this to print new lines.
void
tree_print_matlab_code::newline (const char *alt_txt)
{
os << (printing_newlines ? "\n" : alt_txt);
beginning_of_line = true;
}
// For ressetting print_code state.
void
tree_print_matlab_code::reset (void)
{
beginning_of_line = true;
curr_print_indent_level = 0;
while (nesting.top () != 'n')
nesting.pop ();
}
void
tree_print_matlab_code::print_parens (const tree_expression& expr, const char
*txt)
{
int n = expr.paren_count ();
for (int i = 0; i < n; i++)
os << txt;
}
void
tree_print_matlab_code::print_comment_elt (const octave_comment_elt& elt)
{
bool printed_something = false;
bool prev_char_was_newline = false;
std::string comment = elt.text ();
size_t len = comment.length ();
size_t i = 0;
while (i < len && comment[i++] == '\n')
; /* Skip leading new lines. */
i--;
while (i < len)
{
char c = comment[i++];
if (c == '\n')
{
if (prev_char_was_newline)
os << "%";
newline ();
prev_char_was_newline = true;
}
else
{
if (beginning_of_line)
{
printed_something = true;
indent ();
os << "%%";
if (! (isspace (c) || c == '!'))
os << " ";
}
os << static_cast<char> (c);
prev_char_was_newline = false;
}
}
if (printed_something && ! beginning_of_line)
newline ();
}
void
tree_print_matlab_code::print_comment_list (octave_comment_list *comment_list)
{
if (comment_list)
{
octave_comment_list::iterator p = comment_list->begin ();
while (p != comment_list->end ())
{
octave_comment_elt elt = *p++;
print_comment_elt (elt);
if (p != comment_list->end ())
newline ();
}
}
}
void
tree_print_matlab_code::print_indented_comment (octave_comment_list
*comment_list)
{
increment_indent_level ();
print_comment_list (comment_list);
decrement_indent_level ();
}
/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/
/*
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
2006, 2007 John W. Eaton
Copyright (C) 2008, Muthiah Annamalai
Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.
Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>.
*/
#if !defined (octave_tree_print_matlab_code_h)
#define octave_tree_print_matlab_code_h 1
#include <stack>
#include <string>
#include <map>
#include <octave/comment-list.h>
#include <octave/pt-walk.h>
class tree_expression;
// How to print the code that the parse trees represent.
// and just make sure its Matlab compatible, as far as possible.
class
tree_print_matlab_code : public tree_walker
{
public:
tree_print_matlab_code (std::ostream& os_arg,
const std::string& pfx = std::string (),
bool pr_orig_txt = true)
: os (os_arg), prefix (pfx), nesting (),
print_original_text (pr_orig_txt),
curr_print_indent_level (0), beginning_of_line (true),
printing_newlines (true)
{
// For "none".
nesting.push ('n');
// LUT for identifier swapping.
// FIXME: make static
identifier_lut["SEEK_CUR"]="0";
identifier_lut["SEEK_END"]="1";
identifier_lut["SEEK_SET"]="-1";
identifier_lut["usage"]="error";
identifier_lut["print_usage"]="error";
identifier_lut["__error_text__"]="lasterr";
}
~tree_print_matlab_code (void) { }
void visit_anon_fcn_handle (tree_anon_fcn_handle&);
void visit_argument_list (tree_argument_list&);
void visit_binary_expression (tree_binary_expression&);
void visit_break_command (tree_break_command&);
void visit_colon_expression (tree_colon_expression&);
void visit_continue_command (tree_continue_command&);
void visit_decl_command (tree_decl_command&);
void visit_decl_elt (tree_decl_elt&);
void visit_decl_init_list (tree_decl_init_list&);
void visit_simple_for_command (tree_simple_for_command&);
void visit_complex_for_command (tree_complex_for_command&);
void visit_octave_user_function (octave_user_function&);
void visit_octave_user_function_header (octave_user_function&);
void visit_octave_user_function_trailer (octave_user_function&);
void visit_identifier (tree_identifier&);
void visit_if_clause (tree_if_clause&);
void visit_if_command (tree_if_command&);
void visit_if_command_list (tree_if_command_list&);
void visit_index_expression (tree_index_expression&);
void visit_matrix (tree_matrix&);
void visit_cell (tree_cell&);
void visit_multi_assignment (tree_multi_assignment&);
void visit_no_op_command (tree_no_op_command&);
void visit_constant (tree_constant&);
void visit_fcn_handle (tree_fcn_handle&);
void visit_parameter_list (tree_parameter_list&);
void visit_postfix_expression (tree_postfix_expression&);
void visit_prefix_expression (tree_prefix_expression&);
void visit_return_command (tree_return_command&);
void visit_return_list (tree_return_list&);
void visit_simple_assignment (tree_simple_assignment&);
void visit_statement (tree_statement&);
void visit_statement_list (tree_statement_list&);
void visit_switch_case (tree_switch_case&);
void visit_switch_case_list (tree_switch_case_list&);
void visit_switch_command (tree_switch_command&);
void visit_try_catch_command (tree_try_catch_command&);
void visit_unwind_protect_command (tree_unwind_protect_command&);
void visit_while_command (tree_while_command&);
void visit_do_until_command (tree_do_until_command&);
void suspend_newline (void) { printing_newlines = false; }
void resume_newline (void) { printing_newlines = true; }
private:
std::ostream& os;
std::string prefix;
std::stack<char> nesting;
bool print_original_text;
// Current indentation.
int curr_print_indent_level;
// TRUE means we are at the beginning of a line.
bool beginning_of_line;
// TRUE means we are printing newlines and indenting.
bool printing_newlines;
void reset_indent_level (void) { curr_print_indent_level = 0; }
void increment_indent_level (void) { curr_print_indent_level += 2; }
void decrement_indent_level (void) { curr_print_indent_level -= 2; }
void newline (const char *alt_txt = ", ");
void indent (void);
void reset (void);
void print_parens (const tree_expression& expr, const char *txt);
void print_comment_list (octave_comment_list *comment_list);
void print_comment_elt (const octave_comment_elt& comment_elt);
void print_indented_comment (octave_comment_list *comment_list);
tree_print_matlab_code (void);
// No copying!
std::map<std::string, std::string> identifier_lut;
tree_print_matlab_code(const tree_print_matlab_code&);
tree_print_matlab_code& operator = (const tree_print_matlab_code&);
};
#endif
/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/
fcn_file = {{"hello.m",0},{"hello2.m",0},{"hello3.m",1},{"hello4.m",0}};
arrayfun(@(x) oct2mat(x{1},x{2}),fcn_file)
- oct2mat script based on parse tree,
Muthiah Annamalai <=
- oct2mat script based on parse tree, John W. Eaton, 2008/01/08
- oct2mat script based on parse tree, John W. Eaton, 2008/01/08
- Re: oct2mat script based on parse tree, Muthiah Annamalai, 2008/01/09
- Re: oct2mat script based on parse tree, John W. Eaton, 2008/01/09
- Re: oct2mat script based on parse tree, Muthiah Annamalai, 2008/01/09
- Re: oct2mat script based on parse tree, John W. Eaton, 2008/01/09
- Re: oct2mat script based on parse tree, Muthiah Annamalai, 2008/01/09
Re: oct2mat script based on parse tree, Muthiah Annamalai, 2008/01/09