diff --git a/bin/build.js b/bin/build.js index 628c5bd..b825c77 100755 --- a/bin/build.js +++ b/bin/build.js @@ -6,57 +6,48 @@ const llparse = require('llparse'); const llparseDot = require('llparse-dot'); const prj = 'vcd_parser'; - const p = new llparse.LLParse(prj); +// Add custom uint8_t property to the state +p.property('i8', 'command'); + const declaration = p.node('declaration'); +const commandSpan = p.span(p.code.span('commandSpan')); const inDeclaration = p.node('inDeclaration'); const enddefinitions = p.node('inDeclarationEnd'); const simulation = p.node('simulation'); const inSimulation = p.node('inSimulation'); -// Add custom uint8_t property to the state -p.property('i8', 'declaration'); -p.property('i8', 'simulation'); - -// Store method inside a custom property -const onDeclaration = p.invoke(p.code.store('declaration'), inDeclaration); -const onSimulation = p.invoke(p.code.store('simulation'), inSimulation); - declaration + .match([' ', '\n', '\t'], declaration) .select({ - '$comment': 0, - '$date': 1, - '$scope': 2, - '$timescale': 3, - '$upscope': 4, - '$var': 5, - '$version': 6 - }, onDeclaration) - .match('$enddefinitions', enddefinitions) - .otherwise(p.error(1, 'Expected declaration')); + '$comment': 1, '$date': 2, '$scope': 3, '$timescale': 4, + '$upscope': 5, '$var': 6, '$version': 7 + }, p.invoke(p.code.store('command'), commandSpan.start(inDeclaration))) + .select({ + '$enddefinitions': 100 + }, p.invoke(p.code.store('command'), commandSpan.start(enddefinitions))) + .otherwise(p.error(1, 'Expected declaration command')); inDeclaration - .match('$end', declaration) - .otherwise(p.error(2, 'Expected end of declaration')); + .match('$end', commandSpan.end(declaration)) + .skipTo(inDeclaration); enddefinitions - .match('$end', simulation) - .otherwise(p.error(3, 'Expected end of all declaration')); + .match('$end', commandSpan.end(simulation)) + .skipTo(enddefinitions); simulation + .match([' ', '\n', '\t'], simulation) .select({ - '$dumpall': 0, - '$dumpoff': 1, - '$dumpon': 2, - '$dumpvars': 3, - '$comment': 4 - }, onSimulation) - .otherwise(p.error(4, 'Expected simulation command')); + '$dumpall': 101, '$dumpoff': 102, '$dumpon': 103, '$dumpvars': 104, + '$comment': 1 + }, p.invoke(p.code.store('command'), commandSpan.start(inSimulation))) + .otherwise(p.error(2, 'Expected simulation command')); inSimulation - .match('$end', simulation) - .otherwise(p.error(5, 'Expected end simulation command')); + .match('$end', commandSpan.end(simulation)) + .skipTo(inSimulation); // Build diff --git a/test/basic.js b/test/basic.js index eed35c3..8a6a5e7 100644 --- a/test/basic.js +++ b/test/basic.js @@ -14,6 +14,52 @@ describe('basic', () => { console.log(cxt); done(); }); + it('fail: foo bar', done => { + const cxt = lib.init(); + expect(lib.execute(cxt, ' foo bar ???', '')).to.eq(1); + expect(lib.getError(cxt)).to.eq(1); + expect(lib.getReason(cxt)).to.eq('Expected declaration command'); + done(); + }); + it('$comment', done => { + const cxt = lib.init(); + expect(lib.execute(cxt, ' \n $comment some text $end $comment more text $end ???', '')).to.eq(1); + expect(lib.getError(cxt)).to.eq(1); + expect(lib.getReason(cxt)).to.eq('Expected declaration command'); + expect(lib.getCommand(cxt)).to.eq(1); + // expect(lib.getErrorPos(cxt)).to.eq('Expected declaration'); + done(); + }); + it('$version', done => { + const cxt = lib.init(); + expect(lib.execute(cxt, ` +$version Generated by VerilatedVcd $end +$date Wed Sep 18 22:59:07 2019 + $end +$timescale 1ns $end + + $scope module top $end + $var wire 1 "}G clock $end + $scope module leaf $end + $var wire 64 "}> counter [63:0] $end + $upscope $end + $upscope $end + +$enddefinitions $end + +#1 +0"}G +#2 +1"}G +#3 +0"}G + +`, '')).to.eq(2); + expect(lib.getError(cxt)).to.eq(2); + expect(lib.getReason(cxt)).to.eq('Expected simulation command'); + expect(lib.getCommand(cxt)).to.eq(100); + done(); + }); }); /* eslint-env mocha */ diff --git a/vcd.c b/vcd.c index a6adc2c..57b6e08 100644 --- a/vcd.c +++ b/vcd.c @@ -33,7 +33,7 @@ } #define ASSERT_STRING(name, var) \ - char var[256]; \ + char var[4096]; \ { \ napi_value tmp; \ if (napi_coerce_to_string(env, name, &tmp) != napi_ok) { \ @@ -41,7 +41,7 @@ return 0; \ } \ size_t result; \ - if (napi_get_value_string_latin1(env, tmp, var, 256, &result) != napi_ok) { \ + if (napi_get_value_string_latin1(env, tmp, var, 4096, &result) != napi_ok) { \ napi_throw(env, name); \ return 0; \ } \ @@ -91,10 +91,59 @@ METHOD(execute) { return res; } -napi_value Init(napi_env env, napi_value exports) { - DECLARE_NAPI_METHOD("init", init) - DECLARE_NAPI_METHOD("execute", execute) - return exports; +METHOD(getError) { + ASSERT_ARGC(1) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + + napi_value res; + ASSERT(res, napi_create_int32(env, state->error, &res)) + return res; } +METHOD(getReason) { + ASSERT_ARGC(1) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + + napi_value res; + ASSERT(res, napi_create_string_utf8(env, state->reason, NAPI_AUTO_LENGTH, &res)) + return res; +} + +METHOD(getErrorPos) { + ASSERT_ARGC(1) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + + napi_value res; + ASSERT(res, napi_create_int32(env, state->error_pos, &res)) + return res; +} + +METHOD(getCommand) { + ASSERT_ARGC(1) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + + napi_value res; + ASSERT(res, napi_create_int32(env, state->command, &res)) + return res; +} + +napi_value Init(napi_env env, napi_value exports) { + DECLARE_NAPI_METHOD("init", init) + DECLARE_NAPI_METHOD("execute", execute) + DECLARE_NAPI_METHOD("getError", getError) + DECLARE_NAPI_METHOD("getReason", getReason) + DECLARE_NAPI_METHOD("getErrorPos", getErrorPos) + DECLARE_NAPI_METHOD("getCommand", getCommand) + return exports; +} + +int commandSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { + printf("%d:%.*s\n", s->command, (int)(endp - p - 4), p); + return 0; +}; + NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)