Feature File Grammar Changes
Adobe has not—at least in recent memory—maintained a document with a formal grammar for feature files. However, when AFDKO feature file parser was ported to ANTLR 4 in 2021 we tried to make the new source files easy to read, in part so that other implementers can refer to them when there are changes. This document shows the differences between the three source files as they were in 2021 and how they are after variable value support has been added.
The tokenizer
The grammar for tokens is contained in FeatLexerBase.g4
, which is part of the addfeatures
in AFDKO (what used to be makeotfexe
. The substantive changes are:
- A number of new keywords
- Separate tokens for the axis units (
u
,d
, andn
-
(
,)
,+
, and:
are now keywords - Quoted strings are handled differently
-
LNAME
is the token for the restricted (compared with glyph names) grammar of location names -
CATCHTAG
(which parsed non-quoted tags with special characters) is removed
/* Copyright 2021 Adobe Systems Incorporated (http://www.adobe.com/). All Rights Reserved. * This software is licensed as OpenSource, under the Apache License, Version 2.0. * This license is available at: http://opensource.org/licenses/Apache-2.0. */ // -------------------------- Feature file tokens --------------------------- lexer grammar FeatLexerBase; COMMENT : '#' ~[\r\n]* -> skip ; WHITESPACE : [ \t\r\n]+ -> skip ; INCLUDE : 'include' -> pushMode(Include) ; FEATURE : 'feature' ; TABLE : 'table' ; SCRIPT : 'script' ; LANGUAGE : 'language' ; LANGSYS : 'languagesystem' ; SUBTABLE : 'subtable'; LOOKUP : 'lookup' ; LOOKUPFLAG : 'lookupflag' ; NOTDEF : '.notdef' ; RIGHT_TO_LEFT : 'RightToLeft' ; IGNORE_BASE_GLYPHS : 'IgnoreBaseGlyphs' ; IGNORE_LIGATURES : 'IgnoreLigatures' ; IGNORE_MARKS : 'IgnoreMarks' ; USE_MARK_FILTERING_SET : 'UseMarkFilteringSet' ; MARK_ATTACHMENT_TYPE : 'MarkAttachmentType' ; ANON : 'anon' ; ANON_v : 'anonymous' ; EXCLUDE_DFLT : 'excludeDFLT' ; INCLUDE_DFLT : 'includeDFLT' ; EXCLUDE_dflt : 'exclude_dflt' ; INCLUDE_dflt : 'include_dflt' ; USE_EXTENSION : 'useExtension' ; BEGINVALUE : '<' ; ENDVALUE : '>' ; ENUMERATE : 'enumerate' ; ENUMERATE_v : 'enum' ; EXCEPT : 'except' ; IGNORE : 'ignore' ; SUBSTITUTE : 'substitute' ; SUBSTITUTE_v : 'sub' ; REVERSE : 'reversesub' ; REVERSE_v : 'rsub' ; BY : 'by' ; FROM : 'from' ; POSITION : 'position' ; POSITION_v : 'pos'; PARAMETERS : 'parameters' ; FEATURE_NAMES : 'featureNames' ; CV_PARAMETERS : 'cvParameters' ; CV_UI_LABEL : 'FeatUILabelNameID' ; CV_TOOLTIP : 'FeatUITooltipTextNameID' ; CV_SAMPLE_TEXT : 'SampleTextNameID' ; CV_PARAM_LABEL : 'ParamUILabelNameID' ; CV_CHARACTER : 'Character' ; SIZEMENUNAME : 'sizemenuname' ; CONTOURPOINT : 'contourpoint' ; ANCHOR : 'anchor' ; ANCHOR_DEF : 'anchorDef' ; VALUE_RECORD_DEF : 'valueRecordDef' ; +LOCATION_DEF : 'locationDef' ; MARK : 'mark'; MARK_CLASS : 'markClass' ; CURSIVE : 'cursive' ; MARKBASE : 'base' ; MARKLIG : 'ligature' ; MARKLIG_v : 'lig' ; LIG_COMPONENT : 'ligComponent' ; KNULL : 'NULL' ; BASE : 'BASE' ; HA_BTL : 'HorizAxis.BaseTagList' ; VA_BTL : 'VertAxis.BaseTagList' ; HA_BSL : 'HorizAxis.BaseScriptList' ; VA_BSL : 'VertAxis.BaseScriptList' ; GDEF : 'GDEF' ; GLYPH_CLASS_DEF : 'GlyphClassDef' ; ATTACH : 'Attach' ; LIG_CARET_BY_POS : 'LigatureCaretByPos' ; LIG_CARET_BY_IDX : 'LigatureCaretByIndex' ; HEAD : 'head' ; FONT_REVISION : 'FontRevision' ; HHEA : 'hhea' ; ASCENDER : 'Ascender' ; DESCENDER : 'Descender' ; LINE_GAP : 'LineGap' ; CARET_OFFSET : 'CaretOffset' ; +CARET_SLOPE_RISE : 'CaretSlopeRise' ; +CARET_SLOPE_RUN : 'CaretSlopeRun' ; NAME : 'name' ; NAMEID : 'nameid' ; OS_2 : 'OS/2' ; FS_TYPE : 'FSType' ; FS_TYPE_v : 'fsType' ; OS2_LOWER_OP_SIZE : 'LowerOpSize' ; OS2_UPPER_OP_SIZE : 'UpperOpSize' ; PANOSE : 'Panose' ; TYPO_ASCENDER : 'TypoAscender' ; TYPO_DESCENDER : 'TypoDescender' ; TYPO_LINE_GAP : 'TypoLineGap' ; WIN_ASCENT : 'winAscent' ; WIN_DESCENT : 'winDescent' ; X_HEIGHT : 'XHeight' ; CAP_HEIGHT : 'CapHeight' ; +SUBSCRIPT_X_SIZE : 'SubscriptXSize' ; +SUBSCRIPT_X_OFFSET : 'SubscriptXOffset' ; +SUBSCRIPT_Y_SIZE : 'SubscriptYSize' ; +SUBSCRIPT_Y_OFFSET : 'SubscriptYOffset' ; +SUPERSCRIPT_X_SIZE : 'SuperscriptXSize' ; +SUPERSCRIPT_X_OFFSET : 'SuperscriptXOffset' ; +SUPERSCRIPT_Y_SIZE : 'SuperscriptYSize' ; +SUPERSCRIPT_Y_OFFSET : 'SuperscriptYOffset' ; +STRIKEOUT_SIZE : 'StrikeoutSize' ; +STRIKEOUT_POSITION : 'StrikeoutPosition' ; WEIGHT_CLASS : 'WeightClass' ; WIDTH_CLASS : 'WidthClass' ; VENDOR : 'Vendor' ; UNICODE_RANGE : 'UnicodeRange' ; CODE_PAGE_RANGE : 'CodePageRange' ; FAMILY_CLASS : 'FamilyClass' ; STAT : 'STAT' ; ELIDED_FALLBACK_NAME : 'ElidedFallbackName' ; ELIDED_FALLBACK_NAME_ID : 'ElidedFallbackNameID' ; DESIGN_AXIS : 'DesignAxis' ; AXIS_VALUE : 'AxisValue'; FLAG : 'flag' ; LOCATION : 'location'; AXIS_EAVN : 'ElidableAxisValueName'; AXIS_OSFA : 'OlderSiblingFontAttribute'; VHEA : 'vhea' ; VERT_TYPO_ASCENDER : 'VertTypoAscender' ; VERT_TYPO_DESCENDER : 'VertTypoDescender' ; VERT_TYPO_LINE_GAP : 'VertTypoLineGap' ; VMTX : 'vmtx' ; VERT_ORIGIN_Y : 'VertOriginY' ; VERT_ADVANCE_Y : 'VertAdvanceY' ; LCBRACE : '{' ; RCBRACE : '}' ; LBRACKET : '[' ; RBRACKET : ']' ; +LPAREN : '(' ; +RPAREN : ')' ; HYPHEN : '-' ; +PLUS : '+' ; SEMI : ';' ; EQUALS : '=' ; MARKER : '\'' ; COMMA : ',' ; -QUOTE : '"' -> pushMode(String) ; +COLON : ':' ; +STRVAL : '"' ( '\\"' | ~["] )* '"' ; fragment GNST : 'A' .. 'Z' | 'a' .. 'z' | '_' ; fragment LCHR : GNST | '0' .. '9' | '.' ; fragment GCCHR : LCHR | '-' ; +LNAME : '@' GNST LCHR* ; GCLASS : '@' GNST GCCHR* ; +AXISUNIT : 'u' | 'd' | 'n' ; CID : '\\' ( '0' .. '9' )+ ; fragment GNCHR : GCCHR | '+' | '*' | ':' | '~' | '^' | '|' ; ESCGNAME : '\\' GNST GNCHR* ; NAMELABEL : GNST LCHR* ; EXTNAME : GNST GNCHR* ; POINTNUM : '-'? ( '0' .. '9' )+ '.' ( '0' .. '9' )+ ; NUMEXT : '0x' ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' )+ ; NUMOCT : '0' ( '0' .. '7' )+ ; NUM : '-'? ( '1' .. '9' ( '0' .. '9' )* | '0' ) ; -fragment TSTART : '!' | '$' | '%' | '&' | '*' | '+' | '.' | ':' | '?' | - 'A' .. 'Z' | '^' .. 'z' | '|' | '~' ; -fragment TCHR : TSTART | '0' .. '9' | '-' ; -CATCHTAG : TSTART TCHR? ; mode Include; I_WHITESPACE : [ \t\r\n]+ -> skip ; I_RPAREN : '(' -> mode(Ifile) ; mode Ifile; IFILE : ~')'+ ; I_LPAREN : ')' -> popMode ; - -mode String; - -STRVAL : ~'"'* ; -EQUOTE : '"' -> popMode ;
Anonymous block handling
FeatLexerBase.g4
is imported by FeatLexer.g4
, which contains more complex handling for anonymous blocks. The changes to this file have to do with the changes in tag handling in the base token grammar.
/* Copyright 2024 Adobe Systems Incorporated (http://www.adobe.com/). All Rights Reserved. * This software is licensed as OpenSource, under the Apache License, Version 2.0. * This license is available at: http://opensource.org/licenses/Apache-2.0. */ lexer grammar FeatLexer; import FeatLexerBase; @members { std::string anon_tag; /* All the TSTART/TCHR characters are grouped together, so just * look for the string and if its there verify that the characters * on either side are from the appropriate set (in case there are * "extra" characters). */ bool verify_anon(const std::string &line) { auto p = line.find(anon_tag); if ( p == std::string::npos ) return false; --p; if ( ! ( line[p] == ' ' || line[p] == '\t' || line[p] == '}' ) ) return false; p += anon_tag.size() + 1; if ( ! ( line[p] == ' ' || line[p] == '\t' || line[p] == ';' ) ) return false; return true; } } ANON : 'anon' -> pushMode(Anon) ; ANON_v : 'anonymous' -> pushMode(Anon) ; mode Anon; A_WHITESPACE : [ \t\r\n]+ -> skip ; -A_LABEL : TSTART TCHR* { anon_tag = getText(); } ; +A_LABEL : (NAMELABEL | EXTNAME | STRVAL | MARK) { anon_tag = getText(); } ; A_LBRACE : '{' -> mode(AnonContent) ; mode AnonContent; -A_CLOSE : '\r'? '\n}' [ \t]* TSTART TCHR* [ \t]* ';' { verify_anon(getText()) }? -> popMode ; +A_CLOSE : '\r'? '\n}' [ \t]* (NAMELABEL | EXTNAME | STRVAL | MARK) [ \t]* ';' { verify_anon(getText()) }? -> popMode ; A_LINE : '\r'? '\n' ~[\r\n]* ;
The parser
FeatParser.g4
specifies the grammar. The changes here correspond straightforwardly to the changes in the specification. Note that tags with unusual characters must now have quotes around them.
/* Copyright 2024 Adobe Systems Incorporated (http://www.adobe.com/). All Rights Reserved. * This software is licensed as OpenSource, under the Apache License, Version 2.0. * This license is available at: http://opensource.org/licenses/Apache-2.0. */ // ------------------------- Feature file grammar --------------------------- parser grammar FeatParser; options { tokenVocab = FeatLexer; } file: ( topLevelStatement | featureBlock | tableBlock | anonBlock | lookupBlockTopLevel )* EOF ; topLevelStatement: ( include | glyphClassAssign | langsysAssign | mark_statement | anchorDef | valueRecordDef + | locationDef ) SEMI ; include: INCLUDE I_RPAREN IFILE I_LPAREN ; glyphClassAssign: - GCLASS EQUALS glyphClass + gclass EQUALS glyphClass ; langsysAssign: LANGSYS script=tag lang=tag ; mark_statement: - MARK_CLASS ( glyph | glyphClass ) anchor GCLASS + MARK_CLASS ( glyph | glyphClass ) anchor gclass ; anchorDef: - ANCHOR_DEF xval=NUM yval=NUM ( CONTOURPOINT cp=NUM )? name=label + ANCHOR_DEF anchorLiteral name=label ; valueRecordDef: VALUE_RECORD_DEF valueLiteral label ; +locationDef: + LOCATION_DEF locationLiteral LNAME +; + featureBlock: FEATURE starttag=tag USE_EXTENSION? LCBRACE featureStatement+ RCBRACE endtag=tag SEMI ; tableBlock: TABLE ( table_BASE | table_GDEF | table_head | table_hhea | table_vhea | table_name | table_OS_2 | table_STAT | table_vmtx ) ; anonBlock: anontok A_LABEL A_LBRACE A_LINE* A_CLOSE ; lookupBlockTopLevel: LOOKUP startlabel=label USE_EXTENSION? LCBRACE statement+ RCBRACE endlabel=label SEMI ; featureStatement: statement | lookupBlockOrUse | cvParameterBlock ; lookupBlockOrUse: LOOKUP startlabel=label ( USE_EXTENSION? LCBRACE statement+ RCBRACE endlabel=label )? SEMI ; cvParameterBlock: CV_PARAMETERS LCBRACE cvParameterStatement* RCBRACE SEMI ; cvParameterStatement: ( cvParameter | include ) SEMI ; cvParameter: ( CV_UI_LABEL | CV_TOOLTIP | CV_SAMPLE_TEXT | CV_PARAM_LABEL ) LCBRACE nameEntryStatement+ RCBRACE | CV_CHARACTER genNum ; statement: ( featureUse | scriptAssign | langAssign | lookupflagAssign | glyphClassAssign | ignoreSubOrPos | substitute | mark_statement | position | parameters | sizemenuname | featureNames | subtable | include ) SEMI ; featureUse: FEATURE tag ; scriptAssign: SCRIPT tag ; langAssign: LANGUAGE tag ( EXCLUDE_DFLT | INCLUDE_DFLT | EXCLUDE_dflt | INCLUDE_dflt )? ; lookupflagAssign: LOOKUPFLAG ( NUM | lookupflagElement+ ) ; lookupflagElement: RIGHT_TO_LEFT | IGNORE_BASE_GLYPHS | IGNORE_LIGATURES | IGNORE_MARKS | ( MARK_ATTACHMENT_TYPE glyphClass ) | ( USE_MARK_FILTERING_SET glyphClass ) ; ignoreSubOrPos: IGNORE ( subtok | revtok | postok ) lookupPattern ( COMMA lookupPattern )* ; substitute: ( EXCEPT lookupPattern ( COMMA lookupPattern )* )? ( revtok startpat=lookupPattern ( BY ( KNULL | endpat=lookupPattern ) )? | subtok startpat=lookupPattern ( ( BY | FROM ) ( KNULL | endpat=lookupPattern ) )? ) ; position: enumtok? postok startpat=pattern? ( ( valueRecord valuePattern* ) | ( ( LOOKUP label )+ lookupPatternElement* ) | ( CURSIVE cursiveElement endpat=pattern? ) | ( MARKBASE midpat=pattern baseToMarkElement+ endpat=pattern? ) | ( markligtok midpat=pattern ligatureMarkElement+ endpat=pattern? ) | ( MARK midpat=pattern baseToMarkElement+ endpat=pattern? ) ) ; valuePattern: patternElement valueRecord? ; valueRecord: BEGINVALUE valuename=label ENDVALUE | valueLiteral ; valueLiteral: - ( BEGINVALUE NUM NUM NUM NUM ENDVALUE ) | NUM + singleValueLiteral + | ( BEGINVALUE singleValueLiteral singleValueLiteral + singleValueLiteral singleValueLiteral ENDVALUE ) + | ( LPAREN locationMultiValueLiteral+ RPAREN ) +; + +singleValueLiteral: + NUM | parenLocationValue +; + +parenLocationValue: + LPAREN locationValueLiteral+ RPAREN +; + +locationValueLiteral: + (locationSpecifier COLON)? NUM +; + +locationMultiValueLiteral: + (locationSpecifier COLON)? BEGINVALUE NUM NUM NUM NUM ENDVALUE +; + +locationSpecifier: + locationLiteral | LNAME +; + +locationLiteral: + axisLocationLiteral ( COMMA axisLocationLiteral )* +; + +axisLocationLiteral: + tag EQUALS fixedNum ( HYPHEN | PLUS )? AXISUNIT ; cursiveElement: patternElement anchor anchor ; baseToMarkElement: - anchor MARK GCLASS MARKER? + anchor MARK gclass MARKER? ; ligatureMarkElement: - anchor ( MARK GCLASS )? LIG_COMPONENT? MARKER? + anchor ( MARK gclass )? LIG_COMPONENT? MARKER? ; parameters: PARAMETERS fixedNum+ ; sizemenuname: - SIZEMENUNAME ( genNum ( genNum genNum )? )? QUOTE STRVAL EQUOTE + SIZEMENUNAME ( genNum ( genNum genNum )? )? STRVAL ; featureNames: FEATURE_NAMES LCBRACE nameEntryStatement+ RCBRACE ; subtable: SUBTABLE ; table_BASE: BASE LCBRACE baseStatement+ RCBRACE BASE SEMI ; baseStatement: ( axisTags | axisScripts | include ) SEMI ; axisTags: ( HA_BTL | VA_BTL ) tag+ ; axisScripts: ( HA_BSL | VA_BSL ) baseScript ( COMMA baseScript )* ; baseScript: - script=tag db=tag NUM+ + script=tag db=tag singleValueLiteral+ ; table_GDEF: GDEF LCBRACE gdefStatement+ RCBRACE GDEF SEMI ; gdefStatement: ( gdefGlyphClass | gdefAttach | gdefLigCaretPos | gdefLigCaretIndex | include ) SEMI ; gdefGlyphClass: GLYPH_CLASS_DEF glyphClassOptional COMMA glyphClassOptional COMMA glyphClassOptional COMMA glyphClassOptional ; gdefAttach: ATTACH lookupPattern NUM+ ; gdefLigCaretPos: - LIG_CARET_BY_POS lookupPattern NUM+ + LIG_CARET_BY_POS lookupPattern singleValueLiteral+ ; gdefLigCaretIndex: LIG_CARET_BY_IDX lookupPattern NUM+ ; table_head: HEAD LCBRACE headStatement+ RCBRACE HEAD SEMI ; headStatement: ( head | include ) SEMI ; head: FONT_REVISION POINTNUM ; table_hhea: HHEA LCBRACE hheaStatement* RCBRACE HHEA SEMI ; hheaStatement: ( hhea | include ) SEMI ; hhea: - ( CARET_OFFSET | ASCENDER | DESCENDER | LINE_GAP ) NUM + ( ASCENDER | DESCENDER | LINE_GAP ) NUM + | ( CARET_OFFSET | CARET_SLOPE_RISE | CARET_SLOPE_RUN ) singleValueLiteral ; table_vhea: VHEA LCBRACE vheaStatement* RCBRACE VHEA SEMI ; vheaStatement: ( vhea | include ) SEMI ; vhea: - ( VERT_TYPO_ASCENDER | VERT_TYPO_DESCENDER | VERT_TYPO_LINE_GAP ) NUM + ( VERT_TYPO_ASCENDER | VERT_TYPO_DESCENDER | VERT_TYPO_LINE_GAP + | CARET_OFFSET | CARET_SLOPE_RISE | CARET_SLOPE_RUN ) singleValueLiteral ; table_name: NAME LCBRACE nameStatement+ RCBRACE NAME SEMI ; nameStatement: ( nameID | include ) SEMI ; nameID: - NAMEID id=genNum ( plat=genNum ( spec=genNum lang=genNum )? )? QUOTE STRVAL EQUOTE + NAMEID id=genNum ( plat=genNum ( spec=genNum lang=genNum )? )? STRVAL ; table_OS_2: OS_2 LCBRACE os_2Statement+ RCBRACE OS_2 SEMI ; os_2Statement: ( os_2 | include ) SEMI ; os_2: ( TYPO_ASCENDER | TYPO_DESCENDER | TYPO_LINE_GAP - | WIN_ASCENT | WIN_DESCENT | X_HEIGHT | CAP_HEIGHT ) num=NUM + | WIN_ASCENT | WIN_DESCENT | X_HEIGHT | CAP_HEIGHT + | SUBSCRIPT_X_SIZE | SUBSCRIPT_X_OFFSET + | SUBSCRIPT_Y_SIZE | SUBSCRIPT_Y_OFFSET + | SUPERSCRIPT_X_SIZE | SUPERSCRIPT_X_OFFSET + | SUPERSCRIPT_Y_SIZE | SUPERSCRIPT_Y_OFFSET + | STRIKEOUT_SIZE | STRIKEOUT_POSITION ) num=singleValueLiteral | ( FS_TYPE | FS_TYPE_v | WEIGHT_CLASS | WIDTH_CLASS | OS2_LOWER_OP_SIZE | OS2_UPPER_OP_SIZE ) unum=NUM | FAMILY_CLASS gnum=genNum - | VENDOR QUOTE STRVAL EQUOTE + | VENDOR STRVAL | PANOSE NUM NUM NUM NUM NUM NUM NUM NUM NUM NUM | ( UNICODE_RANGE | CODE_PAGE_RANGE ) NUM+ ; - table_STAT: STAT LCBRACE statStatement+ RCBRACE STAT SEMI ; statStatement: ( designAxis | axisValue | elidedFallbackName | elidedFallbackNameID | include ) SEMI ; designAxis: DESIGN_AXIS tag NUM LCBRACE nameEntryStatement+ RCBRACE ; axisValue: AXIS_VALUE LCBRACE axisValueStatement+ RCBRACE ; axisValueStatement: ( nameEntry | axisValueLocation | axisValueFlags | include ) SEMI ; axisValueLocation: LOCATION tag fixedNum ( fixedNum fixedNum? )? ; axisValueFlags: FLAG ( AXIS_OSFA | AXIS_EAVN )+ ; elidedFallbackName: ELIDED_FALLBACK_NAME LCBRACE nameEntryStatement+ RCBRACE ; nameEntryStatement: ( nameEntry | include ) SEMI ; elidedFallbackNameID: ELIDED_FALLBACK_NAME_ID genNum ; nameEntry: - NAME ( genNum ( genNum genNum )? )? QUOTE STRVAL EQUOTE + NAME ( genNum ( genNum genNum )? )? STRVAL ; table_vmtx: VMTX LCBRACE vmtxStatement+ RCBRACE VMTX SEMI ; vmtxStatement: ( vmtx | include ) SEMI ; vmtx: - ( VERT_ORIGIN_Y | VERT_ADVANCE_Y ) glyph NUM + ( VERT_ORIGIN_Y | VERT_ADVANCE_Y ) glyph singleValueLiteral ; anchor: BEGINVALUE ANCHOR - ( ( xval=NUM yval=NUM ( CONTOURPOINT cp=NUM )? ) + ( anchorLiteral | KNULL | name=label ) ENDVALUE ; +anchorLiteral: + anchorLiteralXY ( CONTOURPOINT cp=NUM )? +; + +anchorLiteralXY: + (xval=singleValueLiteral yval=singleValueLiteral) + | (LPAREN anchorMultiValueLiteral+ RPAREN) +; + +anchorMultiValueLiteral: + (locationSpecifier COLON)? BEGINVALUE NUM NUM ENDVALUE +; + lookupPattern: lookupPatternElement+ ; lookupPatternElement: patternElement ( LOOKUP label )* ; pattern: patternElement+ ; patternElement: ( glyphClass | glyph ) MARKER? ; glyphClassOptional: glyphClass? ; glyphClass: - GCLASS | gcLiteral + gclass | gcLiteral ; gcLiteral: LBRACKET gcLiteralElement+ RBRACKET ; gcLiteralElement: startg=glyph ( HYPHEN endg=glyph )? - | GCLASS + | gclass +; + +gclass: + LNAME | GCLASS ; glyph: glyphName | CID ; glyphName: - ESCGNAME | NAMELABEL | EXTNAME | NOTDEF + ESCGNAME | NAMELABEL | EXTNAME | AXISUNIT | NOTDEF ; label: - NAMELABEL | MARK + NAMELABEL | MARK | AXISUNIT ; tag: - NAMELABEL | EXTNAME | CATCHTAG | MARK // MARK included for "feature mark" + NAMELABEL | EXTNAME | STRVAL | MARK // MARK included for "feature mark" ; fixedNum: POINTNUM | NUM ; genNum: NUM | NUMOCT | NUMEXT ; // These are for an include directive in a block with statements featureFile: featureStatement* EOF ; statementFile: statement* EOF ; cvStatementFile: cvParameterStatement* EOF ; baseFile: baseStatement* EOF ; headFile: headStatement* EOF ; hheaFile: hheaStatement* EOF ; vheaFile: vheaStatement* EOF ; gdefFile: gdefStatement* EOF ; nameFile: nameStatement* EOF ; vmtxFile: vmtxStatement* EOF ; os_2File: os_2Statement* EOF ; statFile: statStatement* EOF ; axisValueFile: axisValueStatement* EOF ; nameEntryFile: nameEntryStatement* EOF ; /* These tokens are defined this way because they slightly improves * Antlr 4's default error reporting. If we wind up overloading the * class with the token literals at the C++ level I will devolve these * back into the Lexer grammar. */ subtok: SUBSTITUTE | SUBSTITUTE_v ; revtok: REVERSE | REVERSE_v ; anontok: ANON | ANON_v ; enumtok: ENUMERATE | ENUMERATE_v ; postok: POSITION | POSITION_v ; markligtok: MARKLIG | MARKLIG_v ;