summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst5
-rw-r--r--elan.py135
-rw-r--r--elan.vim51
3 files changed, 191 insertions, 0 deletions
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..2b83812
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,5 @@
+EUMEL-python
+============
+
+Tools for dealing with EUMEL datastructures and files, mostly written in Python.
+
diff --git a/elan.py b/elan.py
new file mode 100644
index 0000000..beeb9f8
--- /dev/null
+++ b/elan.py
@@ -0,0 +1,135 @@
+"""
+pygments lexer for Elementary Language (ELAN)
+
+- Rainer Hahn, Peter Stock: ELAN Handbuch. 1979.
+- Rainer Hahn, Dietmar Heinrichs, Peter Heyderhoff: EUMEL Benutzerhandbuch Version 1.7. 1984.
+"""
+
+from pygments.lexer import RegexLexer, bygroups, include, words
+from pygments.token import *
+
+__all__ = ['ElanLexer']
+
+def uppercaseWords (l):
+ """
+ Match only uppercase words provided in l. For example FOR should not match
+ FORMAT.
+ """
+ return words (l, prefix=r'(?<![A-Z])', suffix=r'(?![A-Z])')
+
+class ElanLexer(RegexLexer):
+ name = 'ELAN'
+ aliases = ['elan']
+ filenames = ['*.elan']
+
+ tokens = {
+ 'root': [
+ include('comment'),
+ # strings
+ (r'"', String.Double, 'string'),
+ # numbers. lookbehind, because identifiers may contain numbers too
+ (r'([-+]|(?<![a-z]))\d+', Number.Integer),
+ (r'[-+]?\d+\.\d+(E[+-]?\d+)?', Number.Float),
+ # keywords
+ (uppercaseWords ((
+ # not sure
+ 'CONCR',
+ # if-then-else
+ 'IF', 'THEN', 'ELSE', 'ELIF', 'ENDIF', 'END IF',
+ # found in the wild:
+ 'FI',
+ # select statement
+ 'SELECT', 'OF', 'CASE', 'OTHERWISE', 'ENDSELECT', 'END SELECT',
+ # loops
+ 'FOR', 'FROM', 'DOWNTO', 'UPTO', 'WHILE', 'REPEAT', 'UNTIL',
+ 'ENDREPEAT', 'END REPEAT',
+ # found in the wild:
+ 'REP', 'PER', 'END REP',
+ # return statements
+ 'LEAVE', 'WITH',
+ )), Keyword.Reserved),
+ (uppercaseWords ((
+ # type declaration
+ 'TYPE',
+ # shorthand declaration
+ 'LET',
+ )), Keyword.Declaration),
+ (uppercaseWords ((
+ # proper packet
+ 'DEFINES',
+ )), Keyword.Namespace),
+ (uppercaseWords (('VAR', 'CONST', 'BOUND')), Name.Attribute),
+ (uppercaseWords (('BOOL', 'INT', 'REAL', 'TEXT', 'STRUCT', 'ROW',
+ 'DATASPACE')), Keyword.Type),
+ # thruth values
+ (uppercaseWords (('TRUE', 'FALSE')), Name.Builtin),
+ # semi-builtin functions/operators, see Benutzerhandbuch pp. 329
+ # "Standartpakete"
+ (uppercaseWords ((
+ # boolean
+ 'NOT', 'AND', 'OR', 'XOR',
+ # text
+ 'CAT', 'LENGTH', 'TIMESOUT',
+ # math
+ 'DECR', 'DIV', 'INCR', 'MOD', 'SUB',
+ )), Operator),
+ # and the same with symbols
+ (words ((
+ # assignments
+ ':=', '::',
+ # comparison
+ '=', '<>', '<=', '>=', '<', '>',
+ # math
+ '**', '*','+', '-', '/',
+ ), prefix=r'(?<![:=<>*+-/])', suffix=r'(?![:=<>*+-/])'),
+ Operator),
+ # packets, function and operators
+ # no space required between keyword and identifier
+ # XXX comments may be allowed between keyword and name
+ (r'((?:END\s*)?PACKET)([^A-Za-z]*)([a-z][a-z0-9 ]+)',
+ bygroups (Keyword.Declaration, Text, Name.Namespace)),
+ (r'((?:END\s*)?PROC)([^A-Za-z]*)([a-z][a-z0-9 ]+)',
+ bygroups (Keyword.Declaration, Text, Name.Function)),
+ (r'((?:END\s*)?OP)([^A-Za-z]*)([^a-z0-9 (;]+)',
+ bygroups (Keyword.Declaration, Text, Name.Function)),
+ # Refinements
+ (r'\.(?![a-z])', Text, 'refinement'),
+ (r'.', Text),
+ ],
+ 'comment': [
+ (r'\(\*', Comment, 'comment-inside1'),
+ (r'\{', Comment, 'comment-inside2'),
+ (r'#\(', Comment, 'comment-inside3'),
+ ],
+ 'comment-inside1': [
+ # comment can be nested
+ include('comment'),
+ (r'\*\)', Comment, '#pop'),
+ (r'(.|\n)', Comment),
+ ],
+ 'comment-inside2': [
+ # comment can be nested
+ include('comment'),
+ (r'\}', Comment, '#pop'),
+ (r'(.|\n)', Comment),
+ ],
+ 'comment-inside3': [
+ # comment can be nested
+ include('comment'),
+ (r'#\)', Comment, '#pop'),
+ (r'(.|\n)', Comment),
+ ],
+ 'string': [
+ # "" equals '\"', "12" is '\12'
+ (r'"[0-9]*"', String.Escape),
+ (r'"', String.Double, '#pop'),
+ (r'.', String.Double),
+ ],
+ 'refinement': [
+ include('comment'),
+ (r'\s+', Text),
+ (r'([a-z][a-z0-9 ]*)(:\s+)', bygroups(Name.Label, Text), '#pop'),
+ (r'', Text, '#pop'),
+ ]
+ }
+
diff --git a/elan.vim b/elan.vim
new file mode 100644
index 0000000..56f03d6
--- /dev/null
+++ b/elan.vim
@@ -0,0 +1,51 @@
+" Vim syntax file
+" Copy to ~/.vim/syntax/ and enable with :set filetype=elan
+" Language: ELAN
+" Maintainer: Lars-Dominik Braun <lars+eumel@6xq.net>
+" Latest Revision: 2017-02-26
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn keyword elanStatement PROC ENDPROC OP PACKET LEAVE WITH END LET DEFINES
+syn keyword elanConditional IF ELSE FI THEN SELECT OF ELIF
+syn keyword elanRepeat FOR FROM UPTO REP PER WHILE UNTIL
+syn keyword elanBoolean TRUE FALSE
+syn keyword elanType DATASPACE INT TEXT BOOL THESAURUS FILE REAL
+syn match elanOperator ":="
+syn match elanOperator "::"
+syn match elanOperator "\*"
+syn match elanOperator "<>"
+syn keyword elanOperator AND OR CAND COR NOT XOR
+syn keyword elanOperator DIV MUL ISUB INCR DECR MOD SUB LENGTH CAT LIKE CONTAINS
+syn keyword elanStorageClass VAR CONST BOUND ROW
+syn keyword elanStructure STRUCT TYPE
+syn keyword elanLabel CASE OTHERWISE
+syn match elanNumber "-\=\<\d\+\>"
+syn match elanFloat "\d\+\.\d\+"
+
+syn region elanComment start=+(\*+ end=+\*)+
+" XXX: tried to fix strings containing numbers that are not escapes, like "2",
+syn region elanString start=+"+rs=s+1 end=+"+re=e-1 contains=elanStringEscape
+"syn match elanStringEscape contained +"[0-9]\+"+
+
+
+hi def link elanBoolean Boolean
+hi def link elanConditional Conditional
+hi def link elanRepeat Repeat
+hi def link elanType Type
+hi def link elanComment Comment
+hi def link elanOperator Operator
+hi def link elanString String
+hi def link elanStringEscape Special
+hi def link elanStorageClass StorageClass
+hi def link elanStructure Structure
+hi def link elanLabel Label
+hi def link elanStatement Statement
+hi def link elanNumber Number
+hi def link elanFloat Float
+
+let b:current_syntax = "elan"
+
+