%}



/*
 * Lex pattern definitions.
 */
delim		([^a-zA-Z0-9-])
lineBreak       ("\n\015"|"\n")
WSP		(" "|"\t")
VCHAR		([\041-\176])
textVChar	[!#-\176]
HTAB		"\t"
SP		" "
/*
 * Lex state definitions.
 */
%s		Comment
%s		String



%%



 /*
  * Lex rules.
  */

"//" {
    smingTrackInput(0, parser);
    BEGIN(Comment);
}

{lineBreak} {
    smingTrackInput(1, parser);
    BEGIN(INITIAL);
}

{WSP}|{VCHAR} {
    smingTrackInput(0, parser);
}

 /*
  * Lex rules for some special tokens.
  */

[\{\}\(\)\;\,\-\.\|] {
    smingTrackInput(0, parser);
    return yytext[0];
}
    
".." {
    smingTrackInput(0, parser);
    return DOT_DOT;
}

"::" {
    smingTrackInput(0, parser);
    return COLON_COLON;
}

 /*
  * Lex rules for separators.
  */

{lineBreak} {
    smingTrackInput(1, parser);
}

{WSP} {
    smingTrackInput(0, parser);
}

 /*
  * Lex rules for known keywords.
  */

module/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return moduleKeyword;
}

import/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return importKeyword;
}

revision/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return revisionKeyword;
}

oid/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return oidKeyword;
}

date/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return dateKeyword;
}

organization/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return organizationKeyword;
}

contact/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return contactKeyword;
}

description/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return descriptionKeyword;
}

reference/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return referenceKeyword;
}

typedef/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return typedefKeyword;
}

type/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return typeKeyword;
}

writetype/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return writetypeKeyword;
}

node/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return nodeKeyword;
}

scalar/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return scalarKeyword;
}

table/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return tableKeyword;
}

column/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return columnKeyword;
}

row/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return rowKeyword;
}

notification/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return notificationKeyword;
}

group/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return groupKeyword;
}

compliance/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return complianceKeyword;
}

format/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return formatKeyword;
}

units/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return unitsKeyword;
}

status/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return statusKeyword;
}

access/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return accessKeyword;
}

default/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return defaultKeyword;
}

implied/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return impliedKeyword;
}

index/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return indexKeyword;
}

augments/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return augmentsKeyword;
}

reorders/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return reordersKeyword;
}

sparse/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return sparseKeyword;
}

expands/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return expandsKeyword;
}

create/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return createKeyword;
}

objects/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return objectsKeyword;
}

mandatory/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return mandatoryKeyword;
}

optional/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return optionalKeyword;
}

refine/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return refineKeyword;
}

OctetString/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return OctetStringKeyword;
}

ObjectIdentifier/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return ObjectIdentifierKeyword;
}

Integer32/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return Integer32Keyword;
}

Unsigned32/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return Unsigned32Keyword;
}

Integer64/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return Integer64Keyword;
}

Unsigned64/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return Unsigned64Keyword;
}

Float32/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return Float32Keyword;
}

Float64/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return Float64Keyword;
}

Float128/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return Float128Keyword;
}

Bits/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return BitsKeyword;
}

Enumeration/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return EnumerationKeyword;
}

current/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return currentKeyword;
}

deprecated/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return deprecatedKeyword;
}

obsolete/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return obsoleteKeyword;
}

noaccess/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return noaccessKeyword;
}

notifyonly/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return notifyonlyKeyword;
}

readonly/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return readonlyKeyword;
}

readwrite/{delim} {
    smingTrackInput(0, parser);
    yylval.id = yytext;
    return readwriteKeyword;
}

 /*
  * Lex rules for identifiers.
  */

 /* e.g. module names: REF: draft,p.12-13 */
[A-Z](-?[a-zA-Z0-9]+)*-? {
    smingTrackInput(0, parser);
    if (yytext[yyleng-1] == '-') {
	printError(parser, ERR_ID_ENDS_IN_HYPHEN, yytext);
    }
    yylval.text = util_strdup(yytext);
    return ucIdentifier;
}

 /* same for lowercase names */
[a-z](-?[a-zA-Z0-9]+)*-? {
    smingTrackInput(0, parser);
    if (yytext[yyleng-1] == '-') {
	printError(parser, ERR_ID_ENDS_IN_HYPHEN, yytext);
    }
    yylval.text = util_strdup(yytext);
    return lcIdentifier;
}

 /*
  * Lex rules for numbers.
  *
  * NOTE: `-' is a separate token. Hence, there are no negative numbers.
  */

0+/[0-9] {
    smingTrackInput(0, parser);
    printError(parser, ERR_LEADING_ZEROS);
}

([1-9][0-9]*|0)/[^0-9] {
    smingTrackInput(0, parser);
    if ((strlen(yytext) > sizeof(MAX_NUMBER)-1) ||
	((strlen(yytext) == sizeof(MAX_NUMBER)-1) &&
	 (strcmp(yytext, MAX_NUMBER) > 0))) {
	printError(parser, ERR_NUMBER_TO_LARGE, yytext);
    }
    yylval.text = yytext;
    return decimalNumber;
}

0x[0-9a-fA-F]+/[^0-9a-fA-F] {
    smingTrackInput(0, parser);
    if (strlen(yytext) % 2) {
	printError(parser, ERR_HEX_STRING_MUL2, yytext);
    }
    yylval.text = yytext;
    return hexadecimalNumber;
}
 /*
  * Lex rules for floating point values.
  */

0.00/{delim} {
    /* TODO */
    smingTrackInput(0, parser);
    yylval.text = yytext;
    return floatValue;
}

 /*
  * Lex rules for textSegments.
  */

\" {
    smingTrackInput(0, parser);
    currentStringColumn = thisParser.column+1;
    if (currentStringMaxLength <= (currentStringLength+1)) {
        currentStringMaxLength += 4096;
        currentString = realloc(currentString, currentStringMaxLength);
    }
    currentStringLength = 0;
    currentString[0] = '\0';
    BEGIN(String);
}

\" {
    smingTrackInput(0, parser);
    yylval.text = currentString;
    BEGIN(INITIAL);
    return textSegment;
}

 /*
  * any 7-bit displayable ASCII character
  * tab character
  * spaces, and
  * line terminator characters (\n or \r\n)
  */
{textVChar} {
    smingTrackInput(0, parser);
    if (currentStringMaxLength <= (currentStringLength+1)) {
        currentStringMaxLength += 4096;
        currentString = realloc(currentString, currentStringMaxLength);
    }
    currentString[currentStringLength] = yytext[0];
    currentString[currentStringLength+1] = '\0';
    currentStringLength++;
    currentStringFetchLine = 1;
}

{HTAB}|{SP} {
    smingTrackInput(0, parser);
    if (currentStringMaxLength <= (currentStringLength+1)) {
        currentStringMaxLength += 4096;
        currentString = realloc(currentString, currentStringMaxLength);
    }
    if (currentStringFetchLine || (thisParser.column >= currentStringColumn)) {
	currentString[currentStringLength] = yytext[0];
	currentString[currentStringLength+1] = '\0';
	currentStringLength++;
	currentStringFetchLine = 1;
    }
}

{lineBreak} {
    smingTrackInput(1, parser);
    if (currentStringMaxLength <= (currentStringLength+1)) {
        currentStringMaxLength += 4096;
        currentString = realloc(currentString, currentStringMaxLength);
    }
    currentString[currentStringLength] = '\n';
    currentString[currentStringLength+1] = '\0';
    currentStringLength++;
    currentStringFetchLine = 0;
}

. {
    char a[20];

    smingTrackInput(0, parser);
    if (currentStringMaxLength <= (currentStringLength+1)) {
        currentStringMaxLength += 4096;
        currentString = realloc(currentString, currentStringMaxLength);
    }
    currentString[currentStringLength] = yytext[0];
    currentString[currentStringLength+1] = '\0';
    currentStringLength++;
    sprintf(a, "code %u, column %d", (unsigned char)yytext[0],
	    thisParser.column-1);
    printError(parser, ERR_ILLEGAL_CHAR_IN_STRING, a);
}

 /*
  *
  */

. {
    smingTrackInput(0, parser);
    printError(parser, ERR_LEX_UNEXPECTED_CHAR);
}

%%