summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--pygments/lexers/_mapping.py3
-rw-r--r--pygments/lexers/compiled.py682
-rw-r--r--tests/examplefiles/example.i6t32
-rw-r--r--tests/examplefiles/example.i7x45
-rw-r--r--tests/examplefiles/example.inf370
-rw-r--r--tests/examplefiles/example.ni57
7 files changed, 1189 insertions, 1 deletions
diff --git a/AUTHORS b/AUTHORS
index a9a8a2d4..ae77e7fb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -27,6 +27,7 @@ Other contributors, listed alphabetically, are:
* Pierre Bourdon -- bugfixes
* Hiram Chirino -- Scaml and Jade lexers
* Ian Cooper -- VGL lexer
+* David Corbett -- Inform lexers
* Leaf Corcoran -- MoonScript lexer
* Christopher Creutzig -- MuPAD lexer
* Daniël W. Crompton - Pike lexer
diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py
index 68ca5fd6..594040a5 100644
--- a/pygments/lexers/_mapping.py
+++ b/pygments/lexers/_mapping.py
@@ -146,6 +146,9 @@ LEXERS = {
'IDLLexer': ('pygments.lexers.math', 'IDL', ('idl',), ('*.pro',), ('text/idl',)),
'IdrisLexer': ('pygments.lexers.functional', 'Idris', ('idris', 'idr'), ('*.idr',), ('text/x-idris',)),
'IgorLexer': ('pygments.lexers.math', 'Igor', ('igor', 'igorpro'), ('*.ipf',), ('text/ipf',)),
+ 'Inform6Lexer': ('pygments.lexers.compiled', 'Inform 6', ('inform6', 'i6'), ('*.inf', '*.h'), ()),
+ 'Inform6TemplateLexer': ('pygments.lexers.compiled', 'Inform 6 template', ('i6t',), ('*.i6t',), ()),
+ 'Inform7Lexer': ('pygments.lexers.compiled', 'Inform 7', ('inform7', 'i7'), ('*.ni', '*.i7x'), ()),
'IniLexer': ('pygments.lexers.text', 'INI', ('ini', 'cfg', 'dosini'), ('*.ini', '*.cfg'), ('text/x-ini',)),
'IoLexer': ('pygments.lexers.agile', 'Io', ('io',), ('*.io',), ('text/x-iosrc',)),
'IokeLexer': ('pygments.lexers.jvm', 'Ioke', ('ioke', 'ik'), ('*.ik',), ('text/x-iokesrc',)),
diff --git a/pygments/lexers/compiled.py b/pygments/lexers/compiled.py
index 22d3cd67..2a95c374 100644
--- a/pygments/lexers/compiled.py
+++ b/pygments/lexers/compiled.py
@@ -31,7 +31,8 @@ __all__ = ['CLexer', 'CppLexer', 'DLexer', 'DelphiLexer', 'ECLexer',
'FantomLexer', 'RustLexer', 'CudaLexer', 'MonkeyLexer', 'SwigLexer',
'DylanLidLexer', 'DylanConsoleLexer', 'CobolLexer',
'CobolFreeformatLexer', 'LogosLexer', 'ClayLexer', 'PikeLexer',
- 'ChapelLexer', 'EiffelLexer']
+ 'ChapelLexer', 'EiffelLexer', 'Inform6Lexer', 'Inform7Lexer',
+ 'Inform6TemplateLexer']
class CFamilyLexer(RegexLexer):
@@ -3951,3 +3952,682 @@ class EiffelLexer(RegexLexer):
(r'[0-9]+', Number.Integer),
],
}
+
+
+class Inform6Lexer(RegexLexer):
+ """
+ For `Inform 6 <http://inform-fiction.org/>`_ source code.
+ """
+
+ name = 'Inform 6'
+ aliases = ['inform6', 'i6']
+ filenames = ['*.inf', '*.h']
+
+ flags = re.MULTILINE | re.DOTALL | re.UNICODE
+
+ _name = r'[a-zA-Z_][a-zA-Z_0-9]*'
+
+ # Inform 7 maps these four character classes to their ASCII
+ # equivalents. To support Inform 6 inclusions within Inform 7,
+ # Inform6Lexer maps them too.
+ _dash = ur'\-\u2010-\u2014'
+ _dquote = ur'"\u201c\u201d'
+ _squote = ur"'\u2018\u2019"
+ _newline = ur'\n\u0085\u2028\u2029'
+
+ tokens = {
+ 'root': [
+ (r'(\A(!%%[^%s]*[%s])+)?' % (_newline, _newline), Comment.Preproc,
+ 'directive')
+ ],
+ '_whitespace': [
+ (r'\s+', Text),
+ (r'![^%s]*' % _newline, Comment.Single)
+ ],
+ 'default': [
+ include('_whitespace'),
+ (r'\[', Punctuation, 'many-values'), # Array initialization
+ (r':|(?=;)', Punctuation, '#pop'),
+ (r'<', Punctuation), # Second angle bracket in an action statement
+ (r'', Text, ('expression', '_expression'))
+ ],
+
+ # Expressions
+ '_expression': [
+ include('_whitespace'),
+ (r'(?=sp\b)', Text, '#pop'),
+ (r'(?=[%s%s$0-9#a-zA-Z_])' % (_dquote, _squote), Text,
+ ('#pop', 'value')),
+ (r'\+\+|[%s]{1,2}(?!>)|~~?' % _dash, Operator),
+ (r'(?=[()\[%s,?@{:;])' % _dash, Text, '#pop')
+ ],
+ 'expression': [
+ include('_whitespace'),
+ (r'\(', Punctuation, ('expression', '_expression')),
+ (r'\)', Punctuation, '#pop'),
+ (r'\[', Punctuation, ('#pop', 'statements', 'locals')),
+ (r'>(?=(\s+|(![^%s]*))*[>;])' % _newline, Punctuation),
+ (r'\+\+|[%s]{2}(?!>)' % _dash, Operator),
+ (r',', Punctuation, '_expression'),
+ (r'&&?|\|\|?|[=~><]?=|[%s]{1,2}>?|\.\.?[&#]?|::|[<>+*/%%]' % _dash,
+ Operator, '_expression'),
+ (r'(has|hasnt|in|notin|ofclass|or|provides)\b', Operator.Word,
+ '_expression'),
+ (r'(from|near|to)\b', Keyword, '_expression'),
+ (r'sp\b', Name),
+ (r'\?~?', Name.Label, 'label?'),
+ (r'[@{]', Error),
+ (r'', Text, '#pop')
+ ],
+ '_assembly-expression': [
+ (r'\(', Punctuation, ('#push', '_expression')),
+ (r'[\[\]]', Punctuation),
+ (r'[%s]>' % _dash, Punctuation, '_expression'),
+ (r'sp\b', Keyword.Pseudo),
+ (r';', Punctuation, '#pop:3'),
+ include('expression')
+ ],
+ '_for-expression': [
+ (r'\)', Punctuation, '#pop:2'),
+ (r':', Punctuation, '#pop'),
+ include('expression')
+ ],
+ '_list-expression': [
+ (r',', Punctuation, '#pop'),
+ include('expression')
+ ],
+ '_object-expression': [
+ (r'has\b', Keyword.Declaration, '#pop'),
+ include('_list-expression')
+ ],
+
+ # Values
+ 'value': [
+ include('_whitespace'),
+ # Strings
+ (r'[%s][^@][%s]' % (_squote, _squote), String.Char, '#pop'),
+ (r'([%s])(@{[0-9a-fA-F]{1,4}})([%s])' % (_squote, _squote),
+ bygroups(String.Char, String.Escape, String.Char), '#pop'),
+ (r'([%s])(@..)([%s])' % (_squote, _squote),
+ bygroups(String.Char, String.Escape, String.Char), '#pop'),
+ (r'[%s]' % _squote, String.Single, ('#pop', 'dictionary-word')),
+ (r'[%s]' % _dquote, String.Double, ('#pop', 'string')),
+ # Numbers
+ (r'\$[+%s][0-9]*\.?[0-9]*([eE][+%s]?[0-9]+)?' % (_dash, _dash),
+ Number.Float, '#pop'),
+ (r'\$[0-9a-fA-F]+', Number.Hex, '#pop'),
+ (r'\$\$[01]+', Number, '#pop'), # Binary
+ (r'[0-9]+', Number.Integer, '#pop'),
+ # Values prefixed by hashes
+ (r'(##|#a\$)(%s)' % _name, bygroups(Operator, Name), '#pop'),
+ (r'(#g\$)(%s)' % _name,
+ bygroups(Operator, Name.Variable.Global), '#pop'),
+ (r'#[nw]\$', Operator, ('#pop', 'obsolete-dictionary-word')),
+ (r'(#r\$)(%s)' % _name, bygroups(Operator, Name.Function), '#pop'),
+ (r'#', Name.Builtin, ('#pop', 'system-constant')),
+ # System functions
+ (r'(child|children|elder|eldest|glk|indirect|metaclass|parent|'
+ r'random|sibling|younger|youngest)\b', Name.Builtin, '#pop'),
+ # Metaclasses
+ (r'(?i)(Class|Object|Routine|String)\b', Name.Builtin, '#pop'),
+ # Veneer routines
+ (r'(?i)(Box__Routine|CA__Pr|CDefArt|CInDefArt|Cl__Ms|'
+ r'Copy__Primitive|CP__Tab|DA__Pr|DB__Pr|DefArt|Dynam__String|'
+ r'EnglishNumber|Glk__Wrap|IA__Pr|IB__Pr|InDefArt|Main__|'
+ r'Meta__class|OB__Move|OB__Remove|OC__Cl|OP__Pr|Print__Addr|'
+ r'Print__PName|PrintShortName|RA__Pr|RA__Sc|RL__Pr|R_Process|'
+ r'RT__ChG|RT__ChGt|RT__ChLDB|RT__ChLDW|RT__ChPR|RT__ChPrintA|'
+ r'RT__ChPrintC|RT__ChPrintO|RT__ChPrintS|RT__ChPS|RT__ChR|'
+ r'RT__ChSTB|RT__ChSTW|RT__ChT|RT__Err|RT__TrPS|RV__Pr|'
+ r'Symb__Tab|Unsigned__Compare|WV__Pr|Z__Region)\b', Name.Builtin,
+ '#pop'),
+ # Other built-in symbols
+ (r'(?i)(call|copy|create|DEBUG|destroy|DICT_CHAR_SIZE|'
+ r'DICT_ENTRY_BYTES|DICT_IS_UNICODE|DICT_WORD_SIZE|false|'
+ r'FLOAT_INFINITY|FLOAT_NAN|FLOAT_NINFINITY|Grammar__Version|'
+ r'INDIV_PROP_START|INFIX|infix__watching|MODULE_MODE|name|'
+ r'nothing|NUM_ATTR_BYTES|print|print_to_array|recreate|remaining|'
+ r'self|sender|STRICT_MODE|sw__var|sys__glob0|sys__glob1|'
+ r'sys__glob2|sys_statusline_flag|TARGET_GLULX|TARGET_ZCODE|'
+ r'temp__global2|temp__global3|temp__global4|temp_global|true|'
+ r'USE_MODULES|WORDSIZE)\b', Name.Builtin, '#pop'),
+ # Other values
+ (_name, Name, '#pop')
+ ],
+ # Strings
+ 'dictionary-word': [
+ (r'[~^]+', String.Escape),
+ (r'[^~^\\@({%s]+' % _squote, String.Single),
+ (r'[({]', String.Single),
+ (r'@{[0-9a-fA-F]{,4}}', String.Escape),
+ (r'@..', String.Escape),
+ (r'[%s]' % _squote, String.Single, '#pop')
+ ],
+ 'string': [
+ (r'[~^]+', String.Escape),
+ (r'[^~^\\@({%s]+' % _dquote, String.Double),
+ (r'[({]', String.Double),
+ (r'\\', String.Escape),
+ (r'@(\\\s*[%s]\s*)*@((\\\s*[%s]\s*)*[0-9])*' %
+ (_newline, _newline), String.Escape),
+ (r'@(\\\s*[%s]\s*)*{((\\\s*[%s]\s*)*[0-9a-fA-F]){,4}'
+ r'(\\\s*[%s]\s*)*}' % (_newline, _newline, _newline),
+ String.Escape),
+ (r'@(\\\s*[%s]\s*)*.(\\\s*[%s]\s*)*.' % (_newline, _newline),
+ String.Escape),
+ (r'[%s]' % _dquote, String.Double, '#pop')
+ ],
+ 'plain-string': [
+ (r'[^~^\\({\[\]%s]+' % _dquote, String.Double),
+ (r'[~^({\[\]]', String.Double),
+ (r'\\', String.Escape),
+ (r'[%s]' % _dquote, String.Double, '#pop')
+ ],
+ # Names
+ '_constant': [
+ include('_whitespace'),
+ (_name, Name.Constant, '#pop'),
+ include('value')
+ ],
+ '_global': [
+ include('_whitespace'),
+ (_name, Name.Variable.Global, '#pop'),
+ include('value')
+ ],
+ 'label?': [
+ include('_whitespace'),
+ (r'(%s)?' % _name, Name.Label, '#pop')
+ ],
+ 'variable?': [
+ include('_whitespace'),
+ (r'(%s)?' % _name, Name.Variable, '#pop')
+ ],
+ # Values after hashes
+ 'obsolete-dictionary-word': [
+ (r'\S[a-zA-Z_0-9]*', String.Other, '#pop')
+ ],
+ 'system-constant': [
+ include('_whitespace'),
+ (_name, Name.Builtin, '#pop')
+ ],
+
+ # Directives
+ 'directive': [
+ include('_whitespace'),
+ (r'#', Punctuation),
+ (r';', Punctuation, '#pop'),
+ (r'\[', Punctuation,
+ ('default', 'statements', 'locals', 'routine-name?')),
+ (r'(?i)(abbreviate|endif|dictionary|ifdef|iffalse|ifndef|ifnot|'
+ r'iftrue|ifv3|ifv5|release|serial|switches|system_file|version)'
+ r'\b', Keyword, 'default'),
+ (r'(?i)(array|global)\b', Keyword,
+ ('default', 'directive-keyword?', '_global')),
+ (r'(?i)attribute\b', Keyword, ('default', 'alias?', '_constant')),
+ (r'(?i)class\b', Keyword,
+ ('object-body', 'duplicates', 'class-name')),
+ (r'(?i)(constant|default)\b', Keyword,
+ ('default', 'expression', '_constant')),
+ (r'(?i)(end\b)(.*)', bygroups(Keyword, Text)),
+ (r'(?i)(extend|verb)\b', Keyword, 'grammar'),
+ (r'(?i)fake_action\b', Keyword, ('default', '_constant')),
+ (r'(?i)import\b', Keyword, 'manifest'),
+ (r'(?i)(include|link)\b', Keyword,
+ ('default', 'before-plain-string')),
+ (r'(?i)(lowstring|undef)\b', Keyword, ('default', '_constant')),
+ (r'(?i)message\b', Keyword, ('default', 'diagnostic')),
+ (r'(?i)(nearby|object)\b', Keyword,
+ ('object-body', '_object-head')),
+ (r'(?i)property\b', Keyword,
+ ('default', 'alias?', '_constant', 'property-keyword*')),
+ (r'(?i)replace\b', Keyword,
+ ('default', 'routine-name?', 'routine-name?')),
+ (r'(?i)statusline\b', Keyword, ('default', 'directive-keyword?')),
+ (r'(?i)stub\b', Keyword, ('default', 'routine-name?')),
+ (r'(?i)trace\b', Keyword,
+ ('default', 'trace-keyword?', 'trace-keyword?')),
+ (r'(?i)zcharacter\b', Keyword,
+ ('default', 'directive-keyword?', 'directive-keyword?')),
+ (_name, Name.Class, ('object-body', '_object-head'))
+ ],
+ # [, Replace, Stub
+ 'routine-name?': [
+ include('_whitespace'),
+ (r'(%s)?' % _name, Name.Function, '#pop')
+ ],
+ 'locals': [
+ include('_whitespace'),
+ (r';', Punctuation, '#pop'),
+ (r'\*', Punctuation),
+ (_name, Name.Variable)
+ ],
+ # Array
+ 'many-values': [
+ include('_whitespace'),
+ (r';', Punctuation),
+ (r'\]', Punctuation, '#pop'),
+ (r':', Error),
+ (r'', Text, ('expression', '_expression'))
+ ],
+ # Attribute, Property
+ 'alias?': [
+ include('_whitespace'),
+ (r'alias\b', Keyword, ('#pop', '_constant')),
+ (r'', Text, '#pop')
+ ],
+ # Class, Object, Nearby
+ 'class-name': [
+ include('_whitespace'),
+ (r'(?=[,;]|(class|has|private|with)\b)', Text, '#pop'),
+ (_name, Name.Class, '#pop')
+ ],
+ 'duplicates': [
+ include('_whitespace'),
+ (r'\(', Punctuation, ('#pop', 'expression', '_expression')),
+ (r'', Text, '#pop')
+ ],
+ '_object-head': [
+ (r'[%s]>' % _dash, Punctuation),
+ (r'(class|has|private|with)\b', Keyword.Declaration, '#pop'),
+ include('_global')
+ ],
+ 'object-body': [
+ include('_whitespace'),
+ (r';', Punctuation, '#pop:2'),
+ (r',', Punctuation),
+ (r'class\b', Keyword.Declaration, 'class-segment'),
+ (r'(has|private|with)\b', Keyword.Declaration),
+ (r':', Error),
+ (r'', Text, ('_object-expression', '_expression'))
+ ],
+ 'class-segment': [
+ include('_whitespace'),
+ (r'(?=[,;]|(class|has|private|with)\b)', Text, '#pop'),
+ (_name, Name.Class),
+ (r'', Text, 'value')
+ ],
+ # Extend, Verb
+ 'grammar': [
+ include('_whitespace'),
+ (r'=', Punctuation, ('#pop', 'default')),
+ (r'\*', Punctuation, ('#pop', 'grammar-line')),
+ (r'', Text, '_directive-keyword')
+ ],
+ 'grammar-line': [
+ include('_whitespace'),
+ (r';', Punctuation, '#pop'),
+ (r'[/*]', Punctuation),
+ (r'[%s]>' % _dash, Punctuation, 'value'),
+ (r'(noun|scope)\b', Keyword, '=routine'),
+ (r'', Text, '_directive-keyword')
+ ],
+ '=routine': [
+ include('_whitespace'),
+ (r'=', Punctuation, 'routine-name?'),
+ (r'', Text, '#pop')
+ ],
+ # Import
+ 'manifest': [
+ include('_whitespace'),
+ (r';', Punctuation, '#pop'),
+ (r',', Punctuation),
+ (r'(?i)(global\b)?', Keyword, '_global')
+ ],
+ # Include, Link, Message
+ 'diagnostic': [
+ include('_whitespace'),
+ (r'[%s]' % _dquote, String.Double, ('#pop', 'message-string')),
+ (r'', Text, ('#pop', 'before-plain-string', 'directive-keyword?'))
+ ],
+ 'before-plain-string': [
+ include('_whitespace'),
+ (r'[%s]' % _dquote, String.Double, ('#pop', 'plain-string'))
+ ],
+ 'message-string': [
+ (r'[~^]+', String.Escape),
+ include('plain-string')
+ ],
+
+ # Keywords used in directives
+ '_directive-keyword!': [
+ include('_whitespace'),
+ (r'(additive|alias|buffer|class|creature|data|error|fatalerror|'
+ r'first|has|held|initial|initstr|last|long|meta|multi|'
+ r'multiexcept|multiheld|multiinside|noun|number|only|private|'
+ r'replace|reverse|scope|score|special|string|table|terminating|'
+ r'time|topic|warning|with)\b', Keyword, '#pop'),
+ (r'[%s]{1,2}>|[+=]' % _dash, Punctuation, '#pop')
+ ],
+ '_directive-keyword': [
+ include('_directive-keyword!'),
+ include('value')
+ ],
+ 'directive-keyword?': [
+ include('_directive-keyword!'),
+ (r'', Text, '#pop')
+ ],
+ 'property-keyword*': [
+ include('_whitespace'),
+ (r'(additive|long)\b', Keyword),
+ (r'', Text, '#pop')
+ ],
+ 'trace-keyword?': [
+ include('_whitespace'),
+ (r'(assembly|dictionary|expressions|lines|linker|objects|off|on|'
+ r'symbols|tokens|verbs)\b', Keyword, '#pop'),
+ (r'', Text, '#pop')
+ ],
+
+ # Statements
+ 'statements': [
+ include('_whitespace'),
+ (r'\]', Punctuation, '#pop'),
+ (r'[;{}]', Punctuation),
+ (r'(box|break|continue|default|give|inversion|move|new_line|quit|'
+ r'read|remove|return|rfalse|rtrue|spaces|string|until)\b',
+ Keyword, 'default'),
+ (r'(do|else)\b', Keyword),
+ (r'(font|style)\b', Keyword,
+ ('default', 'miscellaneous-keyword?')),
+ (r'for\b', Keyword, ('for', '(?')),
+ (r'(if|switch|while)', Keyword,
+ ('expression', '_expression', '(?')),
+ (r'(jump|save|restore)\b', Keyword, ('default', 'label?')),
+ (r'objectloop\b', Keyword, ('expression', 'variable?', '(?')),
+ (r'print(_ret)?\b|(?=[%s])' % _dquote, Keyword, 'print-list'),
+ (r'\.', Name.Label, 'label?'),
+ (r'@', Keyword, 'opcode'),
+ (r'#(?![agrnw]\$|#)', Punctuation, 'directive'),
+ (r'<', Punctuation, 'default'),
+ (r'', Text, 'default')
+ ],
+ 'miscellaneous-keyword?': [
+ include('_whitespace'),
+ (r'(bold|fixed|from|near|off|on|reverse|roman|to|underline)\b',
+ Keyword, '#pop'),
+ (r'(a|A|an|address|char|name|number|object|property|string|the|'
+ r'The)\b(?=(\s+|(![^%s]*))*\))' % _newline, Keyword.Pseudo,
+ '#pop'),
+ (r'%s(?=(\s+|(![^%s]*))*\))' % (_name, _newline), Name.Function,
+ '#pop'),
+ (r'', Text, '#pop')
+ ],
+ '(?': [
+ include('_whitespace'),
+ (r'\(?', Punctuation, '#pop')
+ ],
+ 'for': [
+ include('_whitespace'),
+ (r';?', Punctuation, ('_for-expression', '_expression'))
+ ],
+ 'print-list': [
+ include('_whitespace'),
+ (r';', Punctuation, '#pop'),
+ (r':', Error),
+ (r'', Text,
+ ('_list-expression', '_expression', '_list-expression', 'form'))
+ ],
+ 'form': [
+ include('_whitespace'),
+ (r'\(', Punctuation, ('#pop', 'miscellaneous-keyword?')),
+ (r'', Text, '#pop')
+ ],
+
+ # Assembly
+ 'opcode': [
+ include('_whitespace'),
+ (r'[%s]' % _dquote, String.Double, ('operands', 'plain-string')),
+ (_name, Keyword, 'operands')
+ ],
+ 'operands': [
+ (r':', Error),
+ (r'', Text, ('_assembly-expression', '_expression'))
+ ]
+ }
+
+ def get_tokens_unprocessed(self, text):
+ # 'in' is either a keyword or an operator.
+ # If the token two tokens after 'in' is ')', 'in' is a keyword:
+ # objectloop(a in b)
+ # Otherwise, it is an operator:
+ # objectloop(a in b && true)
+ objectloop_queue = []
+ objectloop_token_count = -1
+ previous_token = None
+ for index, token, value in RegexLexer.get_tokens_unprocessed(self,
+ text):
+ if previous_token is Name.Variable and value == 'in':
+ objectloop_queue = [[index, token, value]]
+ objectloop_token_count = 2
+ elif objectloop_token_count > 0:
+ if token not in Comment and token not in Text:
+ objectloop_token_count -= 1
+ objectloop_queue.append((index, token, value))
+ else:
+ if objectloop_token_count == 0:
+ if objectloop_queue[-1][2] == ')':
+ objectloop_queue[0][1] = Keyword
+ while objectloop_queue:
+ yield objectloop_queue.pop(0)
+ objectloop_token_count = -1
+ yield index, token, value
+ if token not in Comment and token not in Text:
+ previous_token = token
+ while objectloop_queue:
+ yield objectloop_queue.pop(0)
+
+
+class Inform7Lexer(RegexLexer):
+ """
+ For `Inform 7 <http://inform7.com/>`_ source code.
+ """
+
+ name = 'Inform 7'
+ aliases = ['inform7', 'i7']
+ filenames = ['*.ni', '*.i7x']
+
+ flags = re.MULTILINE | re.DOTALL | re.UNICODE
+
+ _dash = Inform6Lexer._dash
+ _dquote = Inform6Lexer._dquote
+ _newline = Inform6Lexer._newline
+ _start = r'\A|(?<=[%s])' % _newline
+
+ # There are three variants of Inform 7, differing in how to
+ # interpret at signs and braces in I6T. In top-level inclusions, at
+ # signs in the first column are inweb syntax. In phrase definitions
+ # and use options, tokens in braces are treated as I7. Use options
+ # also interpret "{N}".
+ tokens = {}
+ token_variants = ['+i6t-not-inline', '+i6t-inline', '+i6t-use-option']
+
+ for level in token_variants:
+ tokens[level] = {
+ '+i6-root': list(Inform6Lexer.tokens['root']),
+ '+i6t-root': [ # For Inform6TemplateLexer
+ (r'[^%s]*' % Inform6Lexer._newline, Comment.Preproc,
+ ('directive', '+p'))
+ ],
+ 'root': [
+ (r'(\|?\s)+', Text),
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'[%s]' % _dquote, Generic.Heading,
+ ('+main', '+titling', '+titling-string')),
+ (r'', Text, ('+main', '+heading?'))
+ ],
+ '+titling-string': [
+ (r'[^%s]+' % _dquote, Generic.Heading),
+ (r'[%s]' % _dquote, Generic.Heading, '#pop')
+ ],
+ '+titling': [
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'[^%s.;:|%s]+' % (_dquote, _newline), Generic.Heading),
+ (r'[%s]' % _dquote, Generic.Heading, '+titling-string'),
+ (r'[%s]{2}|(?<=[\s%s])\|[\s%s]' % (_newline, _dquote, _dquote),
+ Text, ('#pop', '+heading?')),
+ (r'[.;:]|(?<=[\s%s])\|' % _dquote, Text, '#pop'),
+ (r'[|%s]' % _newline, Generic.Heading)
+ ],
+ '+main': [
+ (r'(?i)[^%s:a\[(|%s]+' % (_dquote, _newline), Text),
+ (r'[%s]' % _dquote, String.Double, '+text'),
+ (r':', Text, '+phrase-definition'),
+ (r'(?i)\bas\b', Text, '+use-option'),
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'(\([%s])(.*?)([%s]\))' % (_dash, _dash),
+ bygroups(Punctuation,
+ using(this, state=('+i6-root', 'directive'),
+ i6t='+i6t-not-inline'), Punctuation)),
+ (r'(%s|(?<=[\s;:.%s]))\|\s|[%s]{2,}' %
+ (_start, _dquote, _newline), Text, '+heading?'),
+ (r'(?i)[a(|%s]' % _newline, Text)
+ ],
+ '+phrase-definition': [
+ (r'\s+', Text),
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'(\([%s])(.*?)([%s]\))' % (_dash, _dash),
+ bygroups(Punctuation,
+ using(this, state=('+i6-root', 'directive',
+ 'default', 'statements'),
+ i6t='+i6t-inline'), Punctuation), '#pop'),
+ (r'', Text, '#pop')
+ ],
+ '+use-option': [
+ (r'\s+', Text),
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'(\([%s])(.*?)([%s]\))' % (_dash, _dash),
+ bygroups(Punctuation,
+ using(this, state=('+i6-root', 'directive'),
+ i6t='+i6t-use-option'), Punctuation), '#pop'),
+ (r'', Text, '#pop')
+ ],
+ '+comment': [
+ (r'[^\[\]]+', Comment.Multiline),
+ (r'\[', Comment.Multiline, '#push'),
+ (r'\]', Comment.Multiline, '#pop')
+ ],
+ '+text': [
+ (r'[^\[%s]+' % _dquote, String.Double),
+ (r'\[.*?\]', String.Interpol),
+ (r'[%s]' % _dquote, String.Double, '#pop')
+ ],
+ '+heading?': [
+ (r'(\|?\s)+', Text),
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'[%s]{4}\s+' % _dash, Text, '+documentation-heading'),
+ (r'[%s]{1,3}' % _dash, Text),
+ (r'(?i)(volume|book|part|chapter|section)\b[^%s]*' % _newline,
+ Generic.Heading, '#pop'),
+ (r'', Text, '#pop')
+ ],
+ '+documentation-heading': [
+ (r'\s+', Text),
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'(?i)documentation\s+', Text, '+documentation-heading2'),
+ (r'', Text, '#pop')
+ ],
+ '+documentation-heading2': [
+ (r'\s+', Text),
+ (r'\[', Comment.Multiline, '+comment'),
+ (r'[%s]{4}\s' % _dash, Text, '+documentation'),
+ (r'', Text, '#pop:2')
+ ],
+ '+documentation': [
+ (r'(?i)(%s)\s*(chapter|example)\s*:[^%s]*' %
+ (_start, _newline), Generic.Heading),
+ (r'(?i)(%s)\s*section\s*:[^%s]*' % (_start, _newline),
+ Generic.Subheading),
+ (r'((%s)\t.*?[%s])+' % (_start, _newline),
+ using(this, state='+main')),
+ (r'[^%s\[]+|[%s\[]' % (_newline, _newline), Text),
+ (r'\[', Comment.Multiline, '+comment'),
+ ],
+ '+i6t-not-inline': [
+ (r'(%s)@c( .*?)?([%s]|\Z)' % (_start, _newline),
+ Comment.Preproc),
+ (r'(%s)@([%s]+|Purpose:)[^%s]*' % (_start, _dash, _newline),
+ Comment.Preproc),
+ (r'(%s)@p( .*?)?([%s]|\Z)' % (_start, _newline),
+ Generic.Heading, '+p')
+ ],
+ '+i6t-use-option': [
+ include('+i6t-not-inline'),
+ (r'({)(N)(})', bygroups(Punctuation, Text, Punctuation))
+ ],
+ '+i6t-inline': [
+ (r'({)(\S[^}]*)?(})',
+ bygroups(Punctuation, using(this, state='+main'),
+ Punctuation))
+ ],
+ '+i6t': [
+ (r'({[%s])(![^}]*)(}?)' % _dash,
+ bygroups(Punctuation, Comment.Single, Punctuation)),
+ (r'({[%s])(lines)(:)([^}]*)(}?)' % _dash,
+ bygroups(Punctuation, Keyword, Punctuation, Text,
+ Punctuation), '+lines'),
+ (r'({[%s])([^:}]*)(:?)([^}]*)(}?)' % _dash,
+ bygroups(Punctuation, Keyword, Punctuation, Text,
+ Punctuation)),
+ (r'(\(\+)(.*?)(\+\)|\Z)',
+ bygroups(Punctuation, using(this, state='+main'),
+ Punctuation))
+ ],
+ '+p': [
+ (r'[^@]+', Comment.Preproc),
+ (r'(%s)@c( .*?)?([%s]|\Z)' % (_start, _newline),
+ Comment.Preproc, '#pop'),
+ (r'(%s)@([%s]|Purpose:)' % (_start, _dash), Comment.Preproc),
+ (r'(%s)@p( .*?)?([%s]|\Z)' % (_start, _newline),
+ Generic.Heading),
+ (r'@', Comment.Preproc)
+ ],
+ '+lines': [
+ (r'(%s)@c( .*?)?([%s]|\Z)' % (_start, _newline),
+ Comment.Preproc),
+ (r'(%s)@([%s]|Purpose:)[^%s]*' % (_start, _dash, _newline),
+ Comment.Preproc),
+ (r'(%s)@p( .*?)?([%s]|\Z)' % (_start, _newline),
+ Generic.Heading, '+p'),
+ (r'(%s)@[a-zA-Z_0-9]*[ %s]' % (_start, _newline), Keyword),
+ (r'![^%s]*' % _newline, Comment.Single),
+ (r'({)([%s]endlines)(})' % _dash,
+ bygroups(Punctuation, Keyword, Punctuation), '#pop'),
+ (r'[^@!{]+?([%s]|\Z)|.' % _newline, Text)
+ ]
+ }
+ # Inform 7 can include snippets of Inform 6 template language,
+ # so all of Inform6Lexer's states are copied here, with
+ # modifications to account for template syntax. Inform7Lexer's
+ # own states begin with '+' to avoid name conflicts. Some of
+ # Inform6Lexer's states begin with '_': these are not modified.
+ # They deal with template syntax either by including modified
+ # states, or by matching r'' then pushing to modified states.
+ for token in Inform6Lexer.tokens:
+ if token == 'root':
+ continue
+ tokens[level][token] = list(Inform6Lexer.tokens[token])
+ if not token.startswith('_'):
+ tokens[level][token][:0] = [include('+i6t'), include(level)]
+
+ def __init__(self, **options):
+ level = options.get('i6t', '+i6t-not-inline')
+ if level not in self._all_tokens:
+ self._tokens = self.__class__.process_tokendef(level)
+ else:
+ self._tokens = self._all_tokens[level]
+ RegexLexer.__init__(self, **options)
+
+
+class Inform6TemplateLexer(Inform7Lexer):
+ """
+ For `Inform 6 template
+ <http://inform7.com/sources/src/i6template/Woven/index.html>`_ code.
+ """
+
+ name = 'Inform 6 template'
+ aliases = ['i6t']
+ filenames = ['*.i6t']
+
+ def get_tokens_unprocessed(self, text, stack=('+i6t-root',)):
+ return Inform7Lexer.get_tokens_unprocessed(self, text, stack)
+
diff --git a/tests/examplefiles/example.i6t b/tests/examplefiles/example.i6t
new file mode 100644
index 00000000..0f41b425
--- /dev/null
+++ b/tests/examplefiles/example.i6t
@@ -0,0 +1,32 @@
+B/examt: Example Template.
+
+@Purpose: To show the syntax of I6T, specifically the parts relating to the
+inclusion of I7 and at signs in the first column.
+
+@-------------------------------------------------------------------------------
+
+@p Lines.
+
+@c
+{-lines:type}
+! This is a comment.
+{-endlines}
+
+@-This line begins with @-, so it is ignored.
+
+@p Paragraph.
+This is a paragraph.
+@p Another paragraph.
+So
+
+is
+
+this.
+
+@Purpose: This purpose line is ignored.
+
+@c At signs and (+ +).
+[ Foo i;
+print (+score [an I7 value]+), "^";
+@add sp 1 -> i; ! Assembly works even in the first column.
+];
diff --git a/tests/examplefiles/example.i7x b/tests/examplefiles/example.i7x
new file mode 100644
index 00000000..ab94ac69
--- /dev/null
+++ b/tests/examplefiles/example.i7x
@@ -0,0 +1,45 @@
+example by David Corbett begins here.
+
+"Implements testable examples."
+
+An example is a kind of thing. An example can be tested. An example is seldom tested.
+
+example ends here.
+
+----
+[The] documentation [starts here.]
+----
+
+This extension adds examples, which may be tested.
+
+Chapter: Usage
+
+To add an example to the story, we write:
+
+ The foobar is an example.
+
+To interact with it in Inform 6, we write something like:
+
+ To say (E - example): (-
+ print (object) {E};
+ -).
+ [The IDE's documentation viewer does not display the closing -). I don't know how to fix that.]
+
+Section: Testing
+
+We can make an example be tested using:
+
+ now the foobar is tested;
+
+Example: * Exempli Gratia - A simple example.
+
+ *: "Exempli Gratia"
+
+ Include example by David Corbett.
+
+ The Kitchen is a room. The egg is an example, here.
+
+ Before dropping the egg:
+ now the egg is tested.
+
+ Test me with "get egg / drop egg".
diff --git a/tests/examplefiles/example.inf b/tests/examplefiles/example.inf
new file mode 100644
index 00000000..bc163de9
--- /dev/null
+++ b/tests/examplefiles/example.inf
@@ -0,0 +1,370 @@
+!% $SMALL ! This is ICL, not a comment.
+!% -w
+
+!% A comprehensive test of Inform6Lexer.
+
+Switches d2SDq;
+
+Constant Story "Informal Testing";
+Constant Headline "^Not a game.^";!% This is a comment, not ICL.
+
+Release 1;
+Serial "140128";
+Version 5;
+
+Ifndef TARGET_ZCODE;
+Ifndef TARGET_GLULX;
+Ifndef WORDSIZE;
+Default WORDSIZE 2;
+Constant TARGET_ZCODE;
+Endif;
+Endif;
+Endif;
+
+Ifv3; Message "Compiling to version 3"; Endif;
+Ifv5; Message "Not compiling to version 3"; endif;
+ifdef TARGET_ZCODE;
+#IFTRUE (#version_number == 5);
+Message "Compiling to version 5";
+#ENDIF;
+endif ;
+
+Replace CreatureTest;
+
+Include "Parser";
+Include "VerbLib";
+
+# ! A hash is optional at the top level.
+Object kitchen "Kitchen"
+ with description "You are in a kitchen.",
+ arr 1 2 3 4,
+ has light;
+
+#[ Initialise;
+ location = kitchen;
+ print "v"; inversion; "^";
+];
+
+Ifdef VN_1633;
+Replace IsSeeThrough IsSeeThroughOrig;
+[ IsSeeThrough * o;
+ return o hasnt opaque || IsSeeThroughOrig(o);
+];
+Endif;
+
+Abbreviate "test";
+
+Array table buffer 260;
+
+Attribute reversed;
+Attribute opaque alias locked;
+
+Property long additive additive long alias;
+Property long long long wingspan alias alias;
+
+Class Flier with wingspan 5;
+Class Bird(10) has animate class Flier with wingspan 2;
+
+Constant Constant1;
+Constant Constant2 Constant1;
+Constant Constant3 = Constant2;
+Ifdef VN_1633; Undef Constant; Endif;
+
+Ifdef VN_1633;
+Dictionary 'word' 1 2;
+Ifnot;
+Dictionary dict_word "word";
+Endif;
+
+Fake_action NotReal;
+
+Global global1;
+Global global2 = 69105;
+
+Lowstring low_string "low string";
+
+Iftrue false;
+Message error "Uh-oh!^~false~ shouldn't be ~true~.";
+Endif;
+Iffalse true;
+Message fatalerror "Uh-oh!^~true~ shouldn't be ~false~.";
+Endif;
+
+Nearby person "person"
+ with name 'person',
+ description "This person is barely implemented.",
+ life [ * x y z;
+ Ask: print_ret (The) self, " says nothing.";
+ Answer: print (The) self, " didn't say anything.^"; rfalse;
+ ]
+ has has animate transparent;
+
+Object -> -> test_tube "test tube"
+ with name 'test' "tube" 'testtube',
+ has ~openable ~opaque container;
+
+Bird -> pigeon
+ with name 'pigeon',
+ description [;
+ "The pigeon has a wingspan of ", self.&wingspan-->0, " wing units.";
+ ];
+
+Object -> "thimble" with name 'thimble';
+
+Object -> pebble "pebble" with name 'pebble';
+
+Ifdef TARGET_ZCODE; Trace objects; Endif;
+
+Statusline score;
+
+Stub StubR 3;
+
+Ifdef TARGET_ZCODE;
+Zcharacter "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "123456789.,!?_#'0/@{005C}-:()";
+Zcharacter table '@!!' '@<<' '@'A';
+Zcharacter table + '@AE' '@{dc}' '@et' '@:y';
+Ifnot;
+Ifdef TARGET_GLULX;
+Message "Glulx doesn't use ~Zcharacter~.^Oh well."; ! '~' and '^' work here.
+Ifnot;
+Message warning "Uh-oh! ^~^"; ! They don't work in other Messages.
+Endif;
+Endif;
+
+Include "Grammar";
+
+Verb"acquire"'collect'='take';
+
+[ NounFilter; return noun ofclass Bird; ];
+
+[ ScopeFilter obj;
+ switch (scope_stage) {
+ 1: rtrue;
+ 2: objectloop (obj in compass) PlaceInScope(obj);
+ 3: "Nothing is in scope.";
+ }
+];
+
+Verb meta "t" 'test'
+ * 'held' held -> TestHeld
+ * number -> TestNumber
+ * reversed -> TestAttribute
+ * 'creature' creature -> TestCreature
+ * 'multiheld' multiheld -> TestMultiheld
+ * 'm' multiexcept 'into'/"in" noun -> TestMultiexcept
+ * 'm' multiinside 'from' noun -> TestMultiinside
+ * multi -> TestMulti
+ * 'filter'/'f' noun=NounFilter -> TestNounFilter
+ * 'filter'/'f' scope=ScopeFilter -> TestScopeFilter
+ * 'special' special -> TestSpecial
+ * topic -> TestTopic;
+
+Verb 'reverse' 'swap' 'exchange'
+ * held 'for' noun -> reverse
+ * noun 'with' noun -> reverse reverse;
+
+Extend "t" last * noun -> TestNoun;
+
+Extend 't' first * -> Test;
+
+Extend 'wave' replace * -> NewWave;
+
+Extend only 'feel' 'touch' replace * noun -> Feel;
+
+[ TestSub a b o;
+ string 25 low_string;
+ print "Test what?> ";
+ table->0 = 260;
+ parse->0 = 61;
+ #Ifdef TARGET_ZCODE;
+ read buffer parse;
+ #Ifnot; ! TARGET_GLULX
+ KeyboardPrimitive(buffer, parse);
+ #Endif; ! TARGET_
+ switch (parse-->1) {
+ 'save':
+ #Ifdef TARGET_ZCODE;
+ #Ifv3;
+ @save ?saved;
+ #Ifnot;
+ save saved;
+ #Endif;
+ #Endif;
+ print "Saving failed.^";
+ 'restore':
+ #Ifdef TARGET_ZCODE;
+ restore saved;
+ #Endif;
+ print "Restoring failed.^";
+ 'restart':
+ @restart;
+ 'quit', 'q//':
+ quit;
+ return 2; rtrue; rfalse; return;
+ 'print', 'p//':
+ print "Print:^",
+ " (string): ", (string) "xyzzy^",
+ " (number): ", (number) 123, "^",
+ " (char): ", (char) 'x', "^",
+ " (address): ", (address) 'plugh//p', "^",
+ " (The): ", (The) person, "^",
+ " (the): ", (the) person, "^",
+ " (A): ", (A) person, "^",
+ " (a): ", (a) person, "^",
+ " (an): ", (an) person, "^",
+ " (name): ", (name) person, "^",
+ " (object): ", (object) person, "^",
+ " (property): ", (property) alias, "^",
+ " (<routine>): ", (LanguageNumber) 123, "^",
+ " <expression>: ", a * 2 - 1, "^",
+ " (<expression>): ", (a + person), "^";
+ print "Escapes:^",
+ " by mnemonic: @!! @<< @'A @AE @et @:y^",
+ " by decimal value: @@64 @@126^",
+ " by Unicode value: @{DC}@{002b}^",
+ " by string variable: @25^";
+ 'font', 'style':
+ font off; print "font off^";
+ font on; print "font on^";
+ style reverse; print "style reverse^"; style roman;
+ style bold; print "style bold^";
+ style underline; print "style underline^";
+ style fixed; print "style fixed^";
+ style roman; print "style roman^";
+ 'statements':
+ spaces 8;
+ objectloop (o) {
+ print "objectloop (o): ", (the) o, "^";
+ }
+ objectloop (o in compass) { ! 'in' is a keyword
+ print "objectloop (o in compass): ", (the) o, "^";
+ }
+ objectloop (o in compass && true) { ! 'in' is an operator
+ print "objectloop (o in compass && true): ", (the) o, "^";
+ }
+ objectloop (o from se_obj) {
+ print "objectloop (o from se_obj): ", (the) o, "^";
+ }
+ objectloop (o near person) {
+ print "objectloop (o near person): ", (the) o, "^";
+ }
+ #Ifdef TARGET_ZCODE;
+ #Trace assembly on;
+@ ! This is assembly.
+ add -4 ($$1+$3)*2 -> b;
+ @get_sibling test_tube -> b ?saved;
+ @inc [b];
+ @je sp (1+3*0) ? equal;
+ @je 1 ((sp)) ?~ different;
+ .! This is a label:
+ equal;
+ print "sp == 1^";
+ jump label;
+ .different;
+ print "sp @@126= 1^";
+ .label;
+ #Trace off; #Endif; ! TARGET_ZCODE
+ a = random(10);
+ switch (a) {
+ 1, 9:
+ box "Testing oneself is best when done alone."
+ " -- Jimmy Carter";
+ 2, 6, 3 to 5:
+ <Take pigeon>;
+ #Ifdef VN_1633;
+ <Jump, person>;
+ #Endif;
+ a = ##Drop;
+ < ! The angle brackets may be separated by whitespace.
+ < (a) pigeon > >;
+ default:
+ do {
+ give person general ~general;
+ } until (person provides life && ~~false);
+ if (a == 7) a = 4;
+ else a = 5;
+ }
+ 'expressions':
+ a = 1+1-1*1/1%1&1|1&&1||1==(1~=(1>(1<(1>=(1<=1)))));
+ a++; ++a; a--; --a;
+ a = person.life;
+ a = kitchen.&arr;
+ a = kitchen.#arr;
+ a = Bird::wingspan;
+ a = kitchen has general;
+ a = kitchen hasnt general;
+ a = kitchen provides arr;
+ a = person in kitchen;
+ a = person notin kitchen;
+ a = person ofclass Bird;
+ a = a == 0 or 1;
+ a = StubR();
+ a = StubR(a);
+ a = StubR(, a);
+ a = "string";
+ a = 'word';
+ a = '''; ! character
+ a = $09afAF;
+ a = $$01;
+ a = ##Eat; a = #a$Eat;
+ a = #g$self;
+ a = #n$!word;
+ a = #r$StubR;
+ a = #dict_par1;
+ default:
+ for (a = 2, b = a; (a < buffer->1 + 2) && (Bird::wingspan): ++a, b--) {
+ print (char) buffer->a;
+ }
+ new_line;
+ for (::) break;
+ }
+ .saved;;
+];
+
+[ TestNumberSub;
+ print_ret parsed_number, " is ", (number) parsed_number, ".";
+];
+
+[ TestAttributeSub; print_ret (The) noun, " has been reversed."; ];
+
+[ CreatureTest obj; return obj has animate; ];
+
+[ TestCreatureSub; print_ret (The) noun, " is a creature."; ];
+
+[ TestMultiheldSub; print_ret "You are holding ", (the) noun, "."; ];
+
+[ TestMultiexceptSub; "You test ", (the) noun, " with ", (the) second, "."; ];
+
+[ TestMultiinsideSub; "You test ", (the) noun, " from ", (the) second, "."; ];
+
+[ TestMultiSub; print_ret (The) noun, " is a thing."; ];
+
+[ TestNounFilterSub; print_ret (The) noun, " is a bird."; ];
+
+[ TestScopeFilterSub; print_ret (The) noun, " is a direction."; ];
+
+[ TestSpecialSub; "Your lucky number is ", parsed_number, "."; ];
+
+[ TestTopicSub; "You discuss a topic."; ];
+
+[ TestNounSub; "That is ", (a) noun, "."; ];
+
+[ TestHeldSub; "You are holding ", (a) noun, "."; ];
+
+[ NewWaveSub; "That would be foolish."; ];
+
+[ FeelSub; print_ret (The) noun, " feels normal."; ];
+
+Global to;
+[ ReverseSub;
+ to = parent(noun);
+ move noun to parent(second);
+ move second to to;
+ give noun reversed;
+ give second reversed;
+ "You swap ", (the) noun, " and ", (the) second, ".";
+];
+
+End: The End directive ends the source code.
diff --git a/tests/examplefiles/example.ni b/tests/examplefiles/example.ni
new file mode 100644
index 00000000..32279e80
--- /dev/null
+++ b/tests/examplefiles/example.ni
@@ -0,0 +1,57 @@
+ | | |
+"Informal by Nature"
+[ * * * ]
+by
+[ * * * ]
+David Corbett
+
+[This is a [nested] comment.]
+
+Section 1 - Use option translation
+
+Use maximum tests of at least 100 translates as (-
+@c
+Constant MAX_TESTS = {N}; —). | Section 2
+
+A room has a number called size.
+
+The Kitchen is a room. "A nondescript kitchen.“ The Kitchen has size 2.
+
+When play begins:
+ say "Testing:[line break]";
+ test 0.
+
+To test (N — number): (—
+ if (Test({N}) == (+size of the Kitchen [this should succeed]+)) {-open—brace}
+ print ”Success.^”;
+ {-close-brace} else {
+ print “Failure.^";
+ }
+]; ! You shouldn't end a routine within a phrase definition, but it works.
+[ Unused;
+ #Include "\
+@p \
+"; ! At signs hold no power here.
+! Of course, the file "@p .h" must exist.
+-).
+
+Include (-!% This is not ICL.
+
+[ Test x;
+ if (x) {x++;}
+ {–! Single line comment.}
+@inc x;
+@p At signs.
+...
+@Purpose: ...
+...
+@-...
+@c ...
+@inc x;
+@c
+@c
+ return x;
+];
+@Purpose: ...
+@-------------------------------------------------------------------------------
+-).