最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jison start conditions with json format - Stack Overflow

programmeradmin0浏览0评论

Despite long search in documentation and forums, I still fail to get the right syntax for Jison start condition using JSON format in node.js

> ** Documentation at / says:
> // Using the JSON format, start conditions are defined with an array
> // before the rule’s 
> matcher {rules:[
>     [['expect'], '[0-9]+"."[0-9]+', 'console.log( "found a float, = " + yytext );'
>     ]]}

But unfortunately no one not provides a full working sample.

I'm trying to exclude any text that is in between two tags. In lex would use start conditions. Jison documentation says it should works. Nevertheless as Jison error messages are not very intuitive, I would be please to find a working sample to move forward.

Would any one have the solution ?

var jison    = require("jison").Parser;

grammar = {  
    "lex": {
        "rules" : [ [" +" , "/* skip whitespace */"]
            ,[['mode1'], '[0-z]+\\b'        , "return 'INFO';"]
            ,[['mode1'], '<\\/extensions>'  , "this.popState(); return 'EXTEND';"]
            ,['<extensions>'                , "this.begin('mode1'); return 'EXTSTART';"]
            ,['$'                           , "return 'EOL';"]
        ]
    },  // end Lex rules

    "bnf": { // WARNING: only one space in between TOKEN ex: "STOP EOF"
        'data': [["EOL"      , "this.cmd='EMPTY'    ; return (this);"]           
           ,['EXTSTART INFO EXTEND EOL'  ,"this.cmd='EXTEN';this.value=$2;return (this);"]
           ]
    }};

  parser    = new jison(grammar);

  test= "\
    <extensions>\
      <opencpn:start></opencpn:start><opencpn:end></opencpn:end>\
      <opencpn:viz>1</opencpn:viz>\
     <opencpn:guid>714d1d6e-78be-46a0-af6e-2f3d0c505f6d</opencpn:guid>\
    </extensions>";

  data=parser.parse (test);

My current sample fail with

/node_modules/jison/node_modules/jison-lex/regexp-lexer.js:42 startConditions[conditions[k]].rules.push(i);

Despite long search in documentation and forums, I still fail to get the right syntax for Jison start condition using JSON format in node.js

> ** Documentation at http://zaach.github.io/jison/docs/ says:
> // Using the JSON format, start conditions are defined with an array
> // before the rule’s 
> matcher {rules:[
>     [['expect'], '[0-9]+"."[0-9]+', 'console.log( "found a float, = " + yytext );'
>     ]]}

But unfortunately no one not provides a full working sample.

I'm trying to exclude any text that is in between two tags. In lex would use start conditions. Jison documentation says it should works. Nevertheless as Jison error messages are not very intuitive, I would be please to find a working sample to move forward.

Would any one have the solution ?

var jison    = require("jison").Parser;

grammar = {  
    "lex": {
        "rules" : [ [" +" , "/* skip whitespace */"]
            ,[['mode1'], '[0-z]+\\b'        , "return 'INFO';"]
            ,[['mode1'], '<\\/extensions>'  , "this.popState(); return 'EXTEND';"]
            ,['<extensions>'                , "this.begin('mode1'); return 'EXTSTART';"]
            ,['$'                           , "return 'EOL';"]
        ]
    },  // end Lex rules

    "bnf": { // WARNING: only one space in between TOKEN ex: "STOP EOF"
        'data': [["EOL"      , "this.cmd='EMPTY'    ; return (this);"]           
           ,['EXTSTART INFO EXTEND EOL'  ,"this.cmd='EXTEN';this.value=$2;return (this);"]
           ]
    }};

  parser    = new jison(grammar);

  test= "\
    <extensions>\
      <opencpn:start></opencpn:start><opencpn:end></opencpn:end>\
      <opencpn:viz>1</opencpn:viz>\
     <opencpn:guid>714d1d6e-78be-46a0-af6e-2f3d0c505f6d</opencpn:guid>\
    </extensions>";

  data=parser.parse (test);

My current sample fail with

/node_modules/jison/node_modules/jison-lex/regexp-lexer.js:42 startConditions[conditions[k]].rules.push(i);

Share Improve this question edited Sep 22, 2014 at 12:05 Louis 152k28 gold badges286 silver badges329 bronze badges asked Sep 17, 2014 at 11:37 FulupFulup 5453 silver badges15 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 13

Unfortunately no one provided an answer to my question :)

I had to reverse engineering Jison Lexer code to find out the right syntax. As I suppose it may help others, here after the answer :)

Jison's lexical conditions work fine under JSON syntax, but they should be predeclared in an array named "startConditions" as in following example.

grammar = { 
   "lex": {

       "startConditions" : { "INITIAL":"// Default initial Jison/Lex context"
            ,"MOD_EXT": "// extenstions context "
            ,"MOD_RTE": "// routes context"
        },

        "rules" : [['[\\n\\s]+' , "/* skip whitespace & new lines */"]
            // extensions blocs
            ,[['INITIAL'], '<extensions>'     , "this.begin('MOD_EXT');"]
            ,[['MOD_EXT'], '<\\/extensions>'  , "this.popState();"]
            ,[['MOD_EXT'], '[<>\\/\\-\\s\\n]', "/* ignore */"]
            ,[['MOD_EXT'], '[0-z]+'           , "/* ignore */"]
        Etc...

In order to make everyone life easier, here after a simple working example.

// Sample JISON start conditions with Jason syntax
var jison    = require("jison").Parser;

grammar = { 

    "lex": {
         "macros": {  // few usefull macro
            "slash": "\\/",
            "space": "\\s+",
            "quot" : "\\\'",
            "dquot": "\\\"",
            "dot"  : "\\.",
            "digit": "[0-9]",
            "int"  : "-?([0-9]+)",
            "float": "-?([0-9]*\\.[0-9]+)",
            "hexa" : "([0-9]|(a-h)|(A-H])+"
        },

       "startConditions" : { "INITIAL":"// Default initial Jison/Lex context"
            ,"MOD_EXT": "// extenstions context "
            ,"MOD_RTE": "// routes context"
        },

        "rules" : [['[\\n\\s]+' , "/* skip whitespace & new lines */"]
            // extensions blocs
            ,[['INITIAL'], '<extensions>'     , "this.begin('MOD_EXT');"]
            ,[['MOD_EXT'], '<\\/extensions>'  , "this.popState();"]
            ,[['MOD_EXT'], '[<>\\/\\-\\s\\n]', "/* ignore */"]
            ,[['MOD_EXT'], '[0-z]+'           , "/* ignore */"]

            // routes points blocs
            ,[['INITIAL'],'<rtept' , "this.begin('MOD_RTE'); return 'RTE_BEG';"]
            ,[['MOD_RTE'], '<\\/rtept>'       , "this.popState(); return 'RTE_END';"]
            ,[['MOD_RTE'], 'lat='             , "return 'LAT';"]
            ,[['MOD_RTE'], 'lon='             , "return 'LON';"]
            ,[['MOD_RTE'], '{float}'          , "return 'CARD';"]
            ,[['MOD_RTE'], '<name>'           , "return 'NAME_BEG';"]
            ,[['MOD_RTE'], '<\\/name>'        , "return 'NAME_END';"]
            ,[['MOD_RTE'], '<time>'           , "return 'TIME_BEG';"]
            ,[['MOD_RTE'], '<\\/time>'        , "return 'TIME_END';"]
            ,[['MOD_RTE'], '<sym>'            , "return 'SYM_BEG';"]
            ,[['MOD_RTE'], '<\\/sym>'         , "return 'SYM_END';"]
            ,[['MOD_RTE'], '<type>'           , "return 'TYPE_BEG';"]
            ,[['MOD_RTE'], '<\\/type>'        , "return 'TYPE_END';"]
            ,[['MOD_RTE'], '<extensions>'     , "this.begin('MOD_EXT');"]
            ,[['MOD_RTE'], '([0-z]|[-+])+\\b' , "return 'TEXT';"]
            ,[['MOD_RTE'], '[>{quot}{dquot}{space}]' , "// ignore"]

            // end of parsing buffer
            ,['$'                            , "return 'EOL';"]
        ]
    },  // end Lex rules

    "bnf": { // WARNING: only one space in between TOKEN ex: "STOP EOF"
        'data': [
            ["EOL"           ,  "return ('EMPTY');"]
           ,["ROUTEPOINTS EOL", "return (this.route);"]
           ]

        // handle multiple waypoints
         // A routepoint should at least have a LAT+LONG+NAME
        ,'ROUTEPOINTS' : [ // store all waypoint in an array
            ["ROUTEPOINT", "console.log('Parsing First Waypts=%j',this.waypts);this.route=[]; this.route.push(this.waypts);"]
           ,["ROUTEPOINTS ROUTEPOINT", "console.log('Parsing Next  Waypts=%j',this.waypts);;this.route.push(this.waypts);"]

        ]

        // A routepoint should at least have a LAT+LONG+NAME
        ,'ROUTEPOINT' :  [ // <rtept lat='47.542780648' lon='-2.896743643'>...
            ["RTE_BEG LATITUDE LONGITUDE DATE NAME SYM TYPE RTE_END", "this.waypts={lat:$2,lon:$3,name:$5,date:$4};"]
           ,["RTE_BEG LATITUDE LONGITUDE DATE NAME RTE_END", "this.waypts={lat:$2,lon:$3,name:$5,date:$4};"]
           ,["RTE_BEG LATITUDE LONGITUDE NAME RTE_END", "this.waypts={lat:$2,lon:$3,name:$4,date:'unknow'};"]
        ]  
        // lat='47.542780648'
        ,'LATITUDE'    : [["LAT CARD", "$$=$2;"]]          
        //  lon='-2.896743643'
        , 'LONGITUDE'  : [["LON CARD", "$$=$2;"]]
        //<time>2014-09-16T21:55:19Z</time>\
        , 'DATE'       : [["TIME_BEG TEXT TIME_END", "$$=$2;"]]
        // <name>001</name>\
        , 'NAME'       : [["NAME_BEG TEXT NAME_END", "$$=$2;"]]
        // <sym>001</name>\
        , 'SYM'        : [["SYM_BEG TEXT SYM_END", "//ignore"]]
        // <name>001</name>\
        , 'TYPE'       : [["TYPE_BEG TEXT TYPE_END", "//ignore"]]

    }};


  parser    = new jison(grammar);

  test= "\
    <extensions>\
        <opencpn:start></opencpn:start><opencpn:end></opencpn:end>\
        <opencpn:viz>1</opencpn:viz>\
        <opencpn:guid>714d1d6e-78be-46a0-af6e-2f3d0c505f6d</opencpn:guid>\
    </extensions>\
    <rtept lat='47.542780648' lon='-2.896743643'>\
        <time>2014-09-16T21:55:19Z</time>\
        <name>001</name>\
        <sym>diamond</sym>\
        <type>WPT</type>\
        <extensions>\
            <opencpn:guid>408c309c-6a8c-411d-815b-0c0054646d45</opencpn:guid>\
            <opencpn:viz>1</opencpn:viz>\
            <opencpn:viz_name>0</opencpn:viz_name>\
            <opencpn:auto_name>1</opencpn:auto_name>\
        </extensions>\
    </rtept>\
    <rtept lat='44.542780648' lon='-4.896743643'>\
        <time>2014-08-16T21:55:19Z</time>\
        <name>002</name>\
    </rtept>\
    <rtept lat='43.542780648' lon='-5.896743643'>\
        <name>003</name>\
    </rtept>\
    <rtept lat='48.542780648' lon='-3.896743643'>\
        <time>2014-10-16T21:55:19Z</time>\
        <name>004</name>\
        <sym>diamond</sym>\
        <type>WPT</type>\
        <extensions>\
            <opencpn:guid>408c309c-6a8c-411d-815b-0c0054646d45</opencpn:guid>\
            <opencpn:viz>1</opencpn:viz>\
            <opencpn:viz_name>0</opencpn:viz_name>\
            <opencpn:auto_name>1</opencpn:auto_name>\
        </extensions>\
    </rtept>";

  route=parser.parse (test);

  console.log ("\n\nMy GPX route's waypoints");
  for (var waypts in route) {
      console.log (" -- name: %s  Lon: %s Lat:%s Date:%s", route [waypts].name, route [waypts].lat, route [waypts].lon, route [waypts].date);
  };

  console.log ("done");
发布评论

评论列表(0)

  1. 暂无评论