Example #1
0
 return base.cons.apply(null, _.map(collected, function(collection) {
     // XXX This is ugly - we know the collection is not empty and
     //     homogenous, hence we can sample it like this. Should be written
     //     differently.
     if ((_.head(collection).type === nodes.TYPE.OPTION)) {
         var available = _.map(collection, _generateNode);
         return parse.rec(function(self) {
             return parse.optional(
                 []
               , parse.choicea(_.map(available, function(parser) {
                     return parse.attempt(base.$(parser))
                         .chain(function(output) {
                             available = _.without(parser);
                             return self.map(function(outputs) {
                                 return [ output ].concat(outputs);
                             });
                         });
               }))
             );
         });
     } else {
         return parse.choicea(_.map(
             collection
           , _.flow(_generateNode, base.$, parse.attempt)
         ));
     }
 })).map(_.flatten);
Example #2
0
 .chain(function(flags) {
     return parse.modifyState(function(userState) {
         return _.assign(userState || {}, {
             flagStart: state.position.index
         });
     }).chain(_.constant(parse.of(flags)));
 });
Example #3
0
 .chain(function(out) {
     return parse.modifyState(function(userState) {
         return _.assign(userState || {}, {
             descriptionStart: state.position.index
         });
     }).chain(_.constant(parse.of(out)));
 });
exports.line_terminator = function(test) {
    test.equal(parse.run(line_terminator_lexer.lineTerminator, '\u000A'), '\u000A');
    test.equal(parse.run(line_terminator_lexer.lineTerminator, '\u000D'), '\u000D');
    test.equal(parse.run(line_terminator_lexer.lineTerminator, '\u2028'), '\u2028');
    test.equal(parse.run(line_terminator_lexer.lineTerminator, '\u2029'), '\u2029');
    
    test.done();
};
Example #5
0
exports.exponent_part = function(test) {
    test.equal(parse.run(number_lexer.exponentPart, 'e012'), 12);
    test.equal(parse.run(number_lexer.exponentPart, 'E123a3'), 123);
    
    test.equal(parse.run(number_lexer.exponentPart, 'e-391'), -391);
    test.equal(parse.run(number_lexer.exponentPart, 'E+391'), 391);
    
    test.done();
};
Example #6
0
exports.signed_integer = function(test) {
    test.equal(parse.run(number_lexer.signedInteger, '012'), 12);
    test.equal(parse.run(number_lexer.signedInteger, '123a3'), 123);
    
    test.equal(parse.run(number_lexer.signedInteger, '-391'), -391);
    test.equal(parse.run(number_lexer.signedInteger, '+391'), 391);
    
    test.done();
};
Example #7
0
exports.unsigned_integer = function(test) {
    test.equal(parse.run(number_lexer.unsignedInteger, '012'), 12);
    test.equal(parse.run(number_lexer.unsignedInteger, '123a3'), 123);
    
    test.throws(parse.run.bind(undefined, number_lexer.unsignedInteger, '-3'));
    test.throws(parse.run.bind(undefined, number_lexer.unsignedInteger, '+3'));
    
    test.done();
};
Example #8
0
exports.startChars = function(test) {
    test.deepEqual(
        parse.run(identifier_lexer.identifier, '$ab$c$'),
        '$ab$c$');
    
    test.deepEqual(
        parse.run(identifier_lexer.identifier, '_ab_c_'),
        '_ab_c_');
    
    test.done();
};
Example #9
0
exports.baicIdentifier = function(test) {
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'a0bc'),
        'a0bc');
    
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'a0bc efd'),
        'a0bc');
    
    test.done();
};
Example #10
0
 parse.attempt(line.chain(function(o) {
     return parse.choice(
         parse.next(
             parse.many(text.match(/\n/))
           , parse.setPosition(new parse.Position(0))
                 .chain(_.constant(self.map(function(os) {
                     return ([ o ]).concat(os);
                 })))
         )
       , parse.of([ o ])
     );
 }))
Example #11
0
 P.bind(P.many(PT.oneOf('0123456789')).map(join), width =>
 P.bind(P.many(PT.oneOf('Lhl')).map(join), size =>
 P.choice(
   P.bind(PT.oneOf('dxoiufcs%n'), type => {
     width = width.length > 0 ? parseInt(width) : false;
     if (type === '%') {
       return P.always({kind: 'l', chars: '%'});
     }
     return P.always({kind: 'p', noStore, width, size, type})}),
   P.next(PT.character('['),
     P.bind(P.optional(false, P.next(PT.character('^'), P.always(true))), negated =>
     P.bind(fp_charset_tail, set =>
     P.always({kind: 'p', noStore, width, type: 'C', negated, set})))))))));
Example #12
0
 .chain(_.spread(function(short, long) {
     return (
     (short.arg && long.arg && short.arg !== long.arg)
       ? parse.fail(util.mstr('\
             Short and long arguments differ.    \n\
             Please either use the same argument \n\
             for both or only specify on one.    \
         '))
       : parse.of({
             short: _.assign(short, { arg: short.arg || long.arg })
           , long: _.assign(long,  { arg: short.arg || long.arg })
           , arg: short.arg || long.arg
         }));
 }))
Example #13
0
exports.reservedWorsd = function(test) {
    test.throws(
        parse.run.bind(undefined, identifier_lexer.identifier, 'while'));
    
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'While'),
        'While');
    
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'awhile'),
        'awhile');
    
    test.done();
};
Example #14
0
 return parse.rec(function(self) {
     return parse.optional(
         []
       , parse.choicea(_.map(available, function(parser) {
             return parse.attempt(base.$(parser))
                 .chain(function(output) {
                     available = _.without(parser);
                     return self.map(function(outputs) {
                         return [ output ].concat(outputs);
                     });
                 });
       }))
     );
 });
Example #15
0
        it('if flag arg does not match (-f FILE)', function() {
            var usage = parse.run(
                meta.usage.line('git')
              , 'git -f FILE'
            );

            var option = parse.run(
                meta.options.line
             , '-f, --file FOO  The file to use.'
            );

            var resolved = meta.resolve(usage, [ option ]);

            assert.strictEqual(resolved[0].length, 2);
            assert.strictEqual(resolved[0][0].type, nodes.TYPE.OPTION);
            assert.strictEqual(resolved[0][1].type, nodes.TYPE.POSITIONAL);
        });
Example #16
0
        it('if flag arg matches (--file FILE)', function() {
            var usage = parse.run(
                meta.usage.line('git')
              , 'git --file FILE'
            );

            var option = parse.run(
                meta.options.line
             , '-f, --file FILE  The file to use.'
            );

            var resolved = meta.resolve(usage, [ option ]);

            assert.strictEqual(resolved[0].length, 1);
            assert.strictEqual(resolved[0][0].type, nodes.TYPE.OPTION);
            assert.strictEqual(resolved[0][0].arg, 'FILE');
        });
Example #17
0
function run(parser, input_) {
    try {
        parse.run(parser, input_);
    } catch(e) {
        console.log(e.toString());
        throw new Error(e.toString());
    }
}
Example #18
0
exports.doesNotCapturePuctuation = function(test) {
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'a.c.d'),
        'a');
    
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'a(c)'),
        'a');
    
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'a+'),
        'a');
    
    test.deepEqual(
        parse.run(identifier_lexer.identifier, 'a\\'),
        'a');
    
    test.done();
};
Example #19
0
        it('if no options provided (-f FILE)', function() {
            var usage = parse.run(
                meta.usage.line('git')
              , 'git -f FILE'
            );

            var resolved = meta.resolve(usage, []);

            assert.strictEqual(resolved[0].length, 2);
            assert.strictEqual(resolved[0][0].type, nodes.TYPE.OPTION);
            assert.strictEqual(resolved[0][1].type, nodes.TYPE.POSITIONAL);
        });
Example #20
0
 , _.spread(function(desc, defs) {
       return (desc !== undefined
           || defs  !== undefined
       )
         ? self.chain(_.spread(function(desc1, defs1) {
               return parse.of([
                   desc + desc1
                 , defs.concat(defs1)
               ]);
           }))
         : parse.of(['', []]);
   })
Example #21
0
 .chain(_.spread(function(desc, defs) {
     return (_.contains(desc, '[default:'))
       ? base.fail(
             'Unparsed `[default: ...]` found. '
           + 'Defaults should be specified at the '
           + 'end of a line.'
         )
       : parse.of([
             desc.replace(
                 _.repeat(' ', state.position.index)
               , '')
             , defs ]);
 }))
Example #22
0
var option = function(name, argumentRequired) {
    return base.cons(
        text.string(name)
      , ((argumentRequired)
          ? parse.choice(
                parse.attempt(parse.next(text.string('='), argument.name))
              , parse.attempt(parse.next(text.string(' '), argument.name)))
          : parse.of(null))).map(_.spread(function(__, value) {
                return value;
            }));
};
Example #23
0
exports.line_terminator_sequence = function(test) {
    test.equal(parse.run(line_terminator_lexer.lineTerminatorSequence, '\u000A'), '\u000A');
    test.equal(parse.run(line_terminator_lexer.lineTerminatorSequence, '\u2028'), '\u2028');
    test.equal(parse.run(line_terminator_lexer.lineTerminatorSequence, '\u2029'), '\u2029');
    
    // CR
    test.equal(parse.run(line_terminator_lexer.lineTerminatorSequence, '\u000D'), '\u000D');
    test.equal(parse.run(line_terminator_lexer.lineTerminatorSequence, '\u000Dabc'), '\u000D');
    test.equal(parse.run(line_terminator_lexer.lineTerminatorSequence, '\u000D\u000A'), '\u000D\u000A');
    
    test.done();
};
Example #24
0
var leadingFlags = parse.getParserState.chain(function(state) {
    return parse.choice(
        parse.attempt(base.cons(
            option.short
          , parse.next(
                parse.either(
                  text.string(', ')
                , text.string(' '))
              , option.long)
        ))
        .chain(_.spread(function(short, long) {
            return (
            (short.arg && long.arg && short.arg !== long.arg)
              ? parse.fail(util.mstr('\
                    Short and long arguments differ.    \n\
                    Please either use the same argument \n\
                    for both or only specify on one.    \
                '))
              : parse.of({
                    short: _.assign(short, { arg: short.arg || long.arg })
                  , long: _.assign(long,  { arg: short.arg || long.arg })
                  , arg: short.arg || long.arg
                }));
        }))
      , parse.attempt(option.short)
            .map(function(short) {
                return { short: short };
            })
      , parse.attempt(option.long)
            .map(function(long) {
                return { long: long };
            })
    )
    .chain(function(flags) {
        return parse.modifyState(function(userState) {
            return _.assign(userState || {}, {
                flagStart: state.position.index
            });
        }).chain(_.constant(parse.of(flags)));
    });
});
Example #25
0
_generators[nodes.TYPE.GROUP] = function(node) {
    return parse.choicea(_.map(node.nodes, _generateEither));
};
Example #26
0
_generators[nodes.TYPE.OPTION] = function(node) {
    return parse.attempt(input.argument.option(
        node.name, (!!node.arg)
    ));
};
Example #27
0
/**
 * Generate a parser for a complete usage spec.
 */
function generate(usage, options) {
    return parse.choicea(_.map(
        usage
      , _.flow(_generateUsagecase, base.$, parse.attempt)));
}
Example #28
0
var _generateUsagecase = function(usecase) {
    return parse.either(parse.choicea(_.map(
        usecase
      , _.flow(_generateEither, base.$)
    ), parse.eof));
};
Example #29
0
        _.spread(function(state, userState) {
            return (userState
                && userState.descriptionStart
                && userState.descriptionStart != state.position.index)
              ? base.fail('Description start not aligned!')
              : parse.rec(function(self) {
                    return parse.bind(
                        parse.choice(

                            // -----------------------------
                            // Try to parse defaults
                            // Note: Must be situated at EOL
                            //       or EOF.
                            // -----------------------------
                            parse.attempt(
                                parse.next(
                                    parse.many1(base.space)
                                  , lang.then(
                                        defaults
                                      , parse.either(
                                            parse.lookahead(
                                                text.match(/\n/)
                                            )
                                          , parse.eof
                                        )
                                    )
                                ).map(function(defs) {
                                    return [ '', [ defs ] ];
                                })
                            )

                            // ---------------------------------
                            // Try to parse plain text
                            // Note: This also parses new-lines
                            //       if the indentation matches.
                            // ---------------------------------
                          , parse.attempt(parse.choice(
                                parse.attempt(parse.sequence(
                                    text.match(/\n/)
                                  , text.string(_.repeat(
                                        ' '
                                      , state.position.index
                                    ))
                                  , text.match(/[^\n ]/)
                                ))
                                .map(function(s) { return ' ' + s; })
                              , parse.attempt(text.match(/[^\n]/))
                            ).map(function(desc) { return [ desc, [] ]; }))

                           // -------------------
                           // Parse final EOF/EOL
                           // -------------------
                          , parse.look(
                                parse.either(
                                    text.match(/\n/)
                                  , parse.eof
                                ).map(_.constant([]))
                            )
                        )
                      , _.spread(function(desc, defs) {
                            return (desc !== undefined
                                || defs  !== undefined
                            )
                              ? self.chain(_.spread(function(desc1, defs1) {
                                    return parse.of([
                                        desc + desc1
                                      , defs.concat(defs1)
                                    ]);
                                }))
                              : parse.of(['', []]);
                        })
                    );
                })

                // ---------------------
                // Sanitize and validate
                // ---------------------
                .chain(_.spread(function(desc, defs) {
                    return (_.contains(desc, '[default:'))
                      ? base.fail(
                            'Unparsed `[default: ...]` found. '
                          + 'Defaults should be specified at the '
                          + 'end of a line.'
                        )
                      : parse.of([
                            desc.replace(
                                _.repeat(' ', state.position.index)
                              , '')
                            , defs ]);
                }))

                .map(_.spread(function(desc, defs) {
                    return {
                        defaults: defs
                      , description: desc
                    };
                }))

                .chain(function(out) {
                    return parse.modifyState(function(userState) {
                        return _.assign(userState || {}, {
                            descriptionStart: state.position.index
                        });
                    }).chain(_.constant(parse.of(out)));
                });
        })
Example #30
0
'use strict';

var parse = require('bennu').parse
  , command = require('./command')
  , option = require('./option')
  , positional = require('./positional')
  , modifiers = require('./modifiers')
  , argname = require('./argname')
;

/**
 * Parse an argument, either positional
 * or not.
 */
var argument = parse.choice(
    parse.attempt(command)
  , modifiers.maybeOptional(modifiers.maybeRepeated(parse.attempt(option)))
  , modifiers.maybeOptional(modifiers.maybeRepeated(parse.attempt(positional)))
);

module.exports = argument;
module.exports.option = option;
module.exports.positional = positional;
module.exports.ARGNAME = argname.ARGNAME;
module.exports._argname_ = argname._argname_;