Task: Parsing_Shunting-yard algorithm

C: #include <sys/types.h>
#include <regex.h>
#include <stdio.h>

typedef struct {
	const char *s;
	int len, prec, assoc;
} str_tok_t;

typedef struct {
	const char * str;
	int assoc, prec;
	regex_t re;
} pat_t;

enum assoc { A_NONE, A_L, A_R };
pat_t pat_eos = {"", A_NONE, 0};

pat_t pat_ops[] = {
	{"^\\)",	A_NONE, -1},
	{"^\\*\\*",	A_R, 3},
	{"^\\^",	A_R, 3},
	{"^\\*",	A_L, 2},
	{"^/",		A_L, 2},
	{"^\\+",	A_L, 1},
	{"^-",		A_L, 1},
	{0}
};

pat_t pat_arg[] = {
	{"^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"},
	{"^[a-zA-Z_][a-zA-Z_0-9]*"},
	{"^\\(", A_L, -1},
	{0}
};

str_tok_t stack[256]; 
str_tok_t queue[256];
int l_queue, l_stack;
#define qpush(x) queue[l_queue++] = x
#define spush(x) stack[l_stack++] = x
#define spop()   stack[--l_stack]

void display(const char *s)
{
	int i;
	printf("\033[1;1H\033[JText | %s", s);
	printf("\nStack| ");
	for (i = 0; i < l_stack; i++)
		printf("%.*s ", stack[i].len, stack[i].s); 
	printf("\nQueue| ");
	for (i = 0; i < l_queue; i++)
		printf("%.*s ", queue[i].len, queue[i].s);
	puts("\n\n<press enter>");
	getchar();
}

int prec_booster;

#define fail(s1, s2) {fprintf(stderr, "[Error %s] %s\n", s1, s2); return 0;}

int init(void)
{
	int i;
	pat_t *p;

	for (i = 0, p = pat_ops; p[i].str; i++)
		if (regcomp(&(p[i].re), p[i].str, REG_NEWLINE|REG_EXTENDED))
			fail("comp", p[i].str);

	for (i = 0, p = pat_arg; p[i].str; i++)
		if (regcomp(&(p[i].re), p[i].str, REG_NEWLINE|REG_EXTENDED))
			fail("comp", p[i].str);

	return 1;
}

pat_t* match(const char *s, pat_t *p, str_tok_t * t, const char **e)
{
	int i;
	regmatch_t m;

	while (*s == ' ') s++;
	*e = s;

	if (!*s) return &pat_eos;

	for (i = 0; p[i].str; i++) {
		if (regexec(&(p[i].re), s, 1, &m, REG_NOTEOL))
			continue;
		t->s = s;
		*e = s + (t->len = m.rm_eo - m.rm_so);
		return p + i;
	}
	return 0;
}

int parse(const char *s) {
	pat_t *p;
	str_tok_t *t, tok;

	prec_booster = l_queue = l_stack = 0;
	display(s);
	while (*s) {
		p = match(s, pat_arg, &tok, &s);
		if (!p || p == &pat_eos) fail("parse arg", s);

		
		if (p->prec == -1) {
			prec_booster += 100;
			continue;
		}
		qpush(tok);
		display(s);

re_op:		p = match(s, pat_ops, &tok, &s);
		if (!p) fail("parse op", s);

		tok.assoc = p->assoc;
		tok.prec = p->prec;

		if (p->prec > 0)
			tok.prec = p->prec + prec_booster;
		else if (p->prec == -1) {
			if (prec_booster < 100)
				fail("unmatched )", s);
			tok.prec = prec_booster;
		}

		while (l_stack) {
			t = stack + l_stack - 1;
			if (!(t->prec == tok.prec && t->assoc == A_L)
					&& t->prec <= tok.prec)
				break;
			qpush(spop());
			display(s);
		}

		if (p->prec == -1) {
			prec_booster -= 100;
			goto re_op;
		}

		if (!p->prec) {
			display(s);
			if (prec_booster)
				fail("unmatched (", s);
			return 1;
		}

		spush(tok);
		display(s);
	}

	if (p->prec > 0)
		fail("unexpected eol", s);

	return 1;
}

int main()
{
	int i;
	const char *tests[] = { 
		"3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3",	
		"123",					
		"3+4 * 2 / ( 1 - 5 ) ^ 2 ^ 3.14",	
		"(((((((1+2+3**(4 + 5))))))",		
		"a^(b + c/d * .1e5)!",			
		"(1**2)**3",				
		"2 + 2 *",				
		0
	};

	if (!init()) return 1;
	for (i = 0; tests[i]; i++) {
		printf("Testing string `%s'   <enter>\n", tests[i]);
		getchar();

		printf("string `%s': %s\n\n", tests[i],
			parse(tests[i]) ? "Ok" : "Error");
	}

	return 0;
}


C++: #include <ciso646>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

using std::vector;
using std::string;




#include <exception>
#include <stdexcept>
template <typename...Args> std::runtime_error error( Args...args )
{
  return std::runtime_error( (std::ostringstream{} << ... << args).str() );
};










template <typename T> struct stack : public std::vector <T>
{
  using base_type = std::vector <T> ;
  T        push ( const T& x ) { base_type::push_back( x ); return x; }
  const T& top  ()             { return base_type::back(); }
  T        pop  ()             { T x = std::move( top() ); base_type::pop_back(); return x; }
  bool     empty()             { return base_type::empty(); }
};


using Number = double;






using Operator_Name = string;
using Precedence    = int;
enum class Associates { none, left_to_right, right_to_left };

struct Operator_Info { Precedence precedence; Associates associativity; };

std::unordered_map <Operator_Name, Operator_Info>  Operators =
{
  { "^", { 4, Associates::right_to_left } },
  { "*", { 3, Associates::left_to_right } },
  { "/", { 3, Associates::left_to_right } },
  { "+", { 2, Associates::left_to_right } },
  { "-", { 2, Associates::left_to_right } },
};

Precedence precedence   ( const Operator_Name& op ) { return Operators[ op ].precedence; }
Associates associativity( const Operator_Name& op ) { return Operators[ op ].associativity; }


using Token = string;

bool is_number           ( const Token& t ) { return regex_match( t, std::regex{ R"z((\d+(\.\d*)?|\.\d+)([Ee][\+\-]?\d+)?)z" } ); }
bool is_operator         ( const Token& t ) { return Operators.count( t ); }
bool is_open_parenthesis ( const Token& t ) { return t == "("; }
bool is_close_parenthesis( const Token& t ) { return t == ")"; }
bool is_parenthesis      ( const Token& t ) { return is_open_parenthesis( t ) or is_close_parenthesis( t ); }







template <typename T> std::ostream& operator << ( std::ostream& outs, const std::vector <T> & xs )
{
  std::size_t n = 0;  for (auto x : xs) outs << (n++ ? " " : "") << x;  return outs;
}








#include <iomanip>

struct Progressive_Display
{
  string token_name;
  string token_type;

  Progressive_Display()  
  {
    std::cout << "\n"
      "  INPUT │ TYPE │ ACTION           │ STACK        │ OUTPUT\n"
      "────────┼──────┼──────────────────┼──────────────┼─────────────────────────────\n";
  }

  Progressive_Display& operator () ( const Token& token )  
  {
    token_name = token;
    token_type = is_operator   ( token ) ? "op"
               : is_parenthesis( token ) ? "()"
               : is_number     ( token ) ? "num"
               : "";
    return *this;
  }

  Progressive_Display& operator () (  
    const string         & description,
    const stack  <Token> & stack,
    const vector <Token> & output )
  {
    std::cout                                                              << std::right
      << std::setw(  7 ) << token_name                            << " │ " << std::left
      << std::setw(  4 ) << token_type                            << " │ "
      << std::setw( 16 ) << description                           << " │ "
      << std::setw( 12 ) << (std::ostringstream{} << stack).str() << " │ "
      <<                    output                                << "\n";
    return operator () ( "" );  
  }
};


vector <Token> parse( const vector <Token> & tokens )

{
  vector <Token> output;
  stack  <Token> stack;

  Progressive_Display display;

  for (auto token : tokens)  

    
    if (is_number( token ))
    {
      output.push_back( token );
      display( token )( "num --> output", stack, output );
    }

    
    else if (is_operator( token ) or is_parenthesis( token ))
    {
      display( token );

      if (!is_open_parenthesis( token ))
      {
        
        
        
        
        while (!stack.empty()
          and (   (is_close_parenthesis( token ) and !is_open_parenthesis( stack.top() ))
               or (precedence( stack.top() ) > precedence( token ))
               or (    (precedence( stack.top() ) == precedence( token ))
                   and (associativity( token ) == Associates::left_to_right))))
        {
          output.push_back( stack.pop() );
          display( "pop --> output", stack, output );
        }

        
        if (is_close_parenthesis( token ))
        {
          stack.pop();
          display( "pop", stack, output );
        }
      }

      
      if (!is_close_parenthesis( token ))
      {
        stack.push( token );
        display( "push op", stack, output );
      }
    }

    
    else throw error( "unexpected token: ", token );

  

  display( "END" );
  while (!stack.empty())
  {
    output.push_back( stack.pop() );
    display( "pop --> output", stack, output );
  }

  return output;
}


int main( int argc, char** argv )

try
{
  auto tokens   = vector <Token> ( argv+1, argv+argc );
  auto rpn_expr = parse( tokens );
  std::cout
    << "\nInfix = " << tokens
    << "\nRPN   = " << rpn_expr
    << "\n";
}
catch (std::exception e)
{
  std::cerr << "error: " << e.what() << "\n";
  return 1;
}