Neat Paraskavedekatriaphobia's Meaning
Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »

tif-parser

0.3.3 • Public • Published

tifParser: Tab Indented Format Parser

This is a simple parser for Tab Indented Format (TIF, the spec of this format is currently in progress).

It transforms a text file into nested objects.

While it is too general to produce anything by itself, it is actually the first stage of more complicated and specific parsers.

  • License: MIT
  • Current status: alpha / unstable
  • Platform: Node.js only

Full BDD spec generated by Mocha:

TOC

Single line

when empty, should return a root node without child.

expect( tifParser.parse( '' ) ).to.eql( {
    depth: 0,
    children: []
} ) ;

with a single word, should return a root node with one child, no comment and the word as content.

expect( tifParser.parse( 'Hello' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'Hello',
        comment: undefined,
        children: []
    } ]
} ) ;

with a many words, should return a root node with one child, no comment and all words as content.

expect( tifParser.parse( 'Hello world! How are you?' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'Hello world! How are you?',
        comment: undefined,
        children: []
    } ]
} ) ;

with a comment, should return a root node with one child, no content and all words as comment.

expect( tifParser.parse( '# This is a comment' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: undefined,
        comment: 'This is a comment',
        children: []
    } ]
} ) ;

with content and comment, should return a root node with one child, having content and comment.

expect( tifParser.parse( 'Hello world! # This is a comment' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'Hello world!',
        comment: 'This is a comment',
        children: []
    } ]
} ) ;

should trim whitespace in both content and comment.

expect( tifParser.parse( '  \t Hello world! \t   #   \t  This is a comment \t   ' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'Hello world!',
        comment: 'This is a comment',
        children: []
    } ]
} ) ;

should thow error if the line is indented.

try {
    tifParser.parse( '\tHello world!' ) ;
    expect().fail( 'An exception must have been thrown' ) ;
}
catch ( error ) {
    expect( error.message ).to.match( /Indentation error/ ) ;
}

Custom comment mark

with a comment, should return a root node with one child, no content and all words as comment.

expect( tifParser.parse( '# This is *NOT* a comment' , { commentMark: '//' } ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: '# This is *NOT* a comment',
        comment: undefined,
        children: []
    } ]
} ) ;

with a comment, should return a root node with one child, no content and all words as comment.

expect( tifParser.parse( '// This is a comment' , { commentMark: '//' } ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: undefined,
        comment: 'This is a comment',
        children: []
    } ]
} ) ;

with content and comment, should return a root node with one child, having content and comment.

expect( tifParser.parse( 'Hello world! # This is *NOT* a comment' , { commentMark: '//' } ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'Hello world! # This is *NOT* a comment',
        comment: undefined,
        children: []
    } ]
} ) ;

with content and comment, should return a root node with one child, having content and comment.

expect( tifParser.parse( 'Hello world! // This is a comment' , { commentMark: '//' } ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'Hello world!',
        comment: 'This is a comment',
        children: []
    } ]
} ) ;

Escape sequences

\n should be replaced by a newline.

expect( tifParser.parse( 'This content have\\na newline' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This content have\na newline',
        comment: undefined,
        children: []
    } ]
} ) ;

\r should be replaced by a carriage return.

expect( tifParser.parse( 'This content have\\ra carriage return' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This content have\ra carriage return',
        comment: undefined,
        children: []
    } ]
} ) ;

\t should be replaced by a tab.

expect( tifParser.parse( 'This content have\\ta tab' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This content have\ta tab',
        comment: undefined,
        children: []
    } ]
} ) ;

> should be replaced by a >.

expect( tifParser.parse( 'Parent\n\t\\> Not\n\ta block' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'Parent',
        comment: undefined,
        children: [
            {
                depth: 2,
                line: 2,
                content: '> Not',
                comment: undefined,
                children: []
            } ,
            {
                depth: 2,
                line: 3,
                content: 'a block',
                comment: undefined,
                children: []
            }
        ]
    } ]
} ) ;

\ should be replaced by a single backslash.

expect( tifParser.parse( 'This content have \\\\ a single backslash' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This content have \\ a single backslash',
        comment: undefined,
        children: []
    } ]
} ) ;

# should escape the comment.

expect( tifParser.parse( 'This is not \\# a comment' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This is not # a comment',
        comment: undefined,
        children: []
    } ]
} ) ;

\# should NOT escape the comment.

expect( tifParser.parse( 'This is \\\\# a comment' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This is \\',
        comment: 'a comment',
        children: []
    } ]
} ) ;

\# should escape the comment.

expect( tifParser.parse( 'This is not \\\\\\# a comment' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This is not \\# a comment',
        comment: undefined,
        children: []
    } ]
} ) ;

\\# should NOT escape the comment.

expect( tifParser.parse( 'This is \\\\\\\\# a comment' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'This is \\\\',
        comment: 'a comment',
        children: []
    } ]
} ) ;

should be able to process a mixing of escape sequences.

expect( tifParser.parse( 'mixing\\nmultiple\\rescape\\t\\t\\tsequences\\#\\#\\\\\\t\\n\\t' ) ).to.eql( {
    depth: 0,
    children: [ {
        depth: 1,
        line: 1,
        content: 'mixing\nmultiple\rescape\t\t\tsequences##\\\t\n\t',
        comment: undefined,
        children: []
    } ]
} ) ;

Sample file

1 comparison.

var parsed = tifParser.parse( fs.readFileSync( 'sample1.txt' ).toString() ) ;
 
var expected = {
    depth: 0,
    children: [
        {
            depth: 1,
            line: 2,
            content: undefined,
            comment: "Starting comment",
            children: []
        },
        {
            depth: 1,
            content: "Big One",
            line: 4,
            comment: undefined,
            children: [
                {
                    depth: 2,
                    line: 5,
                    content: "medium1",
                    comment: undefined,
                    children: []
                },
                {
                    depth: 2,
                    line: 6,
                    content: "medium2",
                    comment: undefined,
                    children: [
                        {
                            depth: 3,
                            line: 7,
                            content: undefined,
                            comment: "Comment #1",
                            children: []
                        },
                        {
                            depth: 3,
                            line: 8,
                            content: "little1",
                            comment: undefined,
                            children: []
                        },
                        {
                            depth: 3,
                            line: 9,
                            content: undefined,
                            comment: "Comment #2",
                            children: []
                        },
                        {
                            depth: 3,
                            line: 10,
                            content: "little2",
                            comment: undefined,
                            children: []
                        }
                    ]
                },
                {
                    depth: 2,
                    line: 11,
                    content: "medium3",
                    comment: "with a comment",
                    children: [
                        {
                            depth: 3,
                            line: 12,
                            content: undefined,
                            comment: "Comment #3",
                            children: []
                        }
                    ]
                },
                {
                    depth: 2,
                    line: 13,
                    content: "medium4 with many words",
                    comment: undefined,
                    children: []
                },
                {
                    depth: 2,
                    line: 14,
                    content: "medium5 with many words",
                    comment: "and a comment",
                    children: []
                }
            ]
        },
        {
            depth: 1,
            line: 18,
            content: "Big2",
            comment: undefined,
            children: [
                {
                    depth: 2,
                    line: 22,
                    content: "not a #comment here",
                    comment: undefined,
                    children: []
                }
            ]
        },
        {
            depth: 1,
            line: 20,
            content: undefined,
            comment: "The next node is not a child of this comment",
            children: []
        } ,
        {
            depth: 1,
            line: 25,
            content: "Big3",
            comment: undefined,
            children: [
                {
                    depth: 2,
                    line: 26,
                    content: "This is\na multi-line\nblock of\ntext",
                    comment: undefined,
                    children: []
                } ,
                {
                    depth: 2,
                    line: 31,
                    content: "This is\n  another one\n\tand this # is not a comment\n> This is still the same block of text",
                    comment: undefined,
                    children: []
                } ,
                {
                    depth: 2,
                    line: 36,
                    content: "A regular text-node",
                    comment: undefined,
                    children: []
                } ,
                {
                    depth: 2,
                    line: 38,
                    content: "One line",
                    comment: undefined,
                    children: []
                } ,
            ]
        } ,
        {
            depth: 1,
            line: 39,
            content: "This does not belong to the previous block",
            comment: undefined,
            children: []
        }
    ]
} ;
 
expect( tree.diff( parsed , expected ) ).to.equal( null ) ;
expect( parsed ).to.eql( expected ) ;

install

npm i tif-parser

Downloadsweekly downloads

0

version

0.3.3

license

MIT

repository

githubgithub

last publish

collaborators

  • avatar