diff options
-rw-r--r-- | pygments/lexers/_mapping.py | 1 | ||||
-rw-r--r-- | pygments/lexers/functional.py | 191 | ||||
-rw-r--r-- | tests/examplefiles/garcia-wachs.kk | 123 |
3 files changed, 314 insertions, 1 deletions
diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py index c9cbb91a..ef6fde66 100644 --- a/pygments/lexers/_mapping.py +++ b/pygments/lexers/_mapping.py @@ -140,6 +140,7 @@ LEXERS = { 'JuliaConsoleLexer': ('pygments.lexers.math', 'Julia console', ('jlcon',), (), ()), 'JuliaLexer': ('pygments.lexers.math', 'Julia', ('julia', 'jl'), ('*.jl',), ('text/x-julia', 'application/x-julia')), 'KconfigLexer': ('pygments.lexers.other', 'Kconfig', ('kconfig', 'menuconfig', 'linux-config', 'kernel-config'), ('Kconfig', '*Config.in*', 'external.in*', 'standard-modules.in'), ('text/x-kconfig',)), + 'KokaLexer':('pygments.lexers.functional', 'Koka', ('koka'), ('*.kk','*.kki'), ('text/x-koka')), 'KotlinLexer': ('pygments.lexers.jvm', 'Kotlin', ('kotlin',), ('*.kt',), ('text/x-kotlin',)), 'LassoCssLexer': ('pygments.lexers.templates', 'CSS+Lasso', ('css+lasso',), (), ('text/css+lasso',)), 'LassoHtmlLexer': ('pygments.lexers.templates', 'HTML+Lasso', ('html+lasso',), (), ('text/html+lasso', 'application/x-httpd-lasso', 'application/x-httpd-lasso[89]')), diff --git a/pygments/lexers/functional.py b/pygments/lexers/functional.py index f77b918c..c22c8989 100644 --- a/pygments/lexers/functional.py +++ b/pygments/lexers/functional.py @@ -18,7 +18,7 @@ from pygments.token import Text, Comment, Operator, Keyword, Name, \ __all__ = ['RacketLexer', 'SchemeLexer', 'CommonLispLexer', 'HaskellLexer', 'LiterateHaskellLexer', 'SMLLexer', 'OcamlLexer', 'ErlangLexer', 'ErlangShellLexer', 'OpaLexer', 'CoqLexer', 'NewLispLexer', - 'ElixirLexer', 'ElixirConsoleLexer'] + 'ElixirLexer', 'ElixirConsoleLexer', 'KokaLexer' ] class RacketLexer(RegexLexer): @@ -2393,3 +2393,192 @@ class ElixirConsoleLexer(Lexer): for item in do_insertions(insertions, exlexer.get_tokens_unprocessed(curcode)): yield item + + +class KokaLexer(RegexLexer): + """ + Lexer for the Koka language. + """ + + name = 'Koka' + aliases = ['koka'] + filenames = ['*.kk', '*.kki'] + mimetypes = ['text/x-koka'] + + keywords = [ + 'infix', 'infixr', 'infixl', 'prefix', 'postfix', + 'type', 'cotype', 'rectype', 'alias', + 'struct', 'con', + 'fun', 'function', 'val', 'var', + 'external', + 'if', 'then', 'else', 'elif', 'return', 'match', + 'private', 'public', 'private', + 'module', 'import', 'as', + 'include', 'inline', + 'rec', + 'try', 'yield', 'enum', + 'interface', 'instance' + ] + + # keywords that are followed by a type + typeStartKeywords = [ + 'type','cotype','rectype','alias','struct','enum' + ] + + # keywords valid in a type + typekeywords = [ + 'forall', 'exists', 'some', 'with' + ] + + # builtin names and special names + builtin = [ + 'for', 'while', 'repeat', + 'foreach', 'foreach-indexed', + 'error', 'catch', 'finally', + 'cs', 'js', 'file', 'ref', 'assigned' + ] + + # symbols that can be in an operator + symbols = '[\$%&\*\+@!/\\\^~=\.:\-\?\|<>]+' + + # symbol boundary: an operator keyword should not be followed by any of these + sboundary = '(?!'+symbols+')' + + # name boundary: a keyword should not be followed by any of these + boundary = '(?![a-zA-Z0-9_\\-])' + + # main lexer + tokens = { + 'root': [ + include('whitespace'), + + # go into type mode + (r'::?'+sboundary, Keyword.Type, 'type'), + (r'alias'+boundary, Keyword,'alias-type'), + (r'struct'+boundary, Keyword,'struct-type'), + (r'(%s)' % '|'.join(typeStartKeywords)+boundary, Keyword, 'type'), + + # special sequences of tokens (we use ?: for non-capturing group as required by 'bygroups') + (r'(module)(\s*)((?:interface)?)(\s*)((?:[a-z](?:[a-zA-Z0-9_]|\-[a-zA-Z])*\.)*[a-z](?:[a-zA-Z0-9_]|\-[a-zA-Z])*)' + , bygroups(Keyword,Text,Keyword,Text,Name.Namespace)), + (r'(import)(\s+)((?:[a-z](?:[a-zA-Z0-9_]|\-[a-zA-Z])*\.)*[a-z](?:[a-zA-Z0-9_]|\-[a-zA-Z])*)(\s*)((?:as)?)((?:[A-Z](?:[a-zA-Z0-9_]|\-[a-zA-Z])*)?)' + , bygroups(Keyword,Text,Name.Namespace,Text,Keyword,Name.Namespace)), + + # keywords + (r'(%s)' % '|'.join(typekeywords) + boundary, Keyword.Type), + (r'(%s)' % '|'.join(keywords) + boundary, Keyword), + (r'(%s)' % '|'.join(builtin) + boundary, Keyword.Pseudo), + (r'::|:=|\->|[=\.:]' + sboundary, Keyword), + (r'\-' + sboundary, Generic.Strong), + + # names + (r'[A-Z]([a-zA-Z0-9_]|\-[a-zA-Z])*(?=\.)',Name.Namespace), + (r'[A-Z]([a-zA-Z0-9_]|\-[a-zA-Z])*(?!\.)',Name.Class), + (r'[a-z]([a-zA-Z0-9_]|\-[a-zA-Z])*',Name), + (r'_([a-zA-Z0-9_]|\-[a-zA-Z])*',Name.Variable), + + # literal string + (r'@"', String.Double, 'litstring'), + + # operators + (symbols, Operator), + (r'`', Operator), + (r'[\{\}\(\)\[\];,]', Punctuation), + + # literals. No check for literal characters with too many characters in it. + (r'[0-9]+\.[0-9]+([eE][\-\+]?[0-9]+)?', Number.Float), + (r'0[xX][0-9a-fA-F]+', Number.Hex), + (r'[0-9]+', Number.Integer), + + (r"'", String.Char, 'char'), + (r'"', String.Double, 'string'), + ], + + # type started by alias + 'alias-type': [ + (r'=',Keyword), + include('type') + ], + + # type started by struct + 'struct-type': [ + (r'(?=\((?!,*\)))',Punctuation,'#pop'), + include('type') + ], + + # type started by colon + 'type': [ + (r'[\(\[<]', Keyword.Type, 'type-nested' ), + include('type-content') + ], + + # type nested in brackets: can contain parameters, comma etc. + 'type-nested': [ + (r'[\)\]>]', Keyword.Type, '#pop' ), + (r'[\(\[<]', Keyword.Type, 'type-nested' ), + (r'[,]', Keyword.Type), + (r'([a-z](?:[a-zA-Z0-9_]|\-[a-zA-Z])*)(\s*)(:)(?![:])',bygroups(Name.Variable,Text,Keyword.Type)), # parameter name + include('type-content') + ], + + # shared contents of a type + 'type-content': [ + include('whitespace'), + + # keywords + (r'(%s)' % '|'.join(typekeywords) + boundary, Keyword.Type), + (r'(?=((%s)' % '|'.join(keywords) + boundary + '))', Keyword, '#pop'), # need to match because names overlap.. + + # kinds + (r'[EPH]' + boundary, Keyword.Type), + (r'[\*\!]', Keyword.Type), + + # type names + (r'[A-Z]([a-zA-Z0-9_]|\-[a-zA-Z])*(?=\.)',Name.Namespace), + (r'[A-Z]([a-zA-Z0-9_]|\-[a-zA-Z])*(?!\.)',Name.Class), + (r'[a-z][0-9]*(?![a-zA-Z_\-])',Keyword.Type), # Generic.Emph + (r'_([a-zA-Z0-9_]|\-[a-zA-Z])*',Keyword.Type), # Generic.Emph + (r'[a-z]([a-zA-Z0-9_]|\-[a-zA-Z])*',Keyword.Type), + + # type keyword operators + (r'::|\->|[\.:|]', Keyword.Type), + + #catchall + (r'', Text, '#pop') + ], + + # comments and literals + 'whitespace': [ + (r'\s+', Text), + (r'/\*', Comment.Multiline, 'comment'), + (r'//.*$', Comment.Single) + ], + 'comment': [ + (r'[^/\*]+', Comment.Multiline), + (r'/\*', Comment.Multiline, '#push'), + (r'\*/', Comment.Multiline, '#pop'), + (r'[\*/]', Comment.Multiline), + ], + 'litstring': [ + (r'[^"]+', String.Double), + (r'""', String.Escape), + (r'"', String.Double, '#pop'), + ], + 'string': [ + (r'[^\\"\n]+', String.Double), + include('escape-sequence'), + (r'["\n]', String.Double, '#pop'), + ], + 'char': [ + (r'[^\\\'\n]+', String.Char), + include('escape-sequence'), + (r'[\'\n]', String.Char, '#pop'), + ], + 'escape-sequence': [ + (r'\\[abfnrtv0\\\"\'\?]', String.Escape), + (r'\\x[0-9a-fA-F]{2}', String.Escape), + (r'\\u[0-9a-fA-F]{4}', String.Escape), + (r'\\U[0-9a-fA-F]{6}', String.Escape) + ] + } + diff --git a/tests/examplefiles/garcia-wachs.kk b/tests/examplefiles/garcia-wachs.kk new file mode 100644 index 00000000..f766e051 --- /dev/null +++ b/tests/examplefiles/garcia-wachs.kk @@ -0,0 +1,123 @@ +/* This is an example in the Koka Language of the Garcia-Wachs algorithm */
+module garcia-wachs
+
+public fun main()
+{
+ test().print
+}
+
+//----------------------------------------------------
+// Trees
+//----------------------------------------------------
+public type tree<a> {
+ con Leaf(value :a)
+ con Node(left :tree<a>, right :tree<a>)
+}
+
+fun show( t : tree<char> ) : string
+{
+ match(t) {
+ Leaf(c) -> Core.show(c)
+ Node(l,r) -> "Node(" + show(l) + "," + show(r) + ")"
+ }
+}
+
+
+//----------------------------------------------------
+// Non empty lists
+//----------------------------------------------------
+public type list1<a> {
+ Cons1( head : a, tail : list<a> )
+}
+
+
+fun map( xs, f ) {
+ val Cons1(y,ys) = xs
+ return Cons1(f(y), Core.map(ys,f))
+}
+
+fun zip( xs :list1<a>, ys :list1<b> ) : list1<(a,b)> {
+ Cons1( (xs.head, ys.head), zip(xs.tail, ys.tail))
+}
+
+
+
+//----------------------------------------------------
+// Phase 1
+//----------------------------------------------------
+
+fun insert( after : list<(tree<a>,int)>, t : (tree<a>,int), before : list<(tree<a>,int)> ) : div tree<a>
+{
+ match(before) {
+ Nil -> extract( [], Cons1(t,after) )
+ Cons(x,xs) -> {
+ if (x.snd < t.snd) then return insert( Cons(x,after), t, xs )
+ match(xs) {
+ Nil -> extract( [], Cons1(x,Cons(t,after)) )
+ Cons(y,ys) -> extract( ys, Cons1(y,Cons(x,Cons(t,after))) )
+ }
+ }
+ }
+}
+
+fun extract( before : list<(tree<a>,int)>, after : list1<(tree<a>,int)> ) : div tree<a>
+{
+ val Cons1((t1,w1) as x, xs ) = after
+ match(xs) {
+ Nil -> t1
+ Cons((t2,w2) as y, ys) -> match(ys) {
+ Nil -> insert( [], (Node(t1,t2), w1+w2), before )
+ Cons((_,w3),_zs) ->
+ if (w1 <= w3)
+ then insert(ys, (Node(t1,t2), w1+w2), before)
+ else extract(Cons(x,before), Cons1(y,ys))
+ }
+ }
+}
+
+
+
+fun balance( xs : list1<(tree<a>,int)> ) : div tree<a>
+{
+ extract( [], xs )
+}
+
+fun mark( depth :int, t :tree<(a,ref<h,int>)> ) : <write<h>> ()
+{
+ match(t) {
+ Leaf((_,d)) -> d := depth
+ Node(l,r) -> { mark(depth+1,l); mark(depth+1,r) }
+ }
+}
+
+
+fun build( depth :int, xs :list1<(a,ref<h,int>)> ) : <read<h>,div> (tree<a>,list<(a,ref<h,int>)>)
+{
+ if (!xs.head.snd == depth) return (Leaf(xs.head.fst), xs.tail)
+
+ l = build(depth+1, xs)
+ match(l.snd) {
+ Nil -> (l.fst, Nil)
+ Cons(y,ys) -> {
+ r = build(depth+1, Cons1(y,ys))
+ (Node(l.fst,r.fst), r.snd)
+ }
+ }
+}
+
+public fun test() {
+ wlist = Cons1(('a',3), [('b',2),('c',1),('d',4),('e',5)])
+ tree = wlist.garciawachs()
+ tree.show()
+}
+
+public fun garciawachs( xs : list1<(a,int)> ) : div tree<a>
+{
+ refs = xs.map(fst).map( fun(x) { (x, ref(0)) } )
+ wleafs = zip( refs.map(Leaf), xs.map(snd) )
+
+ tree = balance(wleafs)
+ mark(0,tree)
+ build(0,refs).fst
+}
+
|