Jison

Online demo & try

Grammar

/* lexical grammar */
%lex
%%

[ \t]*\n[ \t]*   return 'END'
">"    return 'FROM_TO'
"="    return 'DEFINE_BY'
[a-zA-Z0-9]+  return 'ENTITY'
"'"    return "'"
<<EOF>>               return 'EOF'
\s                   /* skip whitespace */
.                     return 'INVALID'

/lex

/* operator associations and precedence */
%left FROM_TO
%left DEFINE_BY

%% /* language grammar */

exps
    : expressions EOF
       {return $expressions;}
    ;

expressions
    : expressions END ed
        {$$ = $expressions; $$.unshift($ed); }
    | expressions END eft
        {$$ = $expressions; $$.push($ed); }
    | e
        {$$ = [$e];}
    ;

e
    :ed
      {ss=$1;}
    |eft
      {ss=$1;}
    ;

ed
    : ENTITY DEFINE_BY text
      {$$={}; $$[$1] = $text;}
    ;

eft
    : ENTITY FROM_TO text
      {$$=[$1, $text];}
    ;

text
    : "'" ENTITY "'"
        { $$=$2;}
    ;

Inputs

asdf > 'asdjfasxdfasf'
fs = 'asdff'
s = 'fasdf'
fff = 'asdf'

Generates

[{"fff":"asdf"},{"s":"fasdf"},{"fs":"asdff"},["asdf","asdjfasxdfasf"]]

Notes

  1. definations will be put before directions,
  2. humanize line break.

TODO

  1. definations should be combined into one dict,
  2. string escape should be support.

New Jison

/* description: Parses end executes mathematical expressions. */

/* lexical grammar */
%lex
%%

[ \t]*[\r\n]+[ \t]*   return 'END'
">"    return 'FROM_TO'
"="    return 'DEFINE_BY'
[a-zA-Z0-9]+  return 'ENTITY'
"'"    return "'"
<<EOF>>               return 'EOF'
\s                   /* skip whitespace */
.                     return 'INVALID'

/lex

%% /* language grammar */

exps
    : expressions EOF
       {return $expressions;}
    ;

expressions
    : expressions END ed
        %{
        $$ = $expressions;
        if($$['defs'][$ed[0]]) {
            yy.parser.error($ed[0] + ' redefined');
        }
        $$['defs'][$ed[0]] = $ed[1];
        %}
    | expressions END eft
        %{
        $$ = $expressions; 
        if(!$$['defs'][$eft[0]]) {
            yy.parser.error($eft[0] + ' undefined');
        }
        if(!$$['defs'][$eft[1]]) {
            yy.parser.error($eft[1] + ' undefined');
        }
        $$['links'].push($eft);
        %}
    | ed
        {$$ = {defs: {}, links:[]}; console.log($ed); $$['defs'][$ed[0]]=$ed[1];}
    ;

e
    :ed
      {ss=$1;}
    |eft
      {ss=$1;}
    ;

ed
    : ENTITY DEFINE_BY text
      {$$=[$1, $text];}
    ;

eft
    : ENTITY FROM_TO ENTITY
      {$$=[$1, $3];}
    ;

text
    : "'" ENTITY "'"
        { $$=$2;}
    ;

Inputs

asdf = 'asdjfasxdfasf'
asdf1 = 'fasdf'
fff = 'fasdf'

asdf > asdf1
fff > asdf

Generates

{"defs":{"asdf":"asdjfasxdfasf","asdf1":"fasdf","fff":"fasdf"},"links":[["asdf","asdf1"],["fff","asdf"]]}

Features

  1. supports compiling time check for defs and link targets,
  2. supports multiple empty lines,
  3. supports combined defs and links.