Commit fefded1c authored by Samuel Newbold's avatar Samuel Newbold

Support .{foo} and [.{bar}]

parent ec8c0cb0
......@@ -83,7 +83,7 @@ std::string::size_type Arg_script::parse_token(const std::string& src,
add_token(token, max_soon, errors);
return point;}
else if (src[split] == '{') {
token_start = add_function(src, token_start, split, max_soon, errors);
token_start = add_braced_token(src, token_start, split, max_soon, errors);
return src.find_first_not_of(WSPACE, token_start);}
else {
point = src.find_first_not_of(WSPACE, split);
......@@ -108,7 +108,8 @@ Arg_script::Arg_script(const std::string& src, unsigned max_soon,
errors.add_error(Exception(Argm::Mismatched_brace,src.substr(0,point+1)));
while (point < src.length()) // see if anything else is wrong
point = constructor(src, ++point, max_soon, errors);}
else std::abort();}
else std::abort();
else;}
Arg_script::Arg_script(const std::string& src, std::string::size_type& point,
unsigned max_soon, Error_list& errors) :
......@@ -159,7 +160,7 @@ void Arg_script::add_token(const std::string& src, unsigned max_soon,
default:
args.push_back(Arg_spec(src, max_soon, errors));}}
std::string::size_type Arg_script::add_function(const std::string& src,
std::string::size_type Arg_script::add_braced_token(const std::string& src,
std::string::size_type style_start, std::string::size_type point,
unsigned max_soon, Error_list& errors) {
if (style_start != point)
......
......@@ -14,7 +14,7 @@ class Arg_script {
Arg_script(const Rwsh_istream_p& input, const Rwsh_ostream_p& output,
const Rwsh_ostream_p& error, const std::string& indent,
char terminator);
std::string::size_type add_function(const std::string& src,
std::string::size_type add_braced_token(const std::string& src,
std::string::size_type style_start, std::string::size_type f_start,
unsigned max_soon, Error_list& errors);
std::string::size_type add_quote(const std::string& src,
......
......@@ -43,7 +43,7 @@ bool sub_term_char(char focus) {
default: return false;}}
} // close unnamed namespace
// Everything except substitutions and soon substitutions
// Everything without braces
Arg_spec::Arg_spec(const std::string& script, unsigned max_soon,
Error_list& errors) :
soon_level(0), ref_level(0), expand_count(0), word_selection(-1),
......@@ -96,43 +96,68 @@ Arg_spec::Arg_spec(const std::string& script, unsigned max_soon,
else if (script[0] == '\\') {type=FIXED; text=script.substr(1);}
else {type=FIXED; text=script;}};
// Substitutions and soon substitutions
Arg_spec::Arg_spec(const std::string& src, std::string::size_type style_start,
std::string::size_type& point, unsigned max_soon, Error_list& errors) :
soon_level(0), ref_level(0), expand_count(0), word_selection(-1),
substitution(0), text() {
auto tpoint = style_start;
if (src[tpoint] == '&') {
void Arg_spec::parse_brace_type(const std::string& src, unsigned max_soon,
std::string::size_type style, std::string::size_type end,
Error_list& errors) {
auto focus = style;
if (src[focus] == '.') {
type = FIXED;
++focus;}
else if (src[focus] == '[' && src[focus+1] == '.') {
type = FIXED;
focus += 2;}
else if (src[focus] == '&') {
type = SOON_SUBSTITUTION;
while (++tpoint < src.length() && src[tpoint] == '&') ++soon_level;}
else if (src[tpoint] == '$') {
while (++focus < end && src[focus] == '&') ++soon_level;}
else if (src[focus] == '$') {
type = SUBSTITUTION;
++tpoint, soon_level = max_soon;}
++focus, soon_level = max_soon;}
else type = FIXED; // This is a Bad_argfunction_style, but since we're going
// to continue processing, we need to properly initialize the structure
if (src[tpoint] != '{') {
if (focus != end)
errors.add_error(Exception(Argm::Bad_argfunction_style,
src.substr(style_start, point-style_start)));
tpoint = point;}
substitution = new Command_block(src, tpoint, soon_level, errors);
if (soon_level > max_soon)
errors.add_error(Exception(Argm::Not_soon_enough,
src.substr(style_start, tpoint-style_start)));
if (tpoint >= src.length() || sub_term_char(src[tpoint])) point = tpoint;
src.substr(style, end-style)));}
// Substitutions, soon substitutions, and literal brace strings
Arg_spec::Arg_spec(const std::string& src, std::string::size_type style,
std::string::size_type& point, unsigned max_soon, Error_list& errors) :
soon_level(0), ref_level(0), expand_count(0), word_selection(-1),
substitution(0), text() {
parse_brace_type(src, max_soon, style, point, errors);
if (type == FIXED) {
auto split = src.find_first_of('}', point);
if (split == std::string::npos)
throw Unclosed_brace(src.substr(0, point-1));
if (src[style] == '[')
if (src[split+1] == ']') ++split;
else errors.add_error(Exception(Argm::Mismatched_bracket,
src.substr(style, split-style+1)));
else;
text = src.substr(style, split-style+1);
point = split+1;}
else {
auto token_end = src.find_first_of(" };", tpoint);
if (src[tpoint] == '$') {
do ++expand_count;
while (++tpoint < src.length() && src[tpoint] == '$');
if (tpoint >= src.length() || sub_term_char(src[tpoint]));
else
try {word_selection = my_strtoi(src.substr(tpoint, token_end-tpoint));}
catch(...) {
errors.add_error(Exception(Argm::Invalid_word_selection,
src.substr(tpoint, token_end-tpoint)));}}
else errors.add_error(Exception(Argm::Invalid_word_selection,
src.substr(tpoint, token_end-tpoint)));
point = token_end;}}
substitution = new Command_block(src, point, soon_level, errors);
if (point < src.length() && !sub_term_char(src[point]))
parse_word_selection(src, point, errors);
if (soon_level > max_soon)
errors.add_error(Exception(Argm::Not_soon_enough,
src.substr(style, point-style)));}}
void Arg_spec::parse_word_selection(const std::string& src,
std::string::size_type& point, Error_list& errors){
auto token_end = src.find_first_of(" };", point);
if (src[point] == '$') {
do ++expand_count;
while (++point < src.length() && src[point] == '$');
if (point >= src.length() || sub_term_char(src[point]));
else
try {word_selection = my_strtoi(src.substr(point, token_end-point));}
catch(...) {
errors.add_error(Exception(Argm::Invalid_word_selection,
src.substr(point, token_end-point)));}}
else errors.add_error(Exception(Argm::Invalid_word_selection,
src.substr(point, token_end-point)));
point = token_end;}
Arg_spec::Arg_spec(Arg_type type_i, unsigned soon_level_i,
unsigned ref_level_i, unsigned expand_count_i,
......
......@@ -17,15 +17,19 @@ class Arg_spec {
std::string text;
std::string trailing;
void add_function_spec(const std::string& src);
template<class Out> Out evaluate_expansion(const std::string& value,
Out res) const;
template<class Out> Out evaluate_substitution(const Argm& src, Out res,
Error_list& exceptions) const;
template<class Out> Out evaluate_var(const Argm& src, Out res) const;
void parse_brace_type(const std::string& src, unsigned max_soon,
std::string::size_type style, std::string::size_type end,
Error_list& errors);
void parse_word_selection(const std::string& src,
std::string::size_type& point, Error_list& errors);
public:
Arg_spec(const std::string& script, unsigned max_soon, Error_list& errors);
Arg_spec(const std::string& src, std::string::size_type style_start,
Arg_spec(const std::string& src, std::string::size_type style,
std::string::size_type& point, unsigned max_soon, Error_list& errors);
Arg_spec(Arg_type type, unsigned soon_level, unsigned ref_level,
unsigned expand_count, int word_selection,
......
......@@ -33,7 +33,7 @@ call stack .source .try_catch_recursive(body)
.echo unacceptable argument count: received $required non-optional
echo , but needed $needed \(with $optional optional\) for $stack$}
.function_all_flags .bad_argfunction_style style {
echo $style is neither an argfunction nor a substitution}
echo $style is neither an argfunction nor a substitution nor a brace literal}
.function_all_flags .bad_args -- proto assigned needed excess call_stack ... {
.combine (unacceptable arguments: for prototype ) $proto , $nl
if_only .test_not_empty $assigned {
......@@ -145,9 +145,9 @@ call stack .source .try_catch_recursive(body)
echo call stack $stack$}
.function_all_flags .mismatched_brace context [stack ...] {
echo mismatched brace: $context $stack$}
.function_all_flags .mismatched_bracket context stack ... {
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
echo call stack: $stack$}
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
......
......@@ -20,7 +20,7 @@
.echo unacceptable argument count: received $required non-optional
echo , but needed $needed \(with $optional optional\) for $stack$}
.function_all_flags .bad_argfunction_style style {
echo $style is neither an argfunction nor a substitution}
echo $style is neither an argfunction nor a substitution nor a brace literal}
.function_all_flags .bad_args -- proto assigned needed excess call_stack ... {
.combine (unacceptable arguments: for prototype ) $proto , $nl
if_only .test_not_empty $assigned {
......@@ -132,9 +132,9 @@
echo call stack $stack$}
.function_all_flags .mismatched_brace context [stack ...] {
echo mismatched brace: $context $stack$}
.function_all_flags .mismatched_bracket context stack ... {
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
echo call stack: $stack$}
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
......
......@@ -87,6 +87,7 @@ fns git command [file ...] {
.else {&{whichp git} $-*$ $command}}
sfn-subcommand git add
fn-subcommand git branch
sfn-subcommand git checkout
fn-subcommand git clone
fn-subcommand git config
sfn-subcommand git commit
......@@ -94,8 +95,10 @@ sfn-subcommand git diff
fn-subcommand git fetch
fn-subcommand git help
fn-subcommand git log
fn-subcommand git mv
fn-subcommand git remote
fn-subcommand git push
sfn-subcommand git reset
sfn-subcommand git rm
sfn-subcommand git status
fns grep [-l] [regex] [file ...] {
......
......@@ -33,7 +33,7 @@ call stack .source .try_catch_recursive(body)
.echo unacceptable argument count: received $required non-optional
echo , but needed $needed \(with $optional optional\) for $stack$}
.function_all_flags .bad_argfunction_style style {
echo $style is neither an argfunction nor a substitution}
echo $style is neither an argfunction nor a substitution nor a brace literal}
.function_all_flags .bad_args -- proto assigned needed excess call_stack ... {
.combine (unacceptable arguments: for prototype ) $proto , $nl
if_only .test_not_empty $assigned {
......@@ -145,9 +145,9 @@ call stack .source .try_catch_recursive(body)
echo call stack $stack$}
.function_all_flags .mismatched_brace context [stack ...] {
echo mismatched brace: $context $stack$}
.function_all_flags .mismatched_bracket context stack ... {
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
echo call stack: $stack$}
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
......@@ -424,21 +424,25 @@ call stack .source
$.source /etc/hosts
/etc/hosts is not executable
call stack: .source
$.source test_files/unclosed_brace_newline.rwsh
$.source test_files/unclosed_brace.rwsh
fn bar {echo baz
mismatched brace: (fn bar) .source
$.source test_files/unclosed_brace.rwsh
$.source test_files/unclosed_brace_without_newline.rwsh
fn bar {echo baz
mismatched brace: (fn bar) .source
$.source test_files/unclosed_parenthesis_newline.rwsh
$.source test_files/unclosed_dot_brace.rwsh
echo bar .{argfunction baz
mismatched brace: (echo bar ) .source
$.source test_files/unclosed_parenthesis.rwsh
echo bar (baz
signal triggered: .mismatched_parenthesis ( echo bar ( .source )
mismatched parenthesis: (echo bar ()
call stack: .source
$.source test_files/unclosed_parenthesis.rwsh
$.source test_files/unclosed_parenthesis_without_newline.rwsh
echo bar (baz
signal triggered: .mismatched_parenthesis ( echo bar ( .source )
......@@ -1151,16 +1155,17 @@ $se {e &&&A}
&&&A attempts to substitute after the command has been run
$se {@{} e &&&without$A $.{mismatched} {.argfunction brace} &&&{thrown}B
}
@ is neither an argfunction nor a substitution
@ is neither an argfunction nor a substitution nor a brace literal
$A is not a valid word selection
call stack
&&&without$A attempts to substitute after the command has been run
$. is neither an argfunction nor a substitution
$. is neither an argfunction nor a substitution nor a brace literal
cannot specify arguments for (.argfunction brace!) directly
&&&{thrown} attempts to substitute after the command has been run
(B
) is not a valid word selection
call stack
(&&&{thrown}B
) attempts to substitute after the command has been run
$echo &{e &&A}
&&A attempts to substitute after the command has been run
$echo &&{e &A}
......@@ -1228,16 +1233,21 @@ $.collect_errors_only .nop {
exception from inside substitution .throw .mapped_argfunction .collect_errors_only
substitution (${.throw echo exception from inside substitution}) failed
call stack: .collect_errors_only
$e x{e bad argfunction style}
x is neither an argfunction nor a substitution
$echo before .{argfunction} between [.{argfunction}] after
before .{argfunction} between [.{argfunction}] after
$echo before ..{still bad} between [.{missing close} after
.. is neither an argfunction nor a substitution nor a brace literal
mismatched bracket: ([.{missing close})
$echo x{e bad argfunction style}
x is neither an argfunction nor a substitution nor a brace literal
$e x&&&{e x}
x&&& is neither an argfunction nor a substitution
x&&& is neither an argfunction nor a substitution nor a brace literal
$e $+{e x}
$+ is neither an argfunction nor a substitution
$+ is neither an argfunction nor a substitution nor a brace literal
$e &+{e x}
&+ is neither an argfunction nor a substitution
&+ is neither an argfunction nor a substitution nor a brace literal
$e &&${e x}
&&$ is neither an argfunction nor a substitution
&&$ is neither an argfunction nor a substitution nor a brace literal
(&&${e x}) attempts to substitute after the command has been run
$echo ${e 0 $nl}
(0
......@@ -1341,7 +1351,7 @@ $.for_each_line <outfile
.for_each_line requires an argfunction
$.for_each_line <outfile <another A{}
double redirection is not supported at this time: <outfile and <another
A is neither an argfunction nor a substitution
A is neither an argfunction nor a substitution nor a brace literal
$.for_each_line <outfile {
echo current line $*
if_only .test_greater $2 1 {
......
fn bar {echo baz
\ No newline at end of file
fn bar {echo baz
fn bar {echo baz
\ No newline at end of file
echo bar .{argfunction baz
echo bar (baz
\ No newline at end of file
echo bar (baz
echo bar (baz
\ No newline at end of file
......@@ -33,7 +33,7 @@ call stack .source .try_catch_recursive(body)
.echo unacceptable argument count: received $required non-optional
echo , but needed $needed \(with $optional optional\) for $stack$}
.function_all_flags .bad_argfunction_style style {
echo $style is neither an argfunction nor a substitution}
echo $style is neither an argfunction nor a substitution nor a brace literal}
.function_all_flags .bad_args -- proto assigned needed excess call_stack ... {
.combine (unacceptable arguments: for prototype ) $proto , $nl
if_only .test_not_empty $assigned {
......@@ -145,9 +145,9 @@ call stack .source .try_catch_recursive(body)
echo call stack $stack$}
.function_all_flags .mismatched_brace context [stack ...] {
echo mismatched brace: $context $stack$}
.function_all_flags .mismatched_bracket context stack ... {
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
echo call stack: $stack$}
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
......@@ -389,7 +389,7 @@ $.source /etc/rwshrc-basic
.echo unacceptable argument count: received $required non-optional
echo , but needed $needed \(with $optional optional\) for $stack$}
.function_all_flags .bad_argfunction_style style {
echo $style is neither an argfunction nor a substitution}
echo $style is neither an argfunction nor a substitution nor a brace literal}
.function_all_flags .bad_args -- proto assigned needed excess call_stack ... {
.combine (unacceptable arguments: for prototype ) $proto , $nl
if_only .test_not_empty $assigned {
......@@ -501,9 +501,9 @@ $.source /etc/rwshrc-basic
echo call stack $stack$}
.function_all_flags .mismatched_brace context [stack ...] {
echo mismatched brace: $context $stack$}
.function_all_flags .mismatched_bracket context stack ... {
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
echo call stack: $stack$}
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
......@@ -704,9 +704,9 @@ polish + .var_add
polish / .var_divide
$.global PATH /bin:/usr/bin
$.scope () {.getpid; .echo $nl}
29100
19929
$.scope () {.getppid; .echo $nl}
22179
3689
$.function_all_flags timings focus {
.combine $focus (: last\() ${.last_execution_time $focus} \) \
.combine (total\() ${.total_execution_time $focus} \) \
......@@ -722,18 +722,18 @@ $.function_all_flags clock-watch {
$clock-watch
timings: last(0.000000) total(0.000000) count(0)
clock-watch: last(0.000000) total(0.000000) count(0)
usleep overhead: 8.6e-05
.usleep: last(0.000686) total(0.000686) count(1)
/bin/true: last(0.001184) total(0.001184) count(1)
usleep overhead: 9.2e-05
.usleep: last(0.000692) total(0.000692) count(1)
/bin/true: last(0.001202) total(0.001202) count(1)
$clock-watch
timings: last(0.000106) total(0.000964) count(4)
clock-watch: last(0.003510) total(0.003510) count(1)
usleep overhead: 8.45e-05
.usleep: last(0.000683) total(0.001369) count(2)
/bin/true: last(0.000867) total(0.002051) count(2)
timings: last(0.000127) total(0.000814) count(4)
clock-watch: last(0.003347) total(0.003347) count(1)
usleep overhead: 9.2e-05
.usleep: last(0.000692) total(0.001384) count(2)
/bin/true: last(0.000748) total(0.001950) count(2)
$.mapped_argfunction {timings timings; timings clock-watch}
timings: last(0.000107) total(0.001461) count(8)
clock-watch: last(0.002152) total(0.005662) count(2)
timings: last(0.000104) total(0.001299) count(8)
clock-watch: last(0.002032) total(0.005379) count(2)
$.error a stderr print will come before the diff $nl
$.nop $A $FIGNORE
$
......
......@@ -28,10 +28,11 @@ line continuation (or it was supposed to be)
.source /etc/hosts {excess argfunc}
.source test_files/*fu*bar*
.source /etc/hosts
.source test_files/unclosed_brace_newline.rwsh
.source test_files/unclosed_brace.rwsh
.source test_files/unclosed_parenthesis_newline.rwsh
.source test_files/unclosed_brace_without_newline.rwsh
.source test_files/unclosed_dot_brace.rwsh
.source test_files/unclosed_parenthesis.rwsh
.source test_files/unclosed_parenthesis_without_newline.rwsh
.source test_files/multiple_errors.rwsh
.source test_files/bad_substitution.rwsh
.nop multiple statements \; on a line
......@@ -268,7 +269,9 @@ se {e &&{.throw .nop}; e after}
.collect_errors_only .nop {
${.throw echo exception from inside substitution}
echo after failed substitution}
e x{e bad argfunction style}
echo before .{argfunction} between [.{argfunction}] after
echo before ..{still bad} between [.{missing close} after
echo x{e bad argfunction style}
e x&&&{e x}
e $+{e x}
e &+{e x}
......
......@@ -33,7 +33,7 @@ call stack .source .try_catch_recursive(body)
.echo unacceptable argument count: received $required non-optional
echo , but needed $needed \(with $optional optional\) for $stack$}
.function_all_flags .bad_argfunction_style style {
echo $style is neither an argfunction nor a substitution}
echo $style is neither an argfunction nor a substitution nor a brace literal}
.function_all_flags .bad_args -- proto assigned needed excess call_stack ... {
.combine (unacceptable arguments: for prototype ) $proto , $nl
if_only .test_not_empty $assigned {
......@@ -145,9 +145,9 @@ call stack .source .try_catch_recursive(body)
echo call stack $stack$}
.function_all_flags .mismatched_brace context [stack ...] {
echo mismatched brace: $context $stack$}
.function_all_flags .mismatched_bracket context stack ... {
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
echo call stack: $stack$}
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment