16

I saw that the Neo4j API uses ASCII Art very cleverly with its API:

http://jaxenter.com/getting-started-with-neo4j-the-java-graph-database-47955.html

I want to try something similar, but with ASCI Art to HTML. How can ASCII art be parsed, so for example, given an ASCII Art input something like:

--------------------------------
I                              I
I   -------          -------   I
I   I     I          I     I   I
I   I  A  I          I  B  I   I
I   I     I          I     I   I
I   -------          -------   I
I                              I
I                              I
--------------------------------

: could result in HTML output something like:

<div>
    <div style='display:inline;'>
             A
    </div>
    <div style='display:inline;'>
             B
    </div>
</div>

Update

The question was closed citing that I need to "demonstrate a minimal understanding of the problem being solved.". I do have an understanding of the problem to be solved. The problem is that I want to solve is to make templated HTML easier to understand in source code for the following web framework:

https://github.com/zubairq/coils

: although the solution could be applied to any web framework. I have since seen someone attempt to make an initial version in C++ here:

https://github.com/h3nr1x/asciidivs2html/blob/master/asciidivs2html.cpp

: very impressive! If you can get it to work in Java or Clojure then if we can get the question reopened I will nominate a bounty so you can get more points for the solution :)

I ran the Java solution provided by @meewok and here is the result:

$ java AsciiToDIVs.RunConverter
Created a box(ID=0,X=0,Y=0,width=33,height=10)
Created a box(ID=1,X=2,Y=4,width=8,height=5,parent=0)
Created a char(Char=A,X=4,Y=7,parent=1)
Created a box(ID=2,X=2,Y=21,width=8,height=5,parent=0)
Created a char(Char=B,X=4,Y=24,parent=2)
<div><div><div>A</div></div><div><div>B</div></div></div>
Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
yazz.com
  • 57,320
  • 66
  • 234
  • 385
  • 3
    Why the closing votes? I want to have some Ascii Art in a program which can return HTML – yazz.com Sep 05 '13 at 13:30
  • 6
    This actually sounds interesting – 0x_Anakin Sep 05 '13 at 13:34
  • 2
    You would have to write a parser. Take a look at http://pegjs.majda.cz/ – jessegavin Sep 05 '13 at 13:36
  • 7
    Yes, sounds interesting, but if a newbie asks for code or library recommendation, the Q is closed on sight, no? – brasofilo Sep 05 '13 at 13:37
  • 1
    Good point, I rephrased the question – yazz.com Sep 05 '13 at 14:30
  • 2
    The question got closed anyway. Is it off topic?? If so I can always post it to another stackexchange site. If so which one? – yazz.com Sep 05 '13 at 17:11
  • 2
    You are not going to find a simple solution. You could write a parser which identifies the corners, and uses their coordinates to build up a structure of nested boxes. Then you emit the box structure as divs. (But inputting ascii art seems like a terribly inefficient way to describe anything) – AShelly Sep 05 '13 at 17:40
  • Do you mean inefficient in runtime performance or inefficient in development time? – yazz.com Sep 05 '13 at 19:55
  • 8
    You don't need to use parsing, use a floodfill to landmark the div's areas, extract the div coordinates, check the borders to get the enclosing parent div and then build a tree with this information, recurse the tree to print the html tags. Have reported sick for work today =(, so I toke my rest time to code a program for this, check out https://github.com/h3nr1x/asciidivs2html – higuaro Sep 05 '13 at 23:27
  • Well, if you can get a Java version working too I will make sure I give you a decent bounty of a couple of hundred points (assumming we can get the question reopened) – yazz.com Sep 06 '13 at 06:00
  • Great, the question has been reopened. It will only let me make the question eligible for a bounty tomorrow which is why I haven't added the bounty yet – yazz.com Sep 06 '13 at 06:33
  • 3
    The "minimal understanding" close reason is probably because you haven't demonstrated any actual attempt to solve this yourself. Are you asking someone to write the whole thing for you? – Martin Smith Sep 06 '13 at 09:30
  • 1
    I have tried several times and made a total mess of it, so I am trying to see if I am attempting something impossible, which is what I was starting to think until I saw one guy implement it in C++. – yazz.com Sep 06 '13 at 09:39
  • 2
    @Zubair: You've seen an implementation, why can't you port it to java yourself? – Eric Sep 07 '13 at 15:54
  • What decides here that `A` comes before `B`? – Eric Sep 07 '13 at 15:57
  • https://github.com/mdr/ascii-graphs/blob/master/README.md – internals-in Sep 07 '13 at 16:50
  • 1
    Can we get some more examples? For instance, how would this render? https://gist.github.com/code-curve/e26449cab12f3cd067d1/raw/21ed0538bb4c2eca51e81c53eaa8d0e8ad0a275b/gistfile1.txt – Dan Prince Sep 07 '13 at 16:59
  • @7-isnotbad - I am not trying to get ascii art as the output, I want ascii art as the input, and html as the output – yazz.com Sep 07 '13 at 17:37
  • @Dan See https://github.com/h3nr1x/asciidivs2html/blob/master/asciidivs2html.cpp for someone who has tried this in C++ – yazz.com Sep 07 '13 at 17:38
  • @eric: I used to be a C++ developer but my C++ is pretty rusty. I started the C++ to Java port but kept getting held back as I had to keep refreshing my C++ knowledge so I admittedly made a total mess of it – yazz.com Sep 07 '13 at 17:43
  • @eric - good point, I am guessing my A and B html div elements should be inline blocks.. is that what you mean? – yazz.com Sep 07 '13 at 17:44
  • 1
    I'm asking what rule you've used to produce `
    A
    B
    ` instead of `
    B
    A
    `
    – Eric Sep 07 '13 at 18:36
  • Question is way too broad, may be interesting but not a good fit for SO. Do you really expect an answer that can fit within a post? -1 – Ruan Mendes Sep 07 '13 at 18:40
  • I would never use a framework with a template engine like this – Ry- Sep 07 '13 at 21:55
  • @minitech I am building a framework with a template engine that I would like to use. It is not aimed at hackers or hard core developers – yazz.com Sep 08 '13 at 10:05
  • which part of the problem is opinion based? – yazz.com Sep 08 '13 at 10:07
  • @eric the ordering of A and B is based on the ascii art – yazz.com Sep 08 '13 at 10:08
  • can we reopen this, I want to have a bounty on this? – yazz.com Sep 08 '13 at 10:09
  • 2
    You really need a spec of some kind. One example isn't a spec. If you had a bounty, exactly what problem should be solved? – Paul Sep 08 '13 at 10:49
  • @Paul Ok, that is a fair point... I will have to think about this, whether I should make a detailed spec to cover all the possible inputs – yazz.com Sep 08 '13 at 11:14
  • 1
    Also, ascii art is art. It can be colorized and such. Does this imply that CSS styles should be set? Should rectangles and text have nice contrasting colors? etc... – Paul Sep 08 '13 at 11:15
  • 1
    You may be familiar with [Nethack](http://en.wikipedia.org/wiki/NetHack), a dungeon quest for the Amulet of Yendor. This late 1980s software was heavily dependent on ascii art and coded in C with support for dumb terminals over termcap and ncurses and eventually X. Well, google "nethack javascript" now lists several Javascript implementations. Maybe there is something in there you can use. – Paul Sep 08 '13 at 11:21
  • @Paul Wow, Nethack is pretty cool. I will look more into that – yazz.com Sep 08 '13 at 11:30
  • 1
    @Zubair Since the question seems to be too open ended I'd try the following: rewrite your example to be a list of requirements. List 1 or 2 variances of the solution(s) you have tried and why they are not working (which section of code is problematic). Since all answers have some opinion (everyone has their experience) you will probably get multple solutions to the specific problem section as well as suggestions. If you have muliple problems I suspect you could split them into muliple wuestions as long as your demonstrating whar solutions your trying/using. – Menelaos Sep 08 '13 at 12:25
  • 1
    In my experience even when you outline a specific problrm you have the opinion based answers that say stuff like : "you should use this and that framework/methodology/approach" for this and that reason which are not always based on 100% fact. – Menelaos Sep 08 '13 at 12:31
  • @meewok Yes, I see that now, maybe it is a bit of an open ended question. However I really appreciate the solution you made. Right now I just want to reopen the question so I can award the 500 points to someone when the bounty ends – yazz.com Sep 08 '13 at 12:36
  • 2
    Not that I'm complaining but I wonder how this was opened again... and wonder if it will be put on hold/closed again :S . – Menelaos Sep 15 '13 at 20:37
  • 1
    I hope it stays open this time – yazz.com Sep 15 '13 at 21:30
  • Converting ASCII art to HTML is going to be really laborious. Especially if you don't have a very well defined set of ASCII art you are going to parse/convert. Where does the ASCII art come from? Are you generating it from another program or writing it yourself? If it is at all possible, I think you should try and get your input as something other than ASCII art. Maybe XML or YAML? It would be significantly easier to port that to HTML. – John Mark Sep 18 '13 at 03:28
  • It will be hand coded – yazz.com Sep 18 '13 at 08:08
  • 1
    @Zubair I made a patch that fixes an error in the `
    ` outputs.
    – Menelaos Sep 19 '13 at 12:09
  • 1
    @Zubair I thought this question was banned and totally forgot about it! Well, I got some free time so I decided to make the porting to Java from my previous C++ flood-fill attempt, check the implementation at [github](https://github.com/h3nr1x/asciidivs2html/tree/master/ascii2div-java) – higuaro Sep 26 '13 at 05:34
  • Yes, it was banned, but then I request it be reopened so I could award the 500 points to someone. I already rewarded it unfortunately, so sorry about that :( but I will check out your implementation – yazz.com Sep 26 '13 at 07:25
  • @Zubair , in relation to the question being put on hold again, I think it will be reopened if you include your very first initial attempted solution in code ... – Menelaos Sep 28 '13 at 17:27
  • @meewok It is fine. As long as they gave you the 500 points then I am happy :) – yazz.com Oct 01 '13 at 12:14

3 Answers3

11

Methodology

A solution to implement is the following:

  • create an in memory 2D array (array of arrays) which is similar to a chessboard.

Then i will create an algorith that when it detects "-" characters, i initialize acall to a method to detect the remaining corners ( top right, bottom left, bottom right) following the characters and where they end.

Example ( quick pseudocode ):

while(selectedCell==I) selectedCell=selectedCell.goDown();

Using such a strategy you can map out your boxes and which boxes are contained within which.

Remaining would be to print this info as html..

Quick and Dirty Implementation

Since I was in the mood I spent an hour+ to quickly cook up a toy implementation. The below is non-optimized in respect to that I do not make use of Iterators to go over Cells, and would need refactoring to become a serious framework.

Cell.java


package AsciiToDIVs;

public class Cell {
    public char Character;
    public CellGrid parentGrid;
    private int rowIndex;
    private int colIndex;

    public Cell(char Character, CellGrid parent, int rowIndex, int colIndex)
    {
        this.Character = Character;
        this.parentGrid = parent;
        this.rowIndex = rowIndex;
        this.colIndex = colIndex;
    }

    public int getRowIndex() {
        return rowIndex;
    }

    public int getColIndex() {
        return colIndex;
    }
}

CellGrid.java


package AsciiToDIVs;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;

public class CellGrid {

    private ArrayList<ArrayList<Cell>> CellGridData;

    public CellGrid(String asciiFile) throws IOException {
        readDataFile(asciiFile);
    }

    public ArrayList<FoundObject> findBoxes(FoundBoxObject parent)
    {

        int startRowIndex = 0, startColIndex = 0, 
                parentRowLimit = Integer.MAX_VALUE, 
                parentColLimit = Integer.MAX_VALUE,
                startingColIndex = 0;
        if(parent != null)
        {
            startRowIndex = parent.getRowIndex()+1;
            startColIndex = startingColIndex =  parent.getColIndex()+1;
            parentRowLimit = parent.getRowIndex() + parent.getHeight();
            parentColLimit = parent.getColIndex() + parent.getWidth();
        }

        ArrayList<FoundObject> results = new ArrayList<FoundObject>();

        Cell currentCell;

        if(startRowIndex>=CellGridData.size())
        return null;        

        for(; startRowIndex<CellGridData.size() && startRowIndex<parentRowLimit; startRowIndex++ )
        {
            startColIndex = startingColIndex;

            for(; startColIndex< CellGridData.get(startRowIndex).size() && startColIndex<parentColLimit; startColIndex++)
            {           
                FoundBoxObject withinBox = checkWithinFoundBoxObject(results, startRowIndex, startColIndex);

                if(withinBox !=null)
                startColIndex+=withinBox.getWidth();

                currentCell = getCell(startRowIndex, startColIndex);

                if(currentCell!=null)
                {
                    if(currentCell.Character == '-') // Found a TOP-CORNER
                    {
                        int boxHeight =  getConsecutiveIs(startRowIndex+1, startColIndex) + 1;
                        if(boxHeight>1)
                        {
                            int boxWidth = getConsecutiveDashes(startRowIndex, startColIndex);

                            FoundBoxObject box = new FoundBoxObject(startRowIndex, startColIndex, boxWidth, boxHeight, parent);
                            results.add(box);
                            findBoxes(box);

                            startColIndex+=boxWidth;                            
                        }                   
                    }

                    //This is a character
                    else if(currentCell.Character != '-' && currentCell.Character != 'I' && currentCell.Character != ' ' 
                            && currentCell.Character != '\n' && currentCell.Character != '\n' && currentCell.Character != '\t')
                    {
                        FoundCharObject Char = new FoundCharObject(startRowIndex, startColIndex, parent,  currentCell.Character);
                        results.add(Char);
                    }
                }
            }       
        }

        if(parent!=null)
        parent.containedObjects = results;

        return results;     
    }

    public static String printDIV(ArrayList<FoundObject> objects)
    {
        String result = "";
        Iterator<FoundObject> it = objects.iterator();
        FoundObject fo;

        while(it.hasNext())
        {
            result+="<div>";

            fo = it.next();

            if(fo instanceof FoundCharObject)
            {
                FoundCharObject fc = (FoundCharObject)fo;
                result+=fc.getChar();
            }

            if(fo instanceof FoundBoxObject)
            {
                FoundBoxObject fb = (FoundBoxObject)fo;
                result+=printDIV(fb.containedObjects);
            }

            result+="</div>";
        }

        return result;
    }

    private FoundBoxObject checkWithinFoundBoxObject(ArrayList<FoundObject> results, int rowIndex, int colIndex)
    {
        Iterator<FoundObject> it = results.iterator();
        FoundObject f;
        FoundBoxObject fbox = null;
        while(it.hasNext())
        {
            f = it.next();

            if(f instanceof FoundBoxObject)
            {
                fbox = (FoundBoxObject) f;

                if(rowIndex >= fbox.getRowIndex() && rowIndex <= fbox.getRowIndex() + fbox.getHeight())
                {
                    if(colIndex >= fbox.getColIndex() && colIndex <= fbox.getColIndex() + fbox.getWidth())
                    {
                        return fbox;
                    }
                }
            }
        }

        return null;
    }

    private int getConsecutiveDashes(int startRowIndex, int startColIndex)
    {
        int counter = 0;
        Cell cell = getCell(startRowIndex, startColIndex);

        while( cell!=null && cell.Character =='-')
        {
            counter++;
            cell = getCell(startRowIndex, startColIndex++);
        }

        return counter;

    }

    private int getConsecutiveIs(int startRowIndex, int startColIndex)
    {
        int counter = 0;
        Cell cell = getCell(startRowIndex, startColIndex);

        while( cell!=null && cell.Character =='I')
        {
            counter++;
            cell = getCell(startRowIndex++, startColIndex);
        }

        return counter;
    }

    public Cell getCell(int rowIndex, int columnIndex)
    {
        ArrayList<Cell> row;


        if(rowIndex<CellGridData.size())
        row = CellGridData.get(rowIndex);
        else return null;

        Cell cell = null;

        if(row!=null){
            if(columnIndex<row.size())
            cell = row.get(columnIndex);
        }

        return cell;
    }


    public Iterator<ArrayList<Cell>> getRowGridIterator(int StartRow) {
        Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();

        int CurrentRow = 0;

        while (itRow.hasNext()) {
            // Itrate to Row
            if (CurrentRow++ < StartRow)
                itRow.next();

        }
        return itRow;
    }

    private void readDataFile(String asciiFile) throws IOException {
        CellGridData = new ArrayList<ArrayList<Cell>>();
        ArrayList<Cell> row;

        FileInputStream fstream = new FileInputStream(asciiFile);
        BufferedReader br = new BufferedReader(new InputStreamReader(fstream));

        String strLine;

        // Read File Line By Line
        int rowIndex = 0;
        while ((strLine = br.readLine()) != null) {
            CellGridData.add(row = new ArrayList<Cell>());
            // System.out.println (strLine);
            for (int colIndex = 0; colIndex < strLine.length(); colIndex++) {
                row.add(new Cell(strLine.charAt(colIndex), this, rowIndex,colIndex));
                // System.out.print(strLine.charAt(i));
            }
            rowIndex++;
            // System.out.println();
        }

        // Close the input stream
        br.close();
    }

    public String printGrid() {
        String result = "";

        Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();
        Iterator<Cell> itCol;
        Cell cell;

        while (itRow.hasNext()) {
            itCol = itRow.next().iterator();

            while (itCol.hasNext()) {
                cell = itCol.next();
                result += cell.Character;
            }
            result += "\n";
        }

        return result;
    }

}

FoundBoxObject.java


package AsciiToDIVs;

import java.util.ArrayList;

public class FoundBoxObject extends FoundObject {
    public ArrayList<FoundObject> containedObjects = new ArrayList<FoundObject>();
    public static int boxCounter = 0;

    public final int ID = boxCounter++;

    public FoundBoxObject(int rowIndex, int colIndex, int width, int height, FoundBoxObject parent) {
        super(rowIndex, colIndex, width, height);

        if(parent!=null)
        System.out.println("Created a box(" +
                "ID="+ID+
                ",X="+rowIndex+
                ",Y="+colIndex+
                ",width="+width+
                ",height="+height+
                ",parent="+parent.ID+")");
        else
            System.out.println("Created a box(" +
                    "ID="+ID+
                    ",X="+rowIndex+
                    ",Y="+colIndex+
                    ",width="+width+
                    ",height="+height+
                    ")");   
    }

}

FoundCharObject.java


package AsciiToDIVs;

public class FoundCharObject extends FoundObject {
private Character Char;

public FoundCharObject(int rowIndex, int colIndex,FoundBoxObject parent, char Char) {
    super(rowIndex, colIndex, 1, 1);

    if(parent!=null)
    System.out.println("Created a char(" +
            "Char="+Char+
            ",X="+rowIndex+
            ",Y="+colIndex+
            ",parent="+parent.ID+")");
    else
        System.out.println("Created a char(" +
                ",X="+rowIndex+
                ",Y="+colIndex+")");

    this.Char = Char;
}

public Character getChar() {
    return Char;
}
}

FoundObject.java


package AsciiToDIVs;

public class FoundObject {

    private int rowIndex;
    private int colIndex;
    private int width = 0;
    private int height = 0;

    public FoundObject(int rowIndex, int colIndex, int width, int height )
    {
        this.rowIndex = rowIndex;
        this.colIndex = colIndex;
        this.width = width;
        this.height = height;
    }

    public int getRowIndex() {
        return rowIndex;
    }

    public int getColIndex() {
        return colIndex;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
}

Main Method


public static void main(String args[])
    {
        try {
            CellGrid grid = new CellGrid("ascii.txt");
            System.out.println(CellGrid.printDIV(grid.findBoxes(null)));
            //System.out.println(grid.printGrid());
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }   

Update

The 'printDIV' should be like this (more '' were being printed than needed).

public static String printDIV(ArrayList<FoundObject> objects)
    {
        String result = "";
        Iterator<FoundObject> it = objects.iterator();
        FoundObject fo;

        while(it.hasNext())
        {
            fo = it.next();

            if(fo instanceof FoundCharObject)
            {
                FoundCharObject fc = (FoundCharObject)fo;
                result+=fc.getChar();
            }

            if(fo instanceof FoundBoxObject)
            {
                result+="<div>";
                FoundBoxObject fb = (FoundBoxObject)fo;
                result+=printDIV(fb.containedObjects);
                result+="</div>";
            }           
        }

        return result;
    }
Menelaos
  • 23,508
  • 18
  • 90
  • 155
  • This seems to be in the right direction – yazz.com Sep 07 '13 at 17:38
  • This seems to work for the case I gave as an example .. see the update I have put on the question :) – yazz.com Sep 08 '13 at 11:29
  • 1
    I'd suggest you convert from .get to using iterators to go through the arraylist elements. Also test for different case.... – Menelaos Sep 08 '13 at 12:49
  • This approach works if you want to recognize some boxes, some times. In practice, you want to recognize a set of entities that are tied together in valid ways. In general, that is called "parsing" (and string parsing has a huge literature behind it). This approach doesn't collect entities and verity relationships, so I doubt it will be successful in complex cases. – Ira Baxter Sep 16 '13 at 01:27
  • 1
    This approach is a toy example, and can recognize all boxes that follow the specific format ( following specific requirements). Obviously special cases (e.g. joined boxes) would require modifications (but so do rules in other systems). This can be extended to handle more complex shapes for simple requirements. More complex requirements will require more code, or a framework based a complex algorithm. It does however adequately cover the requirements of the OP as well as can be modified to recognize other shapes such as (triangles, connections, etc). – Menelaos Sep 16 '13 at 08:24
5

Here's a fairly simple solution in JavaScript, tested via Node. Of course, you'll need to adjust the input and output methods.

var s = "\n\
--------------------------------\n\
I                              I\n\
I   -------          -------   I\n\
I   I     I          I     I   I\n\
I   I  A  I          I  B  I   I\n\
I   I     I          I     I   I\n\
I   -------          -------   I\n\
I                              I\n\
I                              I\n\
--------------------------------\n\
";

var lines = s.split('\n');

var outer_box_top_re = /--+/g;

var i;
for (i=0; i<lines.length; i++) {
    while ((res = outer_box_top_re.exec(lines[i])) != null) {
        L = res.index
        R = outer_box_top_re.lastIndex
        process_box(i, L, R)
    }
}

function process_box(T, L, R) {
    console.log('<div top="' + T + '" left="' + L + '" right="' + R + '">')
    blank_out(T, L, R)

    var i = T;
    while (1) {
        i += 1;
        if (i >= lines.length) {
            console.log('Fell off bottom of ascii-art without finding bottom of box');
            process.exit(1);
        }

        var line = lines[i];

        if (line[L] == 'I' && line[R-1] == 'I') {
            // interior

            // Look for (the tops of) sub-boxes.
            // (between L+1 and R-2)
            var inner_box_top_re = /--+/g;
            // Inner and outer need to be separate so that
            // inner doesn't stomp on outer's lastIndex.
            inner_box_top_re.lastIndex = L+1;
            while ((res = inner_box_top_re.exec(lines[i])) != null) {
                sub_L = res.index;
                sub_R = inner_box_top_re.lastIndex;
                if (sub_L > R-1) { break; }
                process_box(i, sub_L, sub_R);
            }

            // Look for any other content (i.e., a box label)
            content = lines[i].substring(L+1, R-1);
            if (content.search(/[^ ]/) != -1) {
                console.log(content);
            }

            blank_out(i, L, R);
        }
        else if (line.substring(L,R).match(/^-+$/)) {
            // bottom
            blank_out(i, L, R);
            break;
        }
        else {
            console.log("line " + i + " doesn't contain a valid continuation of the box");
            process.exit(1)
        }
    }

    console.log('</div>')
}

function blank_out(i, L, R) {
    lines[i] = (
          lines[i].substring(0,L)
        + lines[i].substring(L,R).replace(/./g, ' ')
        + lines[i].substring(R)
    );
}
Michael Dyck
  • 2,153
  • 1
  • 14
  • 18
1

What you want is the idea of 2-dimensional parsing, which detects 2D entities and verifies they have legitimate relationships.

See http://mmi.tudelft.nl/pub/siska/TSD%202DVisLangGrammar.pdf

What will be difficult is defining the sets of possible "ASCII Art" constraints. Do only want to to recognize letters? Made only of the same-letter characters? "cursive" letters? boxes? (Your example has boxes whose sides aren't made of the same ASCII character). Boxes with arbitrary thick walls? Nested boxes? Diagrams with (thin/fat) arrows? Kilroy-was-here-nose-over-the-wall? Pictures of Mona Lisa in which character pixels provide density relations? What exactly do you mean by "ASCII art"?

The real problem is defining the range of things you intend to recognize. If you limit that range, your odds of success go way up (see the referenced paper).

The problem here has little to to do specifically with Java or Javascript. This is far more related to algorithms. Pick a limited class of art, choose the right algorithms, and then what you have is a coding problem which should be relatively easy to solve. No limits, no algorithms --> no amount of Javascript will save you.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • 1
    The paper you cite does not go into details about how such a parser would work. Other literature is most likely more relevant. This paper deals with a emergency language based on the relationships/arrangements of icons. Additionally, the requirements of OP did not make reference to pictures so "Pictures of Mona Lisa in which character pixels provide density relations?" is a bit of an exaggeration. The OP does provide examples as to what he is looking for, though a spec(design document) is missing as to exactly what set of features (entities for recognition/relationships) should be supported. – Menelaos Sep 16 '13 at 08:23
  • 2
    OP said, "ASCII Art". That's not a well defined term. Showing *1* example hardly constitutes a definition of a category. You can't define the problem of parsing C++ by saying "I want parse some strings that look like programming code, e.g., foo.bar(x,y)". Yes, we're in agreement he didn't define a spec. That's what I said, and he can't make any serious progress until that happens. – Ira Baxter Sep 16 '13 at 10:34
  • 1
    Yep, I guess I need to specify the problem better, I agree – yazz.com Sep 18 '13 at 08:09