grammar FuzzyDoc;

source: .*? (routes .*?)+;

routes: path | route | use | script | clazz | mvcRoute;

use:
     doc=DOC 'use' '(' pattern=STRING ')'
   | doc=DOC 'use' '(' method=STRING comma+=',' pattern=STRING comma+=','
   | doc=DOC 'use' '(' pattern=STRING comma+=',';

path:
      doc=DOC? 'path' '(' pattern=STRING ',' '(' ')' '->' scripts
    | doc=DOC? 'path' '(' pattern=STRING ')' scripts;

route: doc=DOC 'route' '(' pattern=STRING ')' scripts;

scripts: '{' (scripts | script | .)*? '}';

clazz: doc=DOC annotations+=annotation+ (isClass='class'|.)*? '{' classBody  '}';

classBody: (mvcRoute | .)*?;

script:
        doc=DOC dot='.'? method=METHOD kotlinScriptBody
      | doc=DOC dot='.'? method=METHOD '(' ')' kotlinScriptBody
      | doc=DOC dot='.'? method=METHOD '(' kotlinScriptBody ')'
      | doc=DOC dot='.'? method=METHOD '(' pattern=STRING ')' kotlinScriptBody

      | doc=DOC dot='.'? method=METHOD '(' pattern=STRING ',' 'req'  scriptBody
      | doc=DOC dot='.'? method=METHOD '(' pattern=STRING ',' '(' ')' scriptBody
      | doc=DOC dot='.'? method=METHOD '(' pattern=STRING ',' '(' 'req' ')' scriptBody
      | doc=DOC dot='.'? method=METHOD '(' pattern=STRING ',' '(' 'req' ',' 'rsp' ')' scriptBody
      | doc=DOC dot='.'? method=METHOD '(' pattern=STRING ',' '(' 'req' ',' 'rsp' ',' 'chain' ')' scriptBody

      | doc=DOC dot='.'? method=METHOD '(' 'req'  scriptBody
      | doc=DOC dot='.'? method=METHOD '(' '(' ')' scriptBody
      | doc=DOC dot='.'? method=METHOD '(' '(' 'req' ')' scriptBody
      | doc=DOC dot='.'? method=METHOD '(' '(' 'req' ',' 'rsp' ')' scriptBody
      | doc=DOC dot='.'? method=METHOD '(' '(' 'req' ',' 'rsp' ',' 'chain' ')' scriptBody
      | path;

scriptBody:
      '->' '{' (scriptBody | .)*? '}' ')'
    | '->' .*? ')';

kotlinScriptBody:
      '{' '->' (kotlinScriptBody | .)*? '}'
    | '{' 'req' '->' (kotlinScriptBody | .)*? '}'
    | '{' 'req' ',' 'rsp' '->' (kotlinScriptBody | .)*? '}'
    | '{' (kotlinScriptBody | .)*? '}';

mvcRoute: doc=DOC annotations+=annotation+;

annotation:
    name=ANNOTATION '(' 'value' '=' value=STRING ')'
  | name=ANNOTATION '(' value=STRING ')'
  | name=ANNOTATION '(' ')'
  | name=ANNOTATION;

DOC: '/**' .*? '*/';

STRING : '"' ( '\\"' | . )*? '"';

ANNOTATION: '@' [a-zA-Z]+;

CLASS: 'class';

METHOD: 'get' | 'post' | 'put' | 'patch' | 'delete' | 'connect' | 'head' | 'options' | 'trace' | 'all';

WS : [ \r\t\n]+ -> skip;

ANY: . -> skip;

