17b447529Sdriechers /*
27b447529Sdriechers * Copyright (c) 2017, Daniel Riechers
37b447529Sdriechers *
47b447529Sdriechers * This source code is released for free distribution under the terms of the
57b447529Sdriechers * GNU General Public License version 2 or (at your option) any later version.
67b447529Sdriechers *
77b447529Sdriechers * Parser from Robot Framework http://robotframework.org
87b447529Sdriechers */
97b447529Sdriechers
107b447529Sdriechers #include "general.h"
117b447529Sdriechers
127b447529Sdriechers #include <string.h>
137b447529Sdriechers
14950e3d50SMasatake YAMATO #include "entry.h"
157b447529Sdriechers #include "parse.h"
167b447529Sdriechers #include "vstring.h"
177b447529Sdriechers #include "routines.h"
187b447529Sdriechers
197b447529Sdriechers typedef enum {
207b447529Sdriechers K_TESTCASE,
217b447529Sdriechers K_KEYWORD,
227b447529Sdriechers K_VARIABLE,
237b447529Sdriechers COUNT_KIND
247b447529Sdriechers } RobotKind;
257b447529Sdriechers
267b447529Sdriechers static RobotKind section = -1;
277b447529Sdriechers
28e112e8abSMasatake YAMATO static kindDefinition RobotKinds[COUNT_KIND] = {
297b447529Sdriechers {true, 't', "testcase", "testcases"},
307b447529Sdriechers {true, 'k', "keyword", "keywords"},
317b447529Sdriechers {true, 'v', "variable", "variables"},
327b447529Sdriechers };
337b447529Sdriechers
343bb8a657SMasatake YAMATO typedef enum {
353bb8a657SMasatake YAMATO X_WHITESPACE_SWAPPED,
363bb8a657SMasatake YAMATO } robotXtag;
373bb8a657SMasatake YAMATO
38e3712f53SMasatake YAMATO static xtagDefinition RobotXtags [] = {
393bb8a657SMasatake YAMATO {
403bb8a657SMasatake YAMATO .enabled = true,
413bb8a657SMasatake YAMATO .name = "whitespaceSwapped",
423bb8a657SMasatake YAMATO .description = "Include tags swapping whitespace and underscore chars",
433bb8a657SMasatake YAMATO },
443bb8a657SMasatake YAMATO };
453bb8a657SMasatake YAMATO
463bb8a657SMasatake YAMATO
findRobotTags(void)477b447529Sdriechers static void findRobotTags (void)
487b447529Sdriechers {
497b447529Sdriechers findRegexTags ();
507b447529Sdriechers }
517b447529Sdriechers
whitespaceSwap(vString * const s)527b447529Sdriechers static bool whitespaceSwap (vString *const s)
537b447529Sdriechers {
547b447529Sdriechers char replaceWith = '_';
557b447529Sdriechers char toReplace = ' ';
567b447529Sdriechers char changed = false;
577b447529Sdriechers
58*e852ee0eSMasatake YAMATO if(strchr(vStringValue (s), '_'))
597b447529Sdriechers {
607b447529Sdriechers replaceWith = ' ';
617b447529Sdriechers toReplace = '_';
627b447529Sdriechers }
637b447529Sdriechers
6446ab94ccSMasatake YAMATO for(unsigned int i=0; i < vStringLength(s); i++)
65*e852ee0eSMasatake YAMATO if(vStringChar(s, i) == toReplace)
667b447529Sdriechers {
67*e852ee0eSMasatake YAMATO vStringChar (s, i) = replaceWith;
687b447529Sdriechers changed = true;
697b447529Sdriechers }
707b447529Sdriechers
717b447529Sdriechers return changed;
727b447529Sdriechers }
737b447529Sdriechers
changeSection(const char * const line,const regexMatch * const matches,const unsigned int count CTAGS_ATTR_UNUSED,void * data CTAGS_ATTR_UNUSED)7418480890SMasatake YAMATO static bool changeSection (const char *const line, const regexMatch *const matches,
75e4d16241SMasatake YAMATO const unsigned int count CTAGS_ATTR_UNUSED, void *data CTAGS_ATTR_UNUSED)
767b447529Sdriechers {
777b447529Sdriechers const char * const matchedSection = line + matches[1].start;
787b447529Sdriechers
797b447529Sdriechers if(strncasecmp(matchedSection, "test cases", matches[1].length) == 0)
807b447529Sdriechers {
817b447529Sdriechers section = K_TESTCASE;
827b447529Sdriechers }
837b447529Sdriechers else if(strncasecmp(matchedSection, "keywords", matches[1].length) == 0)
847b447529Sdriechers {
857b447529Sdriechers section = K_KEYWORD;
867b447529Sdriechers }
877b447529Sdriechers else if(strncasecmp(matchedSection, "variables", matches[1].length) == 0)
887b447529Sdriechers {
897b447529Sdriechers section = K_VARIABLE;
907b447529Sdriechers }
9118480890SMasatake YAMATO return true;
927b447529Sdriechers }
937b447529Sdriechers
makeSimpleXTag(const vString * const name,const int kind,unsigned int xtagType)94f92e6bf2SMasatake YAMATO static void makeSimpleXTag (const vString* const name, const int kind,
95950e3d50SMasatake YAMATO unsigned int xtagType)
96950e3d50SMasatake YAMATO {
97950e3d50SMasatake YAMATO tagEntryInfo e;
98950e3d50SMasatake YAMATO
9916a2541cSMasatake YAMATO initTagEntry (&e, vStringValue(name), kind);
100950e3d50SMasatake YAMATO markTagExtraBit (&e, xtagType);
101950e3d50SMasatake YAMATO makeTagEntry (&e);
102950e3d50SMasatake YAMATO }
103950e3d50SMasatake YAMATO
tagKeywordsAndTestCases(const char * const line,const regexMatch * const matches,const unsigned int count,void * data CTAGS_ATTR_UNUSED)10418480890SMasatake YAMATO static bool tagKeywordsAndTestCases (const char *const line, const regexMatch *const matches,
105e4d16241SMasatake YAMATO const unsigned int count, void *data CTAGS_ATTR_UNUSED)
1067b447529Sdriechers {
1077b447529Sdriechers if (count > 1 && ( section == K_KEYWORD || section == K_TESTCASE) )
1087b447529Sdriechers {
1097b447529Sdriechers vString *const name = vStringNew ();
1107b447529Sdriechers vStringNCopyS (name, line + matches [1].start, matches [1].length);
11116a2541cSMasatake YAMATO makeSimpleTag (name, section);
1123bb8a657SMasatake YAMATO if (isXtagEnabled (RobotXtags[X_WHITESPACE_SWAPPED].xtype)
1133bb8a657SMasatake YAMATO && whitespaceSwap(name))
114f92e6bf2SMasatake YAMATO makeSimpleXTag (name, section,
115950e3d50SMasatake YAMATO RobotXtags[X_WHITESPACE_SWAPPED].xtype);
1167b447529Sdriechers vStringDelete (name);
11718480890SMasatake YAMATO return true;
1187b447529Sdriechers }
11918480890SMasatake YAMATO return false;
1207b447529Sdriechers }
1217b447529Sdriechers
tagVariables(const char * const line,const regexMatch * const matches,const unsigned int count,void * data CTAGS_ATTR_UNUSED)12218480890SMasatake YAMATO static bool tagVariables (const char *const line, const regexMatch *const matches,
123e4d16241SMasatake YAMATO const unsigned int count, void *data CTAGS_ATTR_UNUSED)
1247b447529Sdriechers {
1257b447529Sdriechers if (count > 1 && section == K_VARIABLE)
1267b447529Sdriechers {
1277b447529Sdriechers vString *const name = vStringNew ();
1287b447529Sdriechers vStringNCopyS (name, line + matches [1].start, matches [1].length);
12916a2541cSMasatake YAMATO makeSimpleTag (name, K_VARIABLE);
1303bb8a657SMasatake YAMATO if (isXtagEnabled (RobotXtags[X_WHITESPACE_SWAPPED].xtype)
1313bb8a657SMasatake YAMATO && whitespaceSwap(name))
132f92e6bf2SMasatake YAMATO makeSimpleXTag (name, K_VARIABLE,
133950e3d50SMasatake YAMATO RobotXtags[X_WHITESPACE_SWAPPED].xtype);
1347b447529Sdriechers vStringDelete (name);
13518480890SMasatake YAMATO return true;
1367b447529Sdriechers }
13718480890SMasatake YAMATO return false;
1387b447529Sdriechers }
1397b447529Sdriechers
initialize(const langType language)1407b447529Sdriechers static void initialize (const langType language)
1417b447529Sdriechers {
14253dda59eSMasatake YAMATO addLanguageCallbackRegex (language, "^\\*+ *([^* ].+[^* ]) *\\*+$",
1437b447529Sdriechers "{exclusive}", changeSection, NULL, NULL);
1440e230a14SMasatake YAMATO
1450e230a14SMasatake YAMATO addLanguageCallbackRegex (
1460e230a14SMasatake YAMATO language,
1470e10675cSDerek Schrock "(^([A-Za-z0-9]+|\\$\\{[_A-Za-z0-9][' _A-Za-z0-9]*(:([^}]|\\\\)+)*\\})([${}' _]([-_$A-Za-z0-9]+|\\{[_A-Za-z0-9][' _A-Za-z0-9]*(:([^}]|\\\\)+)*\\})+)*)",
1487b447529Sdriechers "{exclusive}", tagKeywordsAndTestCases, NULL, NULL);
1490e230a14SMasatake YAMATO
15053dda59eSMasatake YAMATO addLanguageCallbackRegex (language, "^[$@]\\{([_A-Za-z0-9][' _A-Za-z0-9]+)\\} [ ]*.+",
1517b447529Sdriechers "{exclusive}", tagVariables, NULL, NULL);
1527b447529Sdriechers }
1537b447529Sdriechers
RobotParser(void)1547b447529Sdriechers extern parserDefinition* RobotParser (void)
1557b447529Sdriechers {
1567b447529Sdriechers static const char *const extensions[] = { "robot", NULL };
1577b447529Sdriechers parserDefinition *def = parserNew ("Robot");
15809ae690fSMasatake YAMATO def->kindTable = RobotKinds;
1597b447529Sdriechers def->kindCount = COUNT_KIND;
1607b447529Sdriechers def->extensions = extensions;
1617b447529Sdriechers def->initialize = initialize;
1627b447529Sdriechers def->parser = findRobotTags;
163a02a9600SMasatake YAMATO def->xtagTable = RobotXtags;
164a02a9600SMasatake YAMATO def->xtagCount = ARRAY_SIZE (RobotXtags);
1657b447529Sdriechers return def;
1667b447529Sdriechers }
167