// clang-format off /* * $Id: sml.c 536 2007-06-02 06:09:00Z elliotth $ * * Copyright (c) 2002, Venkatesh Prasad Ranganath and Darren Hiebert * * This source code is released for free distribution under the terms of the * GNU General Public License. * * This module contains functions for generating tags for SML language files. */ /* * INCLUDE FILES */ #include "third_party/ctags/general.h" /* must always come first */ #include "libc/mem/alg.h" #include "libc/str/str.h" #include "third_party/ctags/entry.h" #include "third_party/ctags/parse.h" #include "third_party/ctags/read.h" #include "third_party/ctags/vstring.h" /* * DATA DECLARATIONS */ typedef enum { K_AND = -2, K_NONE = -1, K_EXCEPTION, K_FUNCTION, K_FUNCTOR, K_SIGNATURE, K_STRUCTURE, K_TYPE, K_VAL } smlKind; /* * DATA DEFINITIONS */ static kindOption SmlKinds[] = { { TRUE, 'e', "exception", "exception declarations" }, { TRUE, 'f', "function", "function definitions" }, { TRUE, 'c', "functor", "functor definitions" }, { TRUE, 's', "signature", "signature declarations" }, { TRUE, 'r', "structure", "structure declarations" }, { TRUE, 't', "type", "type definitions" }, { TRUE, 'v', "value", "value bindings" } }; static struct { const char *keyword; smlKind kind; } SmlKeywordTypes [] = { { "abstype", K_TYPE }, { "and", K_AND }, { "datatype", K_TYPE }, { "exception", K_EXCEPTION }, { "functor", K_FUNCTOR }, { "fun", K_FUNCTION }, { "signature", K_SIGNATURE }, { "structure", K_STRUCTURE }, { "type", K_TYPE }, { "val", K_VAL } }; static unsigned int CommentLevel = 0; /* * FUNCTION DEFINITIONS */ static void makeSmlTag (smlKind type, vString *name) { tagEntryInfo tag; initTagEntry (&tag, vStringValue (name)); tag.kindName = SmlKinds [type].name; tag.kind = SmlKinds [type].letter; makeTagEntry (&tag); } static const unsigned char *skipSpace (const unsigned char *cp) { while (isspace ((int) *cp)) ++cp; return cp; } static boolean isIdentifier (int c) { boolean result = FALSE; /* Consider '_' as an delimiter to aid user in tracking it's usage. */ const char *const alternateIdentifiers = "!%&$#+-<>=/?@\\~'^|*_"; if (isalnum (c)) result = TRUE; else if (c != '\0' && strchr (alternateIdentifiers, c) != NULL) result = TRUE; return result; } static const unsigned char *parseIdentifier ( const unsigned char *cp, vString *const identifier) { boolean stringLit = FALSE; vStringClear (identifier); while (*cp != '\0' && (!isIdentifier ((int) *cp) || stringLit)) { int oneback = *cp; cp++; if (oneback == '(' && *cp == '*' && stringLit == FALSE) { CommentLevel++; return ++cp; } if (*cp == '"' && oneback != '\\') { stringLit = TRUE; continue; } if (stringLit && *cp == '"' && oneback != '\\') stringLit = FALSE; } if (strcmp ((const char *) cp, "") == 0 || cp == NULL) return cp; while (isIdentifier ((int) *cp)) { vStringPut (identifier, (int) *cp); cp++; } vStringTerminate (identifier); return cp; } static smlKind findNextIdentifier (const unsigned char **cp) { smlKind result = K_NONE; vString *const identifier = vStringNew (); unsigned int count = sizeof (SmlKeywordTypes) / sizeof (SmlKeywordTypes [0]); unsigned int i; *cp = parseIdentifier (*cp, identifier); for (i = 0 ; i < count && result == K_NONE ; ++i) { const char *id = vStringValue (identifier); if (strcmp (id, SmlKeywordTypes [i].keyword) == 0) result = SmlKeywordTypes [i].kind; } vStringDelete (identifier); return result; } static void findSmlTags (void) { vString *const identifier = vStringNew (); const unsigned char *line; smlKind lastTag = K_NONE; while ((line = fileReadLine ()) != NULL) { const unsigned char *cp = skipSpace (line); do { smlKind foundTag; if (CommentLevel != 0) { cp = (const unsigned char *) strstr ((const char *) cp, "*)"); if (cp == NULL) continue; else { --CommentLevel; cp += 2; } } foundTag = findNextIdentifier (&cp); if (foundTag != K_NONE) { cp = skipSpace (cp); cp = parseIdentifier (cp, identifier); if (foundTag == K_AND) makeSmlTag (lastTag, identifier); else { makeSmlTag (foundTag, identifier); lastTag = foundTag; } } if (strstr ((const char *) cp, "(*") != NULL) { cp += 2; cp = (const unsigned char *) strstr ((const char *) cp, "*)"); if (cp == NULL) ++CommentLevel; } } while (cp != NULL && strcmp ((const char *) cp, "") != 0); } vStringDelete (identifier); } extern parserDefinition *SmlParser (void) { static const char *const extensions[] = { "sml", "sig", NULL }; parserDefinition *def = parserNew ("SML"); def->kinds = SmlKinds; def->kindCount = KIND_COUNT (SmlKinds); def->extensions = extensions; def->parser = findSmlTags; return def; } /* vi:set tabstop=4 shiftwidth=4: */