Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
YueLiPicasso committed Sep 14, 2022
1 parent 51cebbf commit d159ad4
Show file tree
Hide file tree
Showing 4 changed files with 344 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# emacs backupfile
*~
44 changes: 42 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,42 @@
# Catala-gedit-syntax-highlighting
GEdit syntax highlighting for Catala
# GEdit syntax highlighting for Catala

This is to support syntax highlighting of English Catala code in GEdit.

The code is modelled after the [Catala syntax highlighting code for the iro compiler](https://github.com/CatalaLang/catala/blob/e7c3ef604e1862dee82a1395ee2a1ea6beb5f9a2/syntax_highlighting/en/catala_en.iro).


## How to use

Copy the file [catala.lang](catala.lang) to the directory below (create if it does not exist) and then
restart GEdit.
```
~/.local/share/gtksourceview-4/language-specs
```

I use [test.catala_en](YCatala.catala_en) as a test file.

## Reference

Here I collect further resources which helped me write the code.


The posts below basically say that to provide gedit syntax highlighting support we simply need to write a XML file specifiying the syntax and put it under the gedit syntax highlighting directory.
```
https://unix.stackexchange.com/questions/4203/how-can-i-write-a-new-syntax-highlighter-for-gedit
https://askubuntu.com/questions/55494/how-do-i-add-a-syntax-highlighter-format-to-gedit
https://github.com/thomasysliu/Gedit-SPICE-syntax-highlighting
```

Below is a trouble shooting Q&A from a user who successfully added a custom syntax highlighting extension to gedit.
```
https://askubuntu.com/questions/295559/how-to-add-a-new-language-definition-for-syntax-highlighting-in-gedit
```

The definitive guide.
```
https://developer-old.gnome.org/gtksourceview/stable/syntax-highlighting-reference.html
```




131 changes: 131 additions & 0 deletions catala.lang
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>

<language id="catala" name="Catala" version="2.0" _section="Source">

<metadata>
<property name="mimetypes">text/x-catala</property>
<property name="globs">*.catala_en</property>
</metadata>

<styles>
<style id="keyword-decl" name="Declaration" map-to="def:constant"/>
<style id="keyword-rule" name="Rule" map-to="def:type"/>
<style id="keyword-expr" name="Expression" map-to="def:keyword"/>
<style id="comment" name="Comment" map-to="def:special-char"/>
<style id="primitive" name="Primitive" map-to="def:preprocessor"/>
<style id="sc_id" name="Snake-case" map-to="def:identifier"/>
<style id="cc_id" name="Camel-case" map-to="def:comment"/>
</styles>

<definitions>

<context id="codeblock">
<start>```catala-metadata|```catala</start>
<end>```</end>
<include>
<context ref="comment"/>
<context ref="keyword-decl"/>
<context ref="keyword-rule"/>
<context ref="keyword-expr"/>
<context ref="primitive"/>
<context ref="operator"/>
<context ref="sc_id"/>
<context ref="cc_id"/>
</include>
</context>

<context id="comment" style-ref="comment">
<start>#</start>
<end>$</end>
</context>

<context id="keyword-decl" style-ref="keyword-decl">
<keyword>declaration</keyword>
</context>

<context id="keyword-rule" style-ref="keyword-rule">
<keyword>context</keyword>
<keyword>input</keyword>
<keyword>output</keyword>
<keyword>internal</keyword>
<keyword>scope</keyword>
<keyword>depends\s+on</keyword>
<keyword>includes</keyword>
<keyword>collection</keyword>
<keyword>content</keyword>
<keyword>optional</keyword>
<keyword>structure</keyword>
<keyword>enumeration</keyword>
<keyword>rule</keyword>
<keyword>under\s+condition</keyword>
<keyword>condition</keyword>
<keyword>data</keyword>
<keyword>consequence</keyword>
<keyword>fulfilled</keyword>
<keyword>equals</keyword>
<keyword>assertion</keyword>
<keyword>definition</keyword>
<keyword>state</keyword>
<keyword>label</keyword>
<keyword>exception</keyword>
</context>

<context id="keyword-expr" style-ref="keyword-expr">
<keyword>match</keyword>
<keyword>with\s+pattern</keyword>
<keyword>fixed</keyword>
<keyword>by</keyword>
<keyword>decreasing</keyword>
<keyword>increasing</keyword>
<keyword>varies</keyword>
<keyword>with</keyword>
<keyword>we\s+have</keyword>
<keyword>let</keyword>
<keyword>in</keyword>
<keyword>such\s+that</keyword>
<keyword>exists</keyword>
<keyword>for</keyword>
<keyword>all</keyword>
<keyword>of</keyword>
<keyword>if</keyword>
<keyword>then</keyword>
<keyword>else</keyword>
<keyword>initial</keyword>
</context>

<context id="primitive" style-ref="primitive">
<keyword>integer</keyword>
<keyword>boolean</keyword>
<keyword>date</keyword>
<keyword>duration</keyword>
<keyword>money</keyword>
<keyword>text</keyword>
<keyword>decimal</keyword>
<keyword>number</keyword>
<keyword>sum</keyword>
</context>

<context id="operator" style-ref="keyword-expr">
<!--for proper matching, do not allow unnecessary spaces in the following regex-->
<match>\.|\s((&lt;=|&lt;|&gt;=|&gt;|\+|-|\*|\/)(\$|\@|\^|\.|)?|not|or|xor|and|year|month|day|!=|=|--)(\s|$)</match>
</context>

<!-- Snake-case identifiers-->
<context id="sc_id" style-ref="sc_id">
<match>\b[[:lower:]]([[:lower:]]|[[:upper:]]|[0-9]|_|\')*\b</match>
</context>

<!-- Camel-case identifiers-->
<context id="cc_id" style-ref="cc_id">
<match>\b[[:upper:]]([[:lower:]]|[[:upper:]]|[0-9]|_|\')*\b</match>
</context>

<!--main context-->
<context id="catala">
<include>
<context ref="codeblock"/>
</include>
</context>

</definitions>
</language>
169 changes: 169 additions & 0 deletions test.catala_en
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Fictional Income Tax Rules

## Article 1

The income tax for an individual is defined
as a fixed percentage of the individual's
income over a year.

```catala-metadata
declaration structure Individual :
data income content money
data number_of_children content integer
# like OCaml record type

declaration enumeration TaxCredit :
-- NoTaxCredit
-- ChildrenTaxCredit content integer
# like OCaml algebraic data type

declaration scope IncomeTaxComputation :
input individual content Individual
internal fixed_percentage content decimal
output income_tax content money

# like OCaml function type declaration
# a variable can be both input and output
```

```catala
scope IncomeTaxComputation :
definition income_tax equals
individual.income *$ fixed_percentage
# *$ is multiplication (*) with money ($)
```

## Article 2

The fixed percentage mentioned at article 1 is equal to 20 %.

```catala
# distributed definition
scope IncomeTaxComputation:
definition fixed_percentage equals 20 %
```

## Article 3

If the individual is in charge of 2 or more
children, then the fixed percentage mentioned
at article 1 is equal to 15 %.

```catala
scope IncomeTaxComputation :
definition fixed_percentage under condition
individual.number_of_children >= 2
consequence equals 15 %
```

### Article 3 bis

The children eligible for application of article 3.

```catala
# can I use catala-metadata here?

declaration scope Child :
input age content integer
output is_eligible_article_3 condition
# "condition" is like "content bool"

scope Child:
rule is_eligible_article_3 under condition
age < 18
consequence fulfilled
# "rule" is like "define", but set conditions
# to either true or false.
# fulfilled is like "equals true"
```

```catala-metadata
declaration structure TwoBrackets:
data breakpoint content money
data rate1 content decimal
data rate2 content decimal

declaration scope TwoBracketsTaxComputation:
input brackets content TwoBrackets
output tax_formula content money depends on money
# the output has a function type
```

## Article 4

The tax amount for a two-brackets computation is
equal to the amount of income in each bracket
multiplied by the rate of each bracket.

```catala
scope TwoBracketsTaxComputation:
definition tax_formula of income equals
# "income" is a formal parameter of the function
if income <=$ brackets.breakpoint then
income *$ brackets.rate1
else (
brackets.breakpoint *$ brackets.rate1 +$
(income -$ brackets.breakpoint) *$
brackets.rate2
)
```

## Article 5

For individuals whose income is greater than
$100,000, the income tax of article 1 is 40%
of the income above $100,000. Below $100,000,
the income tax is 20% of the income.

```catala
declaration scope NewIncomeTaxComputation:
two_brackets scope TwoBracketsTaxComputation
# add a subscope to context
input individual content Individual
output income_tax content money

scope NewIncomeTaxComputation:
definition two_brackets.brackets equals
TwoBrackets {
-- breakpoint : $100,000
-- rate1 : 20%
-- rate2 : 40%
}
# we have now provided the input to the subscope,
# which is then expected to return a function
definition income_tax equals
two_brackets.tax_formula of individual.income
```

## Article 6

Individuals earning less than $10,000 are exempted
of the income tax mentioned at article 1.

```catala
scope NewIncomeTaxComputation :
definition income_tax under condition
individual.income <=$ $10,000
consequence equals $0
```

## Tests

```catala
declaration scope Test1 :
tax_computation scope NewIncomeTaxComputation
output income_tax content money

scope Test1 :
definition tax_computation.individual equals
Individual {
-- income : $700,000
# try also 7,000
-- number_of_children : 0
}
definition income_tax equals
tax_computation.income_tax
assertion income_tax = $260,000
```


0 comments on commit d159ad4

Please sign in to comment.