Skip to content

Commit

Permalink
See if RTD can do TeX in Felix. [ci skip]
Browse files Browse the repository at this point in the history
  • Loading branch information
skaller committed Nov 15, 2017
1 parent 54bc207 commit 351b3da
Show file tree
Hide file tree
Showing 8 changed files with 595 additions and 11 deletions.
1 change: 1 addition & 0 deletions doc/tutorial/_static/custom_lexers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# custom lexers
238 changes: 238 additions & 0 deletions doc/tutorial/_static/custom_lexers/xfelix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
# -*- coding: utf-8 -*-
"""
pygments.lexers.felix
~~~~~~~~~~~~~~~~~~~~~
Lexer for the Felix language.
:copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

from pygments.lexer import RegexLexer, include, bygroups, default, words, \
combined
from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
Number, Punctuation, Generic, Token

__all__ = ['XFelixLexer']

XMath = Token.XMath

class XFelixLexer(RegexLexer):
"""
For `Felix <http://felix-lang.org>`_ source code.
.. versionadded:: 1.2
"""

# screws up latex! Keep for reference. Testing HACK only!
def get_tokens_unprocessed(self,text):
for index,token,value in RegexLexer.get_tokens_unprocessed(self,text):
if token == Generic:
value = "\\(" + value + "\\)"
print ("Generic")
yield (index,token,value)
elif token == XMath:
print ("XMATH")
yield (index,Generic,value)
else:
yield (index,token,value)


name = 'XFelix'
aliases = ['xfelix', 'xflx']
filenames = ['*.flx', '*.flxh']
mimetypes = ['text/x-felix']

keywords = (
'_', '_deref', 'all', 'as',
'assert', 'attempt', 'call', 'callback', 'case', 'caseno', 'cclass',
'code', 'compound', 'ctypes', 'do', 'done', 'downto', 'elif', 'else',
'endattempt', 'endcase', 'endif', 'endmatch', 'enum', 'except',
'exceptions', 'expect', 'finally', 'for', 'forall', 'forget', 'fork',
'functor', 'goto', 'ident', 'if', 'incomplete', 'inherit', 'instance',
'interface', 'jump', 'lambda', 'loop', 'match', 'module', 'namespace',
'new', 'noexpand', 'nonterm', 'obj', 'of', 'open', 'parse', 'raise',
'regexp', 'reglex', 'regmatch', 'rename', 'return', 'the', 'then',
'to', 'type', 'typecase', 'typedef', 'typematch', 'typeof', 'upto',
'when', 'whilst', 'with', 'yield',
'circuit','endcircuit','connect','wire','connector','pin'
)

keyword_directives = (
'_gc_pointer', '_gc_type', 'body', 'comment', 'const', 'export',
'header', 'inline', 'lval', 'macro', 'noinline', 'noreturn',
'package', 'private', 'pod', 'property', 'public', 'publish',
'requires', 'todo', 'virtual', 'use',
)

keyword_declarations = (
'def', 'let', 'ref',
)

keyword_types = (
'unit', 'void', 'any', 'bool',
'byte', 'offset',
'address', 'caddress', 'cvaddress', 'vaddress',
'tiny', 'short', 'int', 'long', 'vlong',
'utiny', 'ushort', 'vshort', 'uint', 'ulong', 'uvlong',
'int8', 'int16', 'int32', 'int64',
'uint8', 'uint16', 'uint32', 'uint64',
'float', 'double', 'ldouble',
'complex', 'dcomplex', 'lcomplex',
'imaginary', 'dimaginary', 'limaginary',
'char', 'wchar', 'uchar',
'charp', 'charcp', 'ucharp', 'ucharcp',
'string', 'wstring', 'ustring',
'cont',
'array', 'varray', 'list',
'lvalue', 'opt', 'slice',
)

keyword_constants = (
'false', 'true',
)

name_builtins = (
'_svc', 'while',
)

name_pseudo = (
'root', 'self', 'this',
)

decimal_suffixes = '((u?([tTsSiIlLvVzpj]|ll|LL))|([iIuU])(8|16|32|64))?'

tokens = {
'root': [
include('whitespace'),

# Keywords
(words(('axiom', 'ctor', 'chip', 'fun', 'gen', 'proc', 'reduce','regdef',
'var','val','typedef',
'union'), suffix=r'\b'),
Keyword, 'funcname'),
(words(('class', 'cclass', 'cstruct', 'obj', 'struct', 'object'), suffix=r'\b'),
Keyword, 'funcname'),
(r'(module|typeclass|interface)\b', Keyword, 'funcname'),

(words(keywords, suffix=r'\b'), Keyword),
(words(keyword_directives, suffix=r'\b'), Name.Decorator),
(words(keyword_declarations, suffix=r'\b'), Keyword.Declaration),
(words(keyword_types, suffix=r'\b'), Keyword.Type),
(words(keyword_constants, suffix=r'\b'), Keyword.Constant),

# Operators
include('operators'),

# Float Literal
# -- Hex Float
(r'0[xX]([0-9a-fA-F_]*\.[0-9a-fA-F_]+|[0-9a-fA-F_]+)'
r'[pP][+\-]?[0-9_]+[lLfFdD]?', Number.Float),
# -- DecimalFloat
(r'[0-9_]+(\.[0-9_]+[eE][+\-]?[0-9_]+|'
r'\.[0-9_]*|[eE][+\-]?[0-9_]+)[lLfFdD]?', Number.Float),
(r'\.(0|[1-9][0-9_]*)([eE][+\-]?[0-9_]+)?[lLfFdD]?',
Number.Float),

# IntegerLiteral
# -- Binary
(r'0[Bb][01_]+%s' % decimal_suffixes, Number.Bin),
# -- Octal
(r'0[oO][0-7_]+%s' % decimal_suffixes, Number.Oct),
# -- Hexadecimal
(r'0[xX][0-9a-fA-F_]+%s' % decimal_suffixes, Number.Hex),
# -- Decimal
(r'0[dD][0-9_]+%s' % decimal_suffixes, Number.Integer),
(r'[0-9][0-9_]*%s' % decimal_suffixes, Number.Integer),

# Strings
('([rR][cC]?|[cC][rR])"""', String, 'tdqs'),
("([rR][cC]?|[cC][rR])'''", String, 'tsqs'),
('([rR][cC]?|[cC][rR])"', String, 'dqs'),
("([rR][cC]?|[cC][rR])'", String, 'sqs'),
('[cCfFqQwWuU]?"""', String, combined('stringescape', 'tdqs')),
("[cCfFqQwWuU]?'''", String, combined('stringescape', 'tsqs')),
('[cCfFqQwWuU]?"', String, combined('stringescape', 'dqs')),
("[cCfFqQwWuU]?'", String, combined('stringescape', 'sqs')),

# Punctuation
(r'[\[\]{}:(),;?]', Punctuation),

# Labels
(r'[a-zA-Z_]\w*:>', Name.Label),

# Identifiers
(r"[a-zA-Z_][a-zA-Z0-9_'-]*", Name),

# TeX Identifiers
(r"\\[A-Za-z]+", Generic),

(r'\\\(.*\\\)',XMath),

],
'whitespace': [
(r'\n', Text),
(r'\s+', Text),

include('comment'),
],
'operators': [
(r'!=|==|<<|>>|\|\||&&|\|->|[#!~+/*%=<>&^|.$-]', Operator),
],
'comment': [
(r'//(.*?)\n', Comment.Single),
(r'/[*]', Comment.Multiline, 'comment2'),
],
'comment2': [
(r'[^/*]', Comment.Multiline),
(r'/[*]', Comment.Multiline, '#push'),
(r'[*]/', Comment.Multiline, '#pop'),
(r'[/*]', Comment.Multiline),
],
'funcname': [
include('whitespace'),
(r'[^[( ]+', Name.Function, '#pop'),
# anonymous functions
(r'(?=\()', Text, '#pop'),
],
'stringescape': [
(r'\\([\\abfnrtv"\']|\n|N\{.*?\}|u[a-fA-F0-9]{4}|'
r'U[a-fA-F0-9]{8}|x[a-fA-F0-9]{2}|[0-7]{1,3})', String.Escape)
],
'strings': [
(r'%(\([a-zA-Z0-9]+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?'
'[hlL]?[diouxXeEfFgGcrs%]', String.Interpol),
(r'[^\\\'"%\n]+', String),
# quotes, percents and backslashes must be parsed one at a time
(r'[\'"\\]', String),
# unhandled string formatting sign
(r'%', String)
# newlines are an error (use "nl" state)
],
'nl': [
(r'\n', String)
],
'dqs': [
(r'"', String, '#pop'),
# included here again for raw strings
(r'\\\\|\\"|\\\n', String.Escape),
include('strings')
],
'sqs': [
(r"'", String, '#pop'),
# included here again for raw strings
(r"\\\\|\\'|\\\n", String.Escape),
include('strings')
],
'tdqs': [
(r'"""', String, '#pop'),
include('strings'),
include('nl')
],
'tsqs': [
(r"'''", String, '#pop'),
include('strings'),
include('nl')
],
}
85 changes: 85 additions & 0 deletions doc/tutorial/_static/felixmathjax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
"""
sphinx.ext.mathjax
~~~~~~~~~~~~~~~~~~
Allow `MathJax <http://mathjax.org/>`_ to be used to display math in
Sphinx's HTML writer -- requires the MathJax JavaScript library on your
webserver/computer.
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

from docutils import nodes

import sphinx
from sphinx.locale import _
from sphinx.errors import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup


def html_visit_math(self, node):
self.body.append(self.starttag(node, 'span', '', CLASS='math'))
self.body.append(self.builder.config.mathjax_inline[0] +
self.encode(node['latex']) +
self.builder.config.mathjax_inline[1] + '</span>')
raise nodes.SkipNode


def html_visit_displaymath(self, node):
self.body.append(self.starttag(node, 'div', CLASS='math'))
if node['nowrap']:
self.body.append(self.encode(node['latex']))
self.body.append('</div>')
raise nodes.SkipNode

# necessary to e.g. set the id property correctly
if node['number']:
self.body.append('<span class="eqno">(%s)' % node['number'])
self.add_permalink_ref(node, _('Permalink to this equation'))
self.body.append('</span>')
self.body.append(self.builder.config.mathjax_display[0])
parts = [prt for prt in node['latex'].split('\n\n') if prt.strip()]
if len(parts) > 1: # Add alignment if there are more than 1 equation
self.body.append(r' \begin{align}\begin{aligned}')
for i, part in enumerate(parts):
part = self.encode(part)
if r'\\' in part:
self.body.append(r'\begin{split}' + part + r'\end{split}')
else:
self.body.append(part)
if i < len(parts) - 1: # append new line if not the last equation
self.body.append(r'\\')
if len(parts) > 1: # Add alignment if there are more than 1 equation
self.body.append(r'\end{aligned}\end{align} ')
self.body.append(self.builder.config.mathjax_display[1])
self.body.append('</div>\n')
raise nodes.SkipNode


def builder_inited(app):
if not app.config.mathjax_path:
raise ExtensionError('mathjax_path config value must be set for the '
'mathjax extension to work')
app.add_javascript(app.config.mathjax_options)
app.add_javascript(app.config.mathjax_path)


def setup(app):
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:
raise ExtensionError('sphinx.ext.mathjax: other math package is already loaded')

# more information for mathjax secure url is here:
# http://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn
app.add_config_value('mathjax_path',
'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?'
'config=TeX-AMS-MML_HTMLorMML', False)
app.add_config_value('mathjax_options', 'felixmathjax.js',False)
app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
app.connect('builder-inited', builder_inited)

return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
5 changes: 5 additions & 0 deletions doc/tutorial/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('./_static'))
import custom_lexers.xfelix

from sphinx.highlighting import lexers
lexers['xfelix']= custom_lexers.xfelix.XFelixLexer()

# -- General configuration ------------------------------------------------

Expand Down
19 changes: 16 additions & 3 deletions doc/tutorial/hello.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Tutorial
========
Hello
=====

This is the Felix tutorial

Expand All @@ -25,6 +25,19 @@ To run it you just say:
It's pretty simple. Felix runs programs like Python does, you run the
source code directly. Behind the scenes, Felix translates the program
into C++, compiles the program, and runs it. All the generated files
are cached in the .felix/cache subdirectory of your $HOME directory.
are cached in the .felix/cache subdirectory of your $HOME directory
on Unix like systems, and $USERPROFILE on Windows.

TeX in code test here.

.. code-block:: xfelix
fun \beta (w:double, a:double) : double =>
\(\sqrt{(w^{2^2} + \alpha^2)\over 2}\) + 42
;
println$ \beta (3.0, 4.0);
println$ \(a^2 + b^2\);
Did that work on RTD?

2 changes: 1 addition & 1 deletion doc/tutorial/pythagoras.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Of course, the operator `+` is addition.
The `fun` binder is used here to define a function. Then we give
the function name we want to use, in this case `hypot`.

Then, in paranthesis we give a comma separated list of paramater
Then, in paranthesis we give a comma separated list of parameter
specifications. Each specification is the name of the parameter,
followed by its type.

Expand Down

0 comments on commit 351b3da

Please sign in to comment.