With no example of "something like that" and a desire to continue my policy of "always provide code",
here's a "tinylanguage" parser complete with AST interpreter and the ability to translate to an equivalent perl program.
Tinylanguage is similar to but slightly different (postfix 'while', ?: instead of 'if') from
https://rosettacode.org/wiki/Compiler/syntax_analyzer
which is a fairly good example also (see the perl code).
The AST consists of perl objects and is displayed in a hierarchical indentation form.
The generated perl is weird, but as far as I have tested it, correct (TIMTOWTDI).
#!/usr/bin/perl
use strict; # tinylanguage
use warnings;
sub node { bless [ splice @_, 1 ], shift } # create perl object
sub error { my $line = substr($_, 0, pos($_)) =~ tr/\n// + 1;
tr/\n// < 2 ? die s/\G.*//sr =~ tr/\t/ /cr, "^ $_[0] !\n" :
die "\nERROR near line $line:\n", s/\G(.{0,30}).*/[** @_ **]$1/sr, "
+\n" }
sub want { /\G$_[1]/gc ? shift : error pop }
my $ws = qr/(?:#.*+|\s++)*+/; # match white space
my $pad = ' ' x 4; # AST indent padding
my %variables; # variable storage
sub expr # parse section
{
/\G$ws/gc;
my $tree =
/\G(print|putc?|int)\b/gc ? node uc $1 => expr(3) :
/\G(?:(-?\d+)|'(.*?)')/gc ? node NUMBER => $+ : # or string
/\G(\w+)$ws=(?!=)/gc ? node STORE => "$1", expr(3) :
/\G\w+/gc ? node FETCH => $& :
/\G-/gc ? node UMINUS => expr(8) :
/\G\+/gc ? expr(8) :
/\G\(/gc ? want expr(0), qr/\)/, 'Missing Right P
+aren' :
/\G\{/gc ? want expr(0), qr/\}/, 'Missing Right B
+race' :
error 'Operand Expected';
$tree =
/\G$ws/gc ? $tree :
$_[0] <= 9 && /\G\;(?=$ws(?:\z|\)|\}))/gc ? $tree : # ignore redun
+dant ;
$_[0] <= 0 && /\G\;/gc ? node STMT => # merging STMTs
ref $tree eq 'STMT' ? @$tree : $tree, expr(1) :
$_[0] <= 1 && /\Gwhile\b/gc ? node WHILE => $tree, expr(2) :
$_[0] <= 2 && /\Gand\b/gc ? node AND => $tree, expr(3) :
$_[0] <= 3 && /\G\?/gc ? node COND => $tree,
want( expr(3), ':', 'Missing : '), expr(3) :
$_[0] <= 4 && /\G==/gc ? node EQ => $tree, expr(5) :
$_[0] <= 5 && /\G>/gc ? node GT => $tree, expr(6) :
$_[0] <= 5 && /\G</gc ? node LT => $tree, expr(6) :
$_[0] <= 6 && /\G\+/gc ? node ADD => $tree, expr(7) :
$_[0] <= 6 && /\G\-/gc ? node SUBTRACT => $tree, expr(7) :
$_[0] <= 6 && /\G\./gc ? node CONCAT => $tree, expr(7) :
$_[0] <= 7 && /\G\*(?!\*)/gc ? node MULTIPLY => $tree, expr(8) :
$_[0] <= 7 && /\G\//gc ? node DIVIDE => $tree, expr(8) :
$_[0] <= 7 && /\G%/gc ? node MOD => $tree, expr(8) :
$_[0] <= 7 && /\Gx\b/gc ? node DUP => $tree, expr(8) :
$_[0] <= 8 && /\G\*\*/gc ? node POWER => $tree, expr(8) :
return $tree while 1;
}
sub ADD::value { $_[0][0]->value + $_[0][1]->value } # execute se
+ction
sub SUBTRACT::value { $_[0][0]->value - $_[0][1]->value }
sub CONCAT::value { $_[0][0]->value . $_[0][1]->value }
sub MULTIPLY::value { $_[0][0]->value * $_[0][1]->value }
sub DIVIDE::value { $_[0][0]->value / $_[0][1]->value }
sub MOD::value { $_[0][0]->value % $_[0][1]->value }
sub DUP::value { $_[0][0]->value x $_[0][1]->value }
sub POWER::value { $_[0][0]->value ** $_[0][1]->value }
sub AND::value { $_[0][0]->value and $_[0][1]->value }
sub UMINUS::value { - $_[0][0]->value }
sub INT::value { int $_[0][0]->value }
sub COND::value { $_[0][0]->value ? $_[0][1]->value : $_[0][2]->va
+lue }
sub NUMBER::value { $_[0][0] }
sub PRINT::value { print my $t = $_[0][0]->value, "\n"; $t }
sub PUT::value { print my $t = $_[0][0]->value; $t }
sub PUTC::value { print chr( my $t = $_[0][0]->value ); $t }
sub STMT::value { (map $_->value, @{ $_[0] })[-1] }
sub GT::value { $_[0][0]->value > $_[0][1]->value ? 1 : 0 }
sub LT::value { $_[0][0]->value < $_[0][1]->value ? 1 : 0 }
sub EQ::value { $_[0][0]->value == $_[0][1]->value ? 1 : 0 }
sub WHILE::value { $_[0][0]->value while $_[0][1]->value; 0 }
sub FETCH::value { $variables{$_[0][0]} // 0 }
sub STORE::value { $variables{$_[0][0]} = $_[0][1]->value }
sub FETCH::show { "FETCH $_[0][0]\n" } # display AST section
sub STORE::show { "STORE $_[0][0]\n" . $_[0][1]->show =~ s/^/$pad/
+gmr}
sub NUMBER::show { local $_ = $_[0][0]; /\s|^\z/ ? "'$_'\n" : "$_\n
+" }
sub UNIVERSAL::show
{ ref($_[0]) . "\n" . join('', map $_->show, @{$_[0]}) =~ s/^/$pad/g
+mr }
# begin translate to perl
my %var;
my %op = qw( ADD + SUBTRACT - MULTIPLY * DIVIDE / CONCAT . MOD %
EQ == LT < GT > DUP x POWER ** AND and
);
sub FETCH::var { $var{$_[0][0]}++ }
sub STORE::var { $var{$_[0][0]}++; $_[0]->SUPER::var }
sub UNIVERSAL::var { ref($_) and $_->var for @{ $_[0] } }
sub NUMBER::perl { qq("$_[0][0]") }
sub FETCH::perl { "\$$_[0][0]" }
sub STORE::perl { "\$$_[0][0] = @{[ $_[0][1]->perl ]}" }
sub PRINT::perl { "print @{[ $_[0][0]->perl ]}, \"\\n\"\n" }
sub PUT::perl { "print @{[ $_[0][0]->perl ]}\n" }
sub PUTC::perl {
"do{local \$\@ = @{[$_[0][0]->perl]}; print chr \$\@\n; \$\@}" }
sub STMT::perl { join ';', map $_->perl, @{ $_[0] } }
sub WHILE::perl { "\nwhile(do{@{[$_[0][1]->perl]}}){" .
"do{@{[$_[0][0]->perl]}}}" }
sub COND::perl { "do{@{[$_[0][0]->perl]}}\n" .
"?" .
"do{@{[$_[0][1]->perl]}}" .
":" .
"do{@{[$_[0][2]->perl]}}" }
sub UNIVERSAL::perl { "do{@{[$_[0][0]->perl]}}\n" .
"$op{ref $_[0]}\n" .
"do{@{[$_[0][1]->perl]}}" }
# end translate to perl
@ARGV or local $/ = ''; # control section - read test cases by paragra
+ph
for ( @ARGV ? <> : <DATA> ) # if no args, use DATA section test cases
{
%variables = ();
s/\s*\z/\n/;
/^last\n\z/ and last;
/^\h*[^#\n]/m or next; # no uncommented code
print;
eval
{
my $tree = expr(0);
pos($_) == length or error 'Incomplete Parse';
print $tree->show; # prints the AST
$tree->value; # executes the AST
%var = (); # generate perl from AST
$tree->var;
my $perl = "do{\n@{[ map qq(my \$$_ =), sort keys %var ]} 0;\n";
$perl .= $tree->perl . '};1';
print "\n$perl\n\n";
eval $perl or die $@; # run the generated perl
1 } or print "$@\n";
print '-' x 70, "\n";
}
__DATA__
print foobar
# inspired by https://rosettacode.org/wiki/Compiler/Sample_programs#Fa
+ctorial
n = fact = 1;
fact = fact * n = n + 1 while n < 12;
print fact;
# 12 factorial is 479001600
n = 1; # primes < 100
put 2;
(
i = isprime = 2;
n % i == 0 and isprime = 0 while isprime and ( i = i + 1 ) ** 2 - 1 <
+n;
isprime and put ' ' . n;
) while ( n = n + 2 ) < 100;
print '' # output just a newline
( put foo = foo + (foo < 20 ? 2 : 10); put ' ' ) while foo < 100; prin
+t ''
stars = '*'; # triangle
{
print ' ' x ( 30 - n ) . stars;
stars = stars . '**'
} while (n = n + 1) < 11
ch = 65; # A to Z
ch = ch + 1 while ( putc ch ) < 90;
print ''
# converted from
# https://rosettacode.org/wiki/Compiler/Sample_programs#Fibonacci_sequ
+ence
# fibonacci of 44 is 701408733
#
n = 44;
i = 1;
a = 0;
b = 1;
{
w = a + b;
a = b;
b = w;
i = i + 1;
} while (i < n);
print w
# converted from
# https://rosettacode.org/wiki/Compiler/Sample_programs#Greatest_commo
+n_divisor
# Compute the gcd of 1071, 1029: 21
#
a = 1071;
b = 1029;
#
{
new_a = b;
b = a % b;
a = new_a;
} while b;
print a;
# This is an ascii Mandelbrot generator converted from
# https://rosettacode.org/wiki/Compiler/Sample_programs#Ascii_Mandlebr
+ot
#
left_edge = -420;
right_edge = 300;
top_edge = 300;
bottom_edge = -300;
x_step = 7;
y_step = 15;
#
max_iter = 200;
#
y0 = top_edge;
{
x0 = left_edge;
{
x = y = i = 0;
the_char = ' ';
{
x_x = x * x / 200;
y_y = y * y / 200;
(x_x + y_y > 800 ) and {
the_char = i > 9 ? '@' : i;
i = max_iter;
};
y = x * y / 100 + y0;
x = x_x - y_y + x0;
i = i + 1;
} while (i < max_iter) ;
put(the_char);
x0 = x0 + x_step;
} while (x0 < right_edge) ;
print '';
y0 = y0 - y_step;
} while y0 > bottom_edge ;
print foobar
PRINT
FETCH foobar
0
do{
my $foobar = 0;
print $foobar, "\n"
};1
0
----------------------------------------------------------------------
# inspired by https://rosettacode.org/wiki/Compiler/Sample_programs#Fa
+ctorial
n = fact = 1;
fact = fact * n = n + 1 while n < 12;
print fact;
# 12 factorial is 479001600
STMT
STORE n
STORE fact
1
WHILE
STORE fact
MULTIPLY
FETCH fact
STORE n
ADD
FETCH n
1
LT
FETCH n
12
PRINT
FETCH fact
479001600
do{
my $fact = my $n = 0;
$n = $fact = "1";
while(do{do{$n}
<
do{"12"}}){do{$fact = do{$fact}
*
do{$n = do{$n}
+
do{"1"}}}};print $fact, "\n"
};1
479001600
----------------------------------------------------------------------
n = 1; # primes < 100
put 2;
(
i = isprime = 2;
n % i == 0 and isprime = 0 while isprime and ( i = i + 1 ) ** 2 - 1 <
+n;
isprime and put ' ' . n;
) while ( n = n + 2 ) < 100;
print '' # output just a newline
STMT
STORE n
1
PUT
2
WHILE
STMT
STORE i
STORE isprime
2
WHILE
AND
EQ
MOD
FETCH n
FETCH i
0
STORE isprime
0
AND
FETCH isprime
LT
SUBTRACT
POWER
STORE i
ADD
FETCH i
1
2
1
FETCH n
AND
FETCH isprime
PUT
CONCAT
' '
FETCH n
LT
STORE n
ADD
FETCH n
2
100
PRINT
''
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
do{
my $i = my $isprime = my $n = 0;
$n = "1";print "2"
;
while(do{do{$n = do{$n}
+
do{"2"}}
<
do{"100"}}){do{$i = $isprime = "2";
while(do{do{$isprime}
and
do{do{do{do{$i = do{$i}
+
do{"1"}}
**
do{"2"}}
-
do{"1"}}
<
do{$n}}}){do{do{do{do{$n}
%
do{$i}}
==
do{"0"}}
and
do{$isprime = "0"}}};do{$isprime}
and
do{print do{" "}
.
do{$n}
}}};print "", "\n"
};1
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
----------------------------------------------------------------------
( put foo = foo + (foo < 20 ? 2 : 10); put ' ' ) while foo < 100; prin
+t ''
STMT
WHILE
STMT
PUT
STORE foo
ADD
FETCH foo
COND
LT
FETCH foo
20
2
10
PUT
' '
LT
FETCH foo
100
PRINT
''
2 4 6 8 10 12 14 16 18 20 30 40 50 60 70 80 90 100
do{
my $foo = 0;
while(do{do{$foo}
<
do{"100"}}){do{print $foo = do{$foo}
+
do{do{do{$foo}
<
do{"20"}}
?do{"2"}:do{"10"}}
;print " "
}};print "", "\n"
};1
2 4 6 8 10 12 14 16 18 20 30 40 50 60 70 80 90 100
----------------------------------------------------------------------
stars = '*'; # triangle
{
print ' ' x ( 30 - n ) . stars;
stars = stars . '**'
} while (n = n + 1) < 11
STMT
STORE stars
*
WHILE
STMT
PRINT
CONCAT
DUP
' '
SUBTRACT
30
FETCH n
FETCH stars
STORE stars
CONCAT
FETCH stars
**
LT
STORE n
ADD
FETCH n
1
11
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
do{
my $n = my $stars = 0;
$stars = "*";
while(do{do{$n = do{$n}
+
do{"1"}}
<
do{"11"}}){do{print do{do{" "}
x
do{do{"30"}
-
do{$n}}}
.
do{$stars}, "\n"
;$stars = do{$stars}
.
do{"**"}}}};1
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
----------------------------------------------------------------------
ch = 65; # A to Z
ch = ch + 1 while ( putc ch ) < 90;
print ''
STMT
STORE ch
65
WHILE
STORE ch
ADD
FETCH ch
1
LT
PUTC
FETCH ch
90
PRINT
''
ABCDEFGHIJKLMNOPQRSTUVWXYZ
do{
my $ch = 0;
$ch = "65";
while(do{do{do{local $@ = $ch; print chr $@
; $@}}
<
do{"90"}}){do{$ch = do{$ch}
+
do{"1"}}};print "", "\n"
};1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
----------------------------------------------------------------------
# converted from
# https://rosettacode.org/wiki/Compiler/Sample_programs#Fibonacci_sequ
+ence
# fibonacci of 44 is 701408733
#
n = 44;
i = 1;
a = 0;
b = 1;
{
w = a + b;
a = b;
b = w;
i = i + 1;
} while (i < n);
print w
STMT
STORE n
44
STORE i
1
STORE a
0
STORE b
1
WHILE
STMT
STORE w
ADD
FETCH a
FETCH b
STORE a
FETCH b
STORE b
FETCH w
STORE i
ADD
FETCH i
1
LT
FETCH i
FETCH n
PRINT
FETCH w
701408733
do{
my $a = my $b = my $i = my $n = my $w = 0;
$n = "44";$i = "1";$a = "0";$b = "1";
while(do{do{$i}
<
do{$n}}){do{$w = do{$a}
+
do{$b};$a = $b;$b = $w;$i = do{$i}
+
do{"1"}}};print $w, "\n"
};1
701408733
----------------------------------------------------------------------
# converted from
# https://rosettacode.org/wiki/Compiler/Sample_programs#Greatest_commo
+n_divisor
# Compute the gcd of 1071, 1029: 21
#
a = 1071;
b = 1029;
#
{
new_a = b;
b = a % b;
a = new_a;
} while b;
print a;
STMT
STORE a
1071
STORE b
1029
WHILE
STMT
STORE new_a
FETCH b
STORE b
MOD
FETCH a
FETCH b
STORE a
FETCH new_a
FETCH b
PRINT
FETCH a
21
do{
my $a = my $b = my $new_a = 0;
$a = "1071";$b = "1029";
while(do{$b}){do{$new_a = $b;$b = do{$a}
%
do{$b};$a = $new_a}};print $a, "\n"
};1
21
----------------------------------------------------------------------
# This is an ascii Mandelbrot generator converted from
# https://rosettacode.org/wiki/Compiler/Sample_programs#Ascii_Mandlebr
+ot
#
left_edge = -420;
right_edge = 300;
top_edge = 300;
bottom_edge = -300;
x_step = 7;
y_step = 15;
#
max_iter = 200;
#
y0 = top_edge;
{
x0 = left_edge;
{
x = y = i = 0;
the_char = ' ';
{
x_x = x * x / 200;
y_y = y * y / 200;
(x_x + y_y > 800 ) and {
the_char = i > 9 ? '@' : i;
i = max_iter;
};
y = x * y / 100 + y0;
x = x_x - y_y + x0;
i = i + 1;
} while (i < max_iter) ;
put(the_char);
x0 = x0 + x_step;
} while (x0 < right_edge) ;
print '';
y0 = y0 - y_step;
} while y0 > bottom_edge ;
STMT
STORE left_edge
-420
STORE right_edge
300
STORE top_edge
300
STORE bottom_edge
-300
STORE x_step
7
STORE y_step
15
STORE max_iter
200
STORE y0
FETCH top_edge
WHILE
STMT
STORE x0
FETCH left_edge
WHILE
STMT
STORE x
STORE y
STORE i
0
STORE the_char
' '
WHILE
STMT
STORE x_x
DIVIDE
MULTIPLY
FETCH x
FETCH x
200
STORE y_y
DIVIDE
MULTIPLY
FETCH y
FETCH y
200
AND
GT
ADD
FETCH x_x
FETCH y_y
800
STMT
STORE the_char
COND
GT
FETCH i
9
@
FETCH i
STORE i
FETCH max_iter
STORE y
ADD
DIVIDE
MULTIPLY
FETCH x
FETCH y
100
FETCH y0
STORE x
ADD
SUBTRACT
FETCH x_x
FETCH y_y
FETCH x0
STORE i
ADD
FETCH i
1
LT
FETCH i
FETCH max_iter
PUT
FETCH the_char
STORE x0
ADD
FETCH x0
FETCH x_step
LT
FETCH x0
FETCH right_edge
PRINT
''
STORE y0
SUBTRACT
FETCH y0
FETCH y_step
GT
FETCH y0
FETCH bottom_edge
1111111111111111111111122222222222222222222222222222222222222222222222
+222222222222222222222222222211111
1111111111111111111122222222222222222222222222222222222222222222222222
+222222222222222222222222222222211
1111111111111111112222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222
+222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333322222
+222222222222222222222222222222222
1111111111111222222222233333333333333333333333334444457655544443333332
+222222222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333
+333222222222222222222222222222222
11111111111222222333333333333333333333334444444445555678@@@@7654444443
+333332222222222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98655544444
+433333332222222222222222222222222
1111111122222333333333333333333333344444444445556668@@@ @@@76555544
+444333333322222222222222222222222
1111111122233333333333333333333344444444445566667778@@ @987666555
+544433333333222222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@87777
+@95443333333322222222222222222222
1111112233333333333333333334444455555556678@@ @@@ @@@@@@
+@@8544333333333222222222222222222
1111122333333333333333334445555555555666789@@@
+@86554433333333322222222222222222
1111123333333333333444466666555556666778@@@@ @
+@87655443333333332222222222222222
111123333333344444455568@887789@87777889@@
+@@@@65443333333332222222222222222
1111333344444444455556679@@@@@@@@@@@99@@@
+ @@765444333333333222222222222222
1111334444444455555567779@@ @@@@
+ @855444333333333222222222222222
11114444444455555668@99@@@ @
+ @@655444433333333322222222222222
11134555556666677789@@@@@
+@86655444433333333322222222222222
111 @@
+876555444433333333322222222222222
11134555556666677789@@@@@
+@86655444433333333322222222222222
11114444444455555668@99@@@ @
+ @@655444433333333322222222222222
1111334444444455555567779@@ @@@@
+ @855444333333333222222222222222
1111333344444444455556679@@@@@@@@@@@99@@@
+ @@765444333333333222222222222222
111123333333344444455568@887789@87777889@@
+@@@@65443333333332222222222222222
1111123333333333333444466666555556666778@@@@ @
+@87655443333333332222222222222222
1111122333333333333333334445555555555666789@@@
+@86554433333333322222222222222222
1111112233333333333333333334444455555556678@@ @@@ @@@@@@
+@@8544333333333222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@87777
+@95443333333322222222222222222222
1111111122233333333333333333333344444444445566667778@@ @987666555
+544433333333222222222222222222222
1111111122222333333333333333333333344444444445556668@@@ @@@76555544
+444333333322222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98655544444
+433333332222222222222222222222222
11111111111222222333333333333333333333334444444445555678@@@@7654444443
+333332222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333
+333222222222222222222222222222222
1111111111111222222222233333333333333333333333334444457655544443333332
+222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333322222
+222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222
+222222222222222222222222222222222
1111111111111111112222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222
1111111111111111111122222222222222222222222222222222222222222222222222
+222222222222222222222222222222211
do{
my $bottom_edge = my $i = my $left_edge = my $max_iter = my $right_edg
+e = my $the_char = my $top_edge = my $x = my $x0 = my $x_step = my $x
+_x = my $y = my $y0 = my $y_step = my $y_y = 0;
$left_edge = "-420";$right_edge = "300";$top_edge = "300";$bottom_edge
+ = "-300";$x_step = "7";$y_step = "15";$max_iter = "200";$y0 = $top_e
+dge;
while(do{do{$y0}
>
do{$bottom_edge}}){do{$x0 = $left_edge;
while(do{do{$x0}
<
do{$right_edge}}){do{$x = $y = $i = "0";$the_char = " ";
while(do{do{$i}
<
do{$max_iter}}){do{$x_x = do{do{$x}
*
do{$x}}
/
do{"200"};$y_y = do{do{$y}
*
do{$y}}
/
do{"200"};do{do{do{$x_x}
+
do{$y_y}}
>
do{"800"}}
and
do{$the_char = do{do{$i}
>
do{"9"}}
?do{"@"}:do{$i};$i = $max_iter};$y = do{do{do{$x}
*
do{$y}}
/
do{"100"}}
+
do{$y0};$x = do{do{$x_x}
-
do{$y_y}}
+
do{$x0};$i = do{$i}
+
do{"1"}}};print $the_char
;$x0 = do{$x0}
+
do{$x_step}}};print "", "\n"
;$y0 = do{$y0}
-
do{$y_step}}}};1
1111111111111111111111122222222222222222222222222222222222222222222222
+222222222222222222222222222211111
1111111111111111111122222222222222222222222222222222222222222222222222
+222222222222222222222222222222211
1111111111111111112222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222
+222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333322222
+222222222222222222222222222222222
1111111111111222222222233333333333333333333333334444457655544443333332
+222222222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333
+333222222222222222222222222222222
11111111111222222333333333333333333333334444444445555678@@@@7654444443
+333332222222222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98655544444
+433333332222222222222222222222222
1111111122222333333333333333333333344444444445556668@@@ @@@76555544
+444333333322222222222222222222222
1111111122233333333333333333333344444444445566667778@@ @987666555
+544433333333222222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@87777
+@95443333333322222222222222222222
1111112233333333333333333334444455555556678@@ @@@ @@@@@@
+@@8544333333333222222222222222222
1111122333333333333333334445555555555666789@@@
+@86554433333333322222222222222222
1111123333333333333444466666555556666778@@@@ @
+@87655443333333332222222222222222
111123333333344444455568@887789@87777889@@
+@@@@65443333333332222222222222222
1111333344444444455556679@@@@@@@@@@@99@@@
+ @@765444333333333222222222222222
1111334444444455555567779@@ @@@@
+ @855444333333333222222222222222
11114444444455555668@99@@@ @
+ @@655444433333333322222222222222
11134555556666677789@@@@@
+@86655444433333333322222222222222
111 @@
+876555444433333333322222222222222
11134555556666677789@@@@@
+@86655444433333333322222222222222
11114444444455555668@99@@@ @
+ @@655444433333333322222222222222
1111334444444455555567779@@ @@@@
+ @855444333333333222222222222222
1111333344444444455556679@@@@@@@@@@@99@@@
+ @@765444333333333222222222222222
111123333333344444455568@887789@87777889@@
+@@@@65443333333332222222222222222
1111123333333333333444466666555556666778@@@@ @
+@87655443333333332222222222222222
1111122333333333333333334445555555555666789@@@
+@86554433333333322222222222222222
1111112233333333333333333334444455555556678@@ @@@ @@@@@@
+@@8544333333333222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@87777
+@95443333333322222222222222222222
1111111122233333333333333333333344444444445566667778@@ @987666555
+544433333333222222222222222222222
1111111122222333333333333333333333344444444445556668@@@ @@@76555544
+444333333322222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98655544444
+433333332222222222222222222222222
11111111111222222333333333333333333333334444444445555678@@@@7654444443
+333332222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333
+333222222222222222222222222222222
1111111111111222222222233333333333333333333333334444457655544443333332
+222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333322222
+222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222
+222222222222222222222222222222222
1111111111111111112222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222
1111111111111111111122222222222222222222222222222222222222222222222222
+222222222222222222222222222222211
----------------------------------------------------------------------
I hope this helps and give you some idea of what's involved in parsing a language.