├── docs ├── CNAME ├── example.js ├── test.cow ├── intro │ ├── type_grammar.ebnf │ └── themes.cow ├── directives │ ├── comments.cow │ ├── foreign.cow │ ├── calc.cow │ ├── references.cow │ ├── separators.cow │ ├── misc.cow │ ├── sections.cow │ └── math.cow └── npm │ ├── README.md │ └── LICENSE ├── test ├── syntax │ ├── empty.cow │ ├── escape_lf.cow │ ├── illegal_backslash.cow │ ├── arguments │ │ ├── ellipsis.cow │ │ ├── group_3.cow │ │ ├── group_1.cow │ │ ├── group_2.cow │ │ ├── balanced_braces.cow │ │ ├── comments_1.cow │ │ ├── block.cow │ │ ├── string.cow │ │ ├── unquoted.cow │ │ └── comments_2.cow │ ├── escape_crlf.cow │ ├── hello_code.cow │ ├── hello_world.cow │ ├── directive_brace_escape.cow │ ├── integers.cow │ ├── directive_brace_escape_2.cow │ ├── directive_multiline.cow │ ├── hello_directive.cow │ ├── directive_multiline_trailing_comma.cow │ ├── directive_as_argument.cow │ ├── directive_names.cow │ ├── literals.cow │ ├── comments.cow │ └── floats.cow └── semantics │ ├── empty.cow │ ├── empty.cow.html │ ├── alias.cow.html │ ├── text.cow │ ├── text.cow.html │ ├── comments.cow.html │ ├── convert │ ├── unit_to_str.cow.html │ ├── bool_to_str.cow.html │ ├── str_to_str.cow.html │ ├── unit_to_str.cow │ ├── reinterpret_as_float.cow.html │ ├── bool_to_str.cow │ ├── str_to_str.cow │ ├── float_to_str.cow.html │ ├── reinterpret_as_int.cow.html │ ├── float_to_str.cow │ ├── reinterpret_as_int.cow │ ├── reinterpret_as_float.cow │ ├── int_to_str.cow.html │ └── int_to_str.cow │ ├── logical │ ├── short_circuit.cow.html │ ├── short_circuit.cow │ ├── ops.cow.html │ └── ops.cow │ ├── macro │ ├── multiline.cow.html │ ├── new.cow.html │ ├── forwarding_named.cow.html │ ├── forwarding_positional.cow.html │ ├── put_paragraphs.cow.html │ ├── put_paragraphs.cow │ ├── forwarding_named.cow │ ├── multiline.cow │ ├── new.cow │ └── forwarding_positional.cow │ ├── paragraphs_deep.cow.html │ ├── paragraphs_with_comments.cow │ ├── paragraphs_with_comments.cow.html │ ├── policy │ ├── text_only.cow.html │ ├── text_as_html.cow.html │ ├── to_html.cow.html │ ├── paragraphs.cow.html │ ├── no_invoke.cow.html │ ├── source_as_text.cow.html │ ├── to_html.cow │ ├── highlight.cow.html │ ├── no_invoke.cow │ ├── paragraphs.cow │ ├── text_only.cow │ ├── highlight.cow │ ├── source_as_text.cow │ └── text_as_html.cow │ ├── paragraphs.cow │ ├── U │ └── ascii.cow │ ├── alias.cow │ ├── paragraphs.cow.html │ ├── arithmetic │ ├── abs.cow.html │ ├── neg.cow.html │ ├── sqrt.cow.html │ ├── ceil.cow.html │ ├── floor.cow.html │ ├── nearest.cow.html │ ├── trunc.cow.html │ ├── max.cow.html │ ├── min.cow.html │ ├── nearest_away_zero.cow.html │ ├── basic.cow.html │ ├── abs.cow │ ├── neg.cow │ ├── sqrt.cow │ ├── ceil.cow │ ├── floor.cow │ ├── trunc.cow │ ├── nearest.cow │ ├── basic.cow │ ├── nearest_away_zero.cow │ ├── max.cow │ └── min.cow │ ├── document │ └── empty.html │ ├── paragraphs_deep.cow │ ├── comments.cow │ ├── highlight.cow.html │ ├── codeblock │ ├── trim.cow │ └── trim.html │ ├── highlight.cow │ ├── compare │ ├── ge.cow.html │ ├── le.cow.html │ ├── gt.cow.html │ ├── lt.cow.html │ ├── eq.cow.html │ ├── ne.cow.html │ ├── ge.cow │ ├── gt.cow │ ├── le.cow │ ├── lt.cow │ ├── eq.cow │ └── ne.cow │ ├── splice │ ├── floats.cow.html │ ├── ints.cow.html │ ├── floats.cow │ └── ints.cow │ ├── paragraph_control.cow.html │ └── paragraph_control.cow ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── cowel-bug.md └── workflows │ └── clang-format.yml ├── .git-blame-ignore-revs ├── .gitignore ├── .gitmodules ├── assets ├── light-dark.js ├── important.svg ├── decision.svg ├── delete.svg ├── insert.svg ├── sync.svg ├── diff.svg ├── tip.svg ├── example.svg ├── dark-mode.svg ├── quote.svg ├── warning.svg ├── note.svg ├── light-mode.svg ├── abstract.svg ├── todo.svg ├── bug.svg └── settings-widget.html ├── include └── cowel │ ├── cedilla │ └── README.md │ ├── util │ ├── function_ref.hpp │ ├── README.md │ ├── annotation_span.hpp │ ├── code_point_names.hpp │ ├── severity.hpp │ ├── assert.hpp │ ├── tty.hpp │ ├── typo.hpp │ ├── ansi.hpp │ ├── meta.hpp │ ├── unicode.hpp │ ├── transparent_comparison.hpp │ ├── html_entities.hpp │ ├── char_sequence_ops.hpp │ ├── chars.hpp │ ├── levenshtein.hpp │ ├── html.hpp │ ├── levenshtein_utf8.hpp │ └── math.hpp │ ├── policy │ ├── factory.hpp │ ├── unprocessed.hpp │ ├── ignorant.hpp │ ├── literally.hpp │ ├── phantom.hpp │ ├── actions.hpp │ ├── text_buffer.hpp │ ├── plaintext.hpp │ ├── content_policy.hpp │ ├── html_literal.hpp │ └── capture.hpp │ ├── theme_to_css.hpp │ ├── assets.hpp │ ├── output_language.hpp │ ├── diagnostic_highlight.hpp │ ├── cowel_lib.hpp │ ├── directive_display.hpp │ ├── grammar.ebnf │ ├── ulight_highlighter.hpp │ ├── relative_file_loader.hpp │ ├── document_generation.hpp │ ├── call_stack.hpp │ ├── parse_utils.hpp │ ├── settings.hpp │ ├── content_status.hpp │ ├── print.hpp │ └── invocation.hpp ├── src ├── test │ └── cpp │ │ ├── main.cpp │ │ ├── document_file_testing.hpp │ │ ├── compilation_stage.hpp │ │ ├── test_valid.cpp │ │ ├── diagnostic_policy.hpp │ │ ├── test_data.hpp │ │ ├── io.hpp │ │ ├── collecting_logger.hpp │ │ ├── test_typo.cpp │ │ ├── test_highlighter.hpp │ │ └── document_file_testing.cpp ├── util │ ├── check-clang-tidy.sh │ ├── transform-package-json.js │ ├── generate-html-entities-cpp.py │ └── file-to-array.py └── main │ └── cpp │ ├── util │ ├── tty.cpp │ ├── code_point_names.cpp │ ├── html_entities.cpp │ ├── io.cpp │ └── typo.cpp │ ├── wasm_stubs.cpp │ ├── semantics.cpp │ ├── directives │ ├── paragraph.cpp │ ├── invoke.cpp │ └── wg21.cpp │ ├── services.cpp │ └── json.cpp ├── tsconfig.json ├── README.md ├── LICENSE ├── .clang-format ├── package.json ├── CONTRIBUTING.md ├── .clang-tidy └── eslint.config.js /docs/CNAME: -------------------------------------------------------------------------------- 1 | cowel.org -------------------------------------------------------------------------------- /test/syntax/empty.cow: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/semantics/empty.cow: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/semantics/empty.cow.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: eisenwave 2 | -------------------------------------------------------------------------------- /test/semantics/alias.cow.html: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | -------------------------------------------------------------------------------- /test/semantics/text.cow: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /test/syntax/escape_lf.cow: -------------------------------------------------------------------------------- 1 | \ 2 | Hello\ 3 | -------------------------------------------------------------------------------- /test/syntax/illegal_backslash.cow: -------------------------------------------------------------------------------- 1 | \0 2 | -------------------------------------------------------------------------------- /test/semantics/text.cow.html: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /test/syntax/arguments/ellipsis.cow: -------------------------------------------------------------------------------- 1 | \x(...) 2 | -------------------------------------------------------------------------------- /test/syntax/arguments/group_3.cow: -------------------------------------------------------------------------------- 1 | \d(((()))) 2 | -------------------------------------------------------------------------------- /test/syntax/escape_crlf.cow: -------------------------------------------------------------------------------- 1 | \ 2 | Hello\ 3 | -------------------------------------------------------------------------------- /test/syntax/hello_code.cow: -------------------------------------------------------------------------------- 1 | \c{/* awoo */} 2 | -------------------------------------------------------------------------------- /test/syntax/hello_world.cow: -------------------------------------------------------------------------------- 1 | Hello world! 2 | -------------------------------------------------------------------------------- /test/semantics/comments.cow.html: -------------------------------------------------------------------------------- 1 | trailing -------------------------------------------------------------------------------- /test/semantics/convert/unit_to_str.cow.html: -------------------------------------------------------------------------------- 1 | unit 2 | -------------------------------------------------------------------------------- /test/syntax/arguments/group_1.cow: -------------------------------------------------------------------------------- 1 | \d((x), ()) 2 | -------------------------------------------------------------------------------- /test/syntax/arguments/group_2.cow: -------------------------------------------------------------------------------- 1 | \d(n = (x, y)) 2 | -------------------------------------------------------------------------------- /test/syntax/directive_brace_escape.cow: -------------------------------------------------------------------------------- 1 | \d{\}} 2 | -------------------------------------------------------------------------------- /test/syntax/integers.cow: -------------------------------------------------------------------------------- 1 | \d(0, 123, -123, 0xff,) 2 | -------------------------------------------------------------------------------- /test/syntax/arguments/balanced_braces.cow: -------------------------------------------------------------------------------- 1 | \d(x={},{}) 2 | -------------------------------------------------------------------------------- /test/syntax/directive_brace_escape_2.cow: -------------------------------------------------------------------------------- 1 | \d{\\{...\\}} 2 | -------------------------------------------------------------------------------- /test/semantics/convert/bool_to_str.cow.html: -------------------------------------------------------------------------------- 1 | true 2 | false 3 | -------------------------------------------------------------------------------- /test/semantics/convert/str_to_str.cow.html: -------------------------------------------------------------------------------- 1 | awoo 2 | chan 3 | -------------------------------------------------------------------------------- /test/semantics/convert/unit_to_str.cow: -------------------------------------------------------------------------------- 1 | \cowel_to_str(unit) 2 | -------------------------------------------------------------------------------- /test/syntax/directive_multiline.cow: -------------------------------------------------------------------------------- 1 | \d( 2 | id = x 3 | ) 4 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | 54278414d6e2f342b2ec29e902d52acd65862201 2 | -------------------------------------------------------------------------------- /docs/example.js: -------------------------------------------------------------------------------- 1 | function sqr(x) { 2 | return x * x; 3 | } 4 | -------------------------------------------------------------------------------- /docs/test.cow: -------------------------------------------------------------------------------- 1 | Hello, \strong{imports}! 2 | 3 | Next paragraph. 4 | -------------------------------------------------------------------------------- /test/semantics/logical/short_circuit.cow.html: -------------------------------------------------------------------------------- 1 | false 2 | true 3 | -------------------------------------------------------------------------------- /test/semantics/macro/multiline.cow.html: -------------------------------------------------------------------------------- 1 | int 2 | -------------------------------------------------------------------------------- /test/syntax/hello_directive.cow: -------------------------------------------------------------------------------- 1 | \b(hello = world, x = 0){test} 2 | -------------------------------------------------------------------------------- /test/semantics/paragraphs_deep.cow.html: -------------------------------------------------------------------------------- 1 |

awoo 2 |

End. 3 | -------------------------------------------------------------------------------- /test/semantics/paragraphs_with_comments.cow: -------------------------------------------------------------------------------- 1 | A 2 | \: comment 3 | 4 | B 5 | -------------------------------------------------------------------------------- /test/syntax/arguments/comments_1.cow: -------------------------------------------------------------------------------- 1 | \a( 2 | \: awoo 3 | \: chan 4 | ) 5 | -------------------------------------------------------------------------------- /test/syntax/directive_multiline_trailing_comma.cow: -------------------------------------------------------------------------------- 1 | \d( 2 | id = x, 3 | ) 4 | -------------------------------------------------------------------------------- /test/semantics/convert/reinterpret_as_float.cow.html: -------------------------------------------------------------------------------- 1 | 0 2 | -0 3 | 1.5 4 | NaN 5 | -------------------------------------------------------------------------------- /test/semantics/paragraphs_with_comments.cow.html: -------------------------------------------------------------------------------- 1 |

A 2 |

3 |

B 4 |

-------------------------------------------------------------------------------- /test/semantics/policy/text_only.cow.html: -------------------------------------------------------------------------------- 1 | 2 | Text 3 | \ 4 | directive 5 | 6 | -------------------------------------------------------------------------------- /test/semantics/convert/bool_to_str.cow: -------------------------------------------------------------------------------- 1 | \cowel_to_str(true) 2 | \cowel_to_str(false) 3 | -------------------------------------------------------------------------------- /test/semantics/convert/str_to_str.cow: -------------------------------------------------------------------------------- 1 | \cowel_to_str(awoo) 2 | \cowel_to_str("chan") 3 | -------------------------------------------------------------------------------- /test/semantics/macro/new.cow.html: -------------------------------------------------------------------------------- 1 | awoo 2 | baka 3 | baka content baka 4 | otherwise 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/build 2 | node_modules 3 | 4 | .vscode/ 5 | playground/ 6 | 7 | .clangd 8 | -------------------------------------------------------------------------------- /test/semantics/convert/float_to_str.cow.html: -------------------------------------------------------------------------------- 1 | 1e+10 2 | 1e+10 3 | 10000000000 4 | 1e+10 5 | -------------------------------------------------------------------------------- /test/semantics/policy/text_as_html.cow.html: -------------------------------------------------------------------------------- 1 | 2 | Text 3 | \ 4 | directive 5 | 6 | -------------------------------------------------------------------------------- /test/semantics/policy/to_html.cow.html: -------------------------------------------------------------------------------- 1 | 2 | Text 3 | \ 4 | directive 5 | 6 | -------------------------------------------------------------------------------- /test/syntax/arguments/block.cow: -------------------------------------------------------------------------------- 1 | \d({}) 2 | \d({awoo}) 3 | \d({\x}) 4 | \d({{\{awoo\}}}) 5 | -------------------------------------------------------------------------------- /test/syntax/arguments/string.cow: -------------------------------------------------------------------------------- 1 | \d("") 2 | \d("awoo") 3 | \d("\x") 4 | \d("\"awoo\"") 5 | -------------------------------------------------------------------------------- /test/syntax/directive_as_argument.cow: -------------------------------------------------------------------------------- 1 | \a(x()) 2 | \b(y(){}) 3 | \c(z () {}) 4 | \d(w{}) 5 | -------------------------------------------------------------------------------- /test/semantics/macro/forwarding_named.cow.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/semantics/paragraphs.cow: -------------------------------------------------------------------------------- 1 | This is 2 | a paragraph. 3 | 4 | This is another paragraph. 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ulight"] 2 | path = ulight 3 | url = git@github.com:Eisenwave/ulight.git 4 | -------------------------------------------------------------------------------- /test/semantics/policy/paragraphs.cow.html: -------------------------------------------------------------------------------- 1 | 2 |

Text 3 | \ 4 | directive 5 |

6 | -------------------------------------------------------------------------------- /test/syntax/arguments/unquoted.cow: -------------------------------------------------------------------------------- 1 | \d(null) 2 | \d(true) 3 | \d(false) 4 | \d(awoo) 5 | \d(awoo-_) 6 | -------------------------------------------------------------------------------- /test/semantics/macro/forwarding_positional.cow.html: -------------------------------------------------------------------------------- 1 | 123 2 | 112 3 | c12 4 | 12d 5 | e1E 6 | 11f 7 | XYZ 8 | -------------------------------------------------------------------------------- /test/semantics/macro/put_paragraphs.cow.html: -------------------------------------------------------------------------------- 1 |

First paragraph. 2 |

3 |

Second paragraph.

4 | -------------------------------------------------------------------------------- /test/semantics/policy/no_invoke.cow.html: -------------------------------------------------------------------------------- 1 | 2 | Text 3 | \ 4 | \cowel_html_element(span){directive} 5 | 6 | -------------------------------------------------------------------------------- /test/semantics/U/ascii.cow: -------------------------------------------------------------------------------- 1 | \cowel_char_by_num{41}\cowel_char_by_num{0042}\cowel_char_by_num{0000000000043} 2 | -------------------------------------------------------------------------------- /test/semantics/alias.cow: -------------------------------------------------------------------------------- 1 | \cowel_alias(ch, char){cowel_char_by_name}\ 2 | \ch{DIGIT ZERO} 3 | \char{DIGIT ONE} 4 | -------------------------------------------------------------------------------- /test/semantics/paragraphs.cow.html: -------------------------------------------------------------------------------- 1 |

This is 2 | a paragraph. 3 |

4 |

This is another paragraph. 5 |

-------------------------------------------------------------------------------- /test/syntax/arguments/comments_2.cow: -------------------------------------------------------------------------------- 1 | \b( 2 | \: awoo 3 | text, 4 | \: awoo 5 | named = arg, 6 | ) 7 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/abs.cow.html: -------------------------------------------------------------------------------- 1 | 0 2 | 0 3 | 1 4 | 1 5 | 6 | infinity 7 | infinity 8 | 9 | NaN 10 | -------------------------------------------------------------------------------- /test/syntax/directive_names.cow: -------------------------------------------------------------------------------- 1 | \x 2 | \x_y 3 | \-x 4 | \x- 5 | \_x 6 | \x.y 7 | \xy 8 | \xy0 9 | \0xy 10 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/neg.cow.html: -------------------------------------------------------------------------------- 1 | -0 2 | 0 3 | -1 4 | 1 5 | 6 | infinity 7 | -infinity 8 | 9 | NaN 10 | -------------------------------------------------------------------------------- /test/semantics/document/empty.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/semantics/paragraphs_deep.cow: -------------------------------------------------------------------------------- 1 | \i{\cowel_paragraph_leave{}awoo} 2 | \cowel_paragraph_leave{}\cowel_text_as_html{End.} 3 | -------------------------------------------------------------------------------- /test/semantics/policy/source_as_text.cow.html: -------------------------------------------------------------------------------- 1 | 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | 7 | -------------------------------------------------------------------------------- /test/syntax/literals.cow: -------------------------------------------------------------------------------- 1 | \d( 2 | unit, 3 | null, 4 | true, 5 | false, 6 | 0, 7 | "", 8 | awoo, 9 | ) 10 | -------------------------------------------------------------------------------- /test/semantics/convert/reinterpret_as_int.cow.html: -------------------------------------------------------------------------------- 1 | 0 2 | 9223372036854775808 3 | 4609434218613702656 4 | 18444492273895866368 5 | -------------------------------------------------------------------------------- /test/semantics/policy/to_html.cow: -------------------------------------------------------------------------------- 1 | \cowel_to_html{ 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | } 7 | -------------------------------------------------------------------------------- /test/semantics/policy/highlight.cow.html: -------------------------------------------------------------------------------- 1 | 2 | Text 3 | \ 4 | directive 5 | 6 | -------------------------------------------------------------------------------- /test/semantics/policy/no_invoke.cow: -------------------------------------------------------------------------------- 1 | \cowel_no_invoke{ 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | } 7 | -------------------------------------------------------------------------------- /test/semantics/policy/paragraphs.cow: -------------------------------------------------------------------------------- 1 | \cowel_paragraphs{ 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | } 7 | -------------------------------------------------------------------------------- /test/semantics/policy/text_only.cow: -------------------------------------------------------------------------------- 1 | \cowel_text_only{ 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | } 7 | -------------------------------------------------------------------------------- /test/semantics/comments.cow: -------------------------------------------------------------------------------- 1 | \:Comment 2 | \: xyz 3 | \: { awoo 4 | \dfn\:} 5 | \: nested \: comment 6 | trailing \: comment 7 | \: \dfn(){} 8 | -------------------------------------------------------------------------------- /test/semantics/logical/short_circuit.cow: -------------------------------------------------------------------------------- 1 | \cowel_and(false, cowel_eq(0, cowel_div(0, 0))) 2 | \cowel_or(true, cowel_eq(0, cowel_div(0, 0))) 3 | -------------------------------------------------------------------------------- /test/semantics/policy/highlight.cow: -------------------------------------------------------------------------------- 1 | \cowel_highlight(cpp){ 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | } 7 | -------------------------------------------------------------------------------- /test/syntax/comments.cow: -------------------------------------------------------------------------------- 1 | \:Comment 2 | \: xyz 3 | \: { awoo 4 | \dfn\:} 5 | \: nested \: comment 6 | trailing \: comment 7 | \: \dfn(){} 8 | -------------------------------------------------------------------------------- /test/semantics/highlight.cow.html: -------------------------------------------------------------------------------- 1 | div 2 | div 3 | mov 4 | mov 5 | -------------------------------------------------------------------------------- /test/semantics/macro/put_paragraphs.cow: -------------------------------------------------------------------------------- 1 | \cowel_macro(ps){\cowel_paragraphs{\cowel_put}}\ 2 | \ps{First paragraph. 3 | 4 | Second paragraph.} 5 | -------------------------------------------------------------------------------- /test/semantics/policy/source_as_text.cow: -------------------------------------------------------------------------------- 1 | \cowel_source_as_text{ 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | } 7 | -------------------------------------------------------------------------------- /test/semantics/policy/text_as_html.cow: -------------------------------------------------------------------------------- 1 | \cowel_text_as_html{ 2 | \: Comment 3 | Text 4 | \\ 5 | \cowel_html_element(span){directive} 6 | } 7 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/sqrt.cow.html: -------------------------------------------------------------------------------- 1 | 0 2 | -0 3 | 1 4 | NaN 5 | 6 | 2 7 | 3 8 | 4 9 | 10 10 | 11 | NaN 12 | infinity 13 | 14 | NaN 15 | -------------------------------------------------------------------------------- /test/semantics/macro/forwarding_named.cow: -------------------------------------------------------------------------------- 1 | \cowel_macro(d){\cowel_html_element(div,(...)){\cowel_put}}\ 2 | \d(id = awoo, hidden = hidden){inner text} 3 | -------------------------------------------------------------------------------- /assets/light-dark.js: -------------------------------------------------------------------------------- 1 | const theme = localStorage.getItem("cowel-theme"); 2 | if (theme !== null) { 3 | document.documentElement.className = theme; 4 | } 5 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/ceil.cow.html: -------------------------------------------------------------------------------- 1 | -infinity 2 | -1 3 | -0 4 | -0 5 | -0 6 | -0 7 | 0 8 | 1 9 | 1 10 | 1 11 | 1 12 | infinity 13 | 14 | NaN 15 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/floor.cow.html: -------------------------------------------------------------------------------- 1 | -infinity 2 | -1 3 | -1 4 | -1 5 | -1 6 | -0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 1 12 | infinity 13 | 14 | NaN 15 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/nearest.cow.html: -------------------------------------------------------------------------------- 1 | -infinity 2 | -1 3 | -1 4 | -0 5 | -0 6 | -0 7 | 0 8 | 0 9 | 0 10 | 1 11 | 1 12 | infinity 13 | 14 | NaN 15 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/trunc.cow.html: -------------------------------------------------------------------------------- 1 | -infinity 2 | -1 3 | -0 4 | -0 5 | -0 6 | -0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 1 12 | infinity 13 | 14 | NaN 15 | -------------------------------------------------------------------------------- /test/semantics/codeblock/trim.cow: -------------------------------------------------------------------------------- 1 | \codeblock(x){abc} 2 | \codeblock(x){ 3 | abc 4 | } 5 | 6 | \codeblock(x){xxx} 7 | \codeblock(x){ 8 | xxx 9 | } 10 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/max.cow.html: -------------------------------------------------------------------------------- 1 | 1 2 | 3 | 3 4 | 5 | 0 6 | -0 7 | 0 8 | 0 9 | 10 | 1 11 | 1 12 | 0 13 | infinity 14 | 15 | NaN 16 | NaN 17 | NaN 18 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/min.cow.html: -------------------------------------------------------------------------------- 1 | 1 2 | 3 | -5 4 | 5 | 0 6 | -0 7 | -0 8 | -0 9 | 10 | 0 11 | 0 12 | -infinity 13 | 0 14 | 15 | NaN 16 | NaN 17 | NaN 18 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/nearest_away_zero.cow.html: -------------------------------------------------------------------------------- 1 | -infinity 2 | -1 3 | -1 4 | -1 5 | -0 6 | -0 7 | 0 8 | 0 9 | 1 10 | 1 11 | 1 12 | infinity 13 | 14 | NaN 15 | -------------------------------------------------------------------------------- /test/semantics/convert/float_to_str.cow: -------------------------------------------------------------------------------- 1 | \cowel_to_str(1e10) 2 | \cowel_to_str(1e10, format=splice) 3 | \cowel_to_str(1e10, format=fixed) 4 | \cowel_to_str(1e10, format=scientific) 5 | -------------------------------------------------------------------------------- /test/semantics/macro/multiline.cow: -------------------------------------------------------------------------------- 1 | \cowel_macro(hl){\ 2 | \cowel_paragraph_enter\ 3 | \cowel_highlight_as(cowel_put{0}){\cowel_put}\ 4 | }\ 5 | \cowel_highlight(cpp){\hl(keyword){int}} 6 | -------------------------------------------------------------------------------- /test/semantics/convert/reinterpret_as_int.cow: -------------------------------------------------------------------------------- 1 | \cowel_reinterpret_as_int(0.0) 2 | \cowel_reinterpret_as_int(-0.0) 3 | \cowel_reinterpret_as_int(1.5) 4 | \cowel_reinterpret_as_int(cowel_mul(infinity, 0.0)) 5 | -------------------------------------------------------------------------------- /test/semantics/codeblock/trim.html: -------------------------------------------------------------------------------- 1 | abc 2 | abc 3 | 4 | xxx 5 | xxx 6 | -------------------------------------------------------------------------------- /test/semantics/highlight.cow: -------------------------------------------------------------------------------- 1 | \cowel_highlight(html){div} 2 | \cowel_highlight(lang=html){\cowel_highlight_phantom{<}div} 3 | \cowel_highlight(nasm){mov} 4 | \cowel_highlight(nasm){mov\cowel_highlight_phantom{:}} 5 | -------------------------------------------------------------------------------- /test/semantics/compare/ge.cow.html: -------------------------------------------------------------------------------- 1 | true 2 | false 3 | true 4 | true 5 | 6 | true 7 | true 8 | false 9 | true 10 | true 11 | true 12 | true 13 | 14 | true 15 | true 16 | false 17 | true 18 | false 19 | true 20 | -------------------------------------------------------------------------------- /test/semantics/compare/le.cow.html: -------------------------------------------------------------------------------- 1 | true 2 | true 3 | false 4 | true 5 | 6 | true 7 | false 8 | true 9 | true 10 | true 11 | true 12 | true 13 | 14 | true 15 | false 16 | true 17 | true 18 | true 19 | false 20 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/basic.cow.html: -------------------------------------------------------------------------------- 1 | 2 2 | -2 3 | 4 | -2 5 | 2 6 | 7 | 2 8 | 2 9 | 10 | 8 11 | 10 12 | 15 13 | 10 14 | 15 | 8 16 | 6 17 | 4 18 | -6 19 | 20 | 8 21 | 16 22 | 80 23 | 16 24 | 25 | 4 26 | 0 27 | -------------------------------------------------------------------------------- /test/semantics/compare/gt.cow.html: -------------------------------------------------------------------------------- 1 | false 2 | false 3 | true 4 | false 5 | 6 | false 7 | true 8 | false 9 | false 10 | false 11 | false 12 | false 13 | 14 | false 15 | true 16 | false 17 | false 18 | false 19 | true 20 | -------------------------------------------------------------------------------- /test/semantics/compare/lt.cow.html: -------------------------------------------------------------------------------- 1 | false 2 | true 3 | false 4 | false 5 | 6 | false 7 | false 8 | true 9 | false 10 | false 11 | false 12 | false 13 | 14 | false 15 | false 16 | true 17 | false 18 | true 19 | false 20 | -------------------------------------------------------------------------------- /test/semantics/convert/reinterpret_as_float.cow: -------------------------------------------------------------------------------- 1 | \cowel_reinterpret_as_float(0) 2 | \cowel_reinterpret_as_float(0x8000000000000000) 3 | \cowel_reinterpret_as_float(0x3ff8000000000000) 4 | \cowel_reinterpret_as_float(0xffffffffffffffff) 5 | -------------------------------------------------------------------------------- /test/semantics/logical/ops.cow.html: -------------------------------------------------------------------------------- 1 | false 2 | true 3 | 4 | true 5 | false 6 | true 7 | false 8 | false 9 | false 10 | true 11 | false 12 | 13 | true 14 | false 15 | true 16 | true 17 | true 18 | false 19 | true 20 | true 21 | -------------------------------------------------------------------------------- /test/syntax/floats.cow: -------------------------------------------------------------------------------- 1 | \d( 2 | 0., 3 | .0, 4 | 0.0, 5 | 0e0, 6 | 0.e0, 7 | .0e0, 8 | 0.0e0, 9 | 0e0, 10 | 0e+0, 11 | 0e-0, 12 | 0E0, 13 | 0E+0, 14 | 0E-0, 15 | 123.456e789, 16 | -123.456e789, 17 | ) 18 | -------------------------------------------------------------------------------- /test/semantics/splice/floats.cow.html: -------------------------------------------------------------------------------- 1 | 0.1 2 | 0.1 3 | 4 | 1125899906842624.2 5 | 1125899906842624.2 6 | 7 | 100 8 | 1000 9 | 1e+4 10 | 1e+5 11 | 1e+9 12 | 1e+10 13 | 1e-10 14 | 1e+100 15 | 1e+100 16 | 17 | infinity 18 | -infinity 19 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/abs.cow: -------------------------------------------------------------------------------- 1 | \cowel_abs(0.0) 2 | \cowel_abs(-0.0) 3 | \cowel_abs(1.0) 4 | \cowel_abs(-1.0) 5 | 6 | \cowel_abs(-infinity) 7 | \cowel_abs(infinity) 8 | 9 | \cowel_abs(cowel_reinterpret_as_float(0x7ff8000000000000)) 10 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/neg.cow: -------------------------------------------------------------------------------- 1 | \cowel_neg(0.0) 2 | \cowel_neg(-0.0) 3 | \cowel_neg(1.0) 4 | \cowel_neg(-1.0) 5 | 6 | \cowel_neg(-infinity) 7 | \cowel_neg(infinity) 8 | 9 | \cowel_neg(cowel_reinterpret_as_float(0x7ff8000000000000)) 10 | -------------------------------------------------------------------------------- /include/cowel/cedilla/README.md: -------------------------------------------------------------------------------- 1 | # `cowel/cp` 2 | 3 | The files here are generated from https://github.com/cor3ntin/ext-unicode-db, 4 | with comments for suppressing linting and code formatting added. 5 | 6 | See the `LICENSE` file for license information. 7 | -------------------------------------------------------------------------------- /assets/important.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/semantics/compare/eq.cow.html: -------------------------------------------------------------------------------- 1 | true 2 | 3 | true 4 | 5 | true 6 | false 7 | false 8 | true 9 | 10 | true 11 | false 12 | false 13 | true 14 | 15 | true 16 | false 17 | false 18 | true 19 | true 20 | true 21 | 22 | true 23 | false 24 | false 25 | true 26 | -------------------------------------------------------------------------------- /test/semantics/compare/ne.cow.html: -------------------------------------------------------------------------------- 1 | false 2 | 3 | false 4 | 5 | false 6 | true 7 | true 8 | false 9 | 10 | false 11 | true 12 | true 13 | false 14 | 15 | false 16 | true 17 | true 18 | false 19 | false 20 | false 21 | 22 | false 23 | true 24 | true 25 | false 26 | -------------------------------------------------------------------------------- /assets/decision.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/cpp/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "ulight/ulight.h" 6 | 7 | int main(int argc, char** argv) 8 | { 9 | std::setlocale(LC_ALL, ".UTF8"); 10 | ::testing::InitGoogleTest(&argc, argv); 11 | return RUN_ALL_TESTS(); 12 | } 13 | -------------------------------------------------------------------------------- /include/cowel/util/function_ref.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_FUNCTION_REF_HPP 2 | #define COWEL_FUNCTION_REF_HPP 3 | 4 | #include "ulight/function_ref.hpp" 5 | 6 | namespace cowel { 7 | 8 | template 9 | using Function_Ref = ulight::Function_Ref; 10 | 11 | } // namespace cowel 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/util/check-clang-tidy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SOURCES=$(find src -type f \( -name "*.cpp" -o -name "*.hpp" \) ! -name "*autogenerated*") 4 | INCLUDES=$(find include -type f -name "*.hpp" ! -name "*autogenerated*") 5 | 6 | COMMAND="clang-tidy-19 $SOURCES $INCLUDES -p build" 7 | 8 | echo $COMMAND 9 | $COMMAND 10 | -------------------------------------------------------------------------------- /test/semantics/macro/new.cow: -------------------------------------------------------------------------------- 1 | \cowel_macro(identity){\cowel_put}\ 2 | \cowel_macro(arg0){\cowel_put{0}}\ 3 | \cowel_macro(arg0x){\cowel_put{0} \cowel_put \cowel_put{0}}\ 4 | \cowel_macro(arg0_else){\cowel_put(else={otherwise}){0}}\ 5 | \ 6 | \identity{awoo} 7 | \arg0(baka) 8 | \arg0x(baka){content} 9 | \arg0_else 10 | -------------------------------------------------------------------------------- /test/semantics/paragraph_control.cow.html: -------------------------------------------------------------------------------- 1 |

First paragraph. 2 |

3 |

Second paragraph. 4 |

5 |

third paragraph. 6 |

7 |

fourth paragraph. 8 |

9 |

Fifth

paragraph. 10 |

11 |

Sixth paragraph. 12 |

13 |

Seventh paragraph. 14 |

15 |

Eight paragraph.

16 | -------------------------------------------------------------------------------- /assets/delete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/sqrt.cow: -------------------------------------------------------------------------------- 1 | \cowel_sqrt(0.0) 2 | \cowel_sqrt(-0.0) 3 | \cowel_sqrt(1.0) 4 | \cowel_sqrt(-1.0) 5 | 6 | \cowel_sqrt(4.0) 7 | \cowel_sqrt(9.0) 8 | \cowel_sqrt(16.0) 9 | \cowel_sqrt(100.0) 10 | 11 | \cowel_sqrt(-infinity) 12 | \cowel_sqrt(infinity) 13 | 14 | \cowel_sqrt(cowel_reinterpret_as_float(0x7ff8000000000000)) 15 | -------------------------------------------------------------------------------- /assets/insert.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/cowel/util/README.md: -------------------------------------------------------------------------------- 1 | # `cowel/util` 2 | 3 | The headers in this directory are for portable utilities 4 | that could be practically plugged into any other project. 5 | 6 | Ideally, the headers in this directory should have no dependencies, 7 | other than on the standard library. 8 | With the exception of `fwd.hpp`, 9 | no headers outside `util/` should be included. 10 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/ceil.cow: -------------------------------------------------------------------------------- 1 | \cowel_ceil(-infinity) 2 | \cowel_ceil(-1.0) 3 | \cowel_ceil(-0.75) 4 | \cowel_ceil(-0.5) 5 | \cowel_ceil(-0.25) 6 | \cowel_ceil(-0.0) 7 | \cowel_ceil(0.0) 8 | \cowel_ceil(0.25) 9 | \cowel_ceil(0.5) 10 | \cowel_ceil(0.75) 11 | \cowel_ceil(1.0) 12 | \cowel_ceil(infinity) 13 | 14 | \cowel_ceil(cowel_reinterpret_as_float(0x7ff8000000000000)) 15 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/floor.cow: -------------------------------------------------------------------------------- 1 | \cowel_floor(-infinity) 2 | \cowel_floor(-1.0) 3 | \cowel_floor(-0.75) 4 | \cowel_floor(-0.5) 5 | \cowel_floor(-0.25) 6 | \cowel_floor(-0.0) 7 | \cowel_floor(0.0) 8 | \cowel_floor(0.25) 9 | \cowel_floor(0.5) 10 | \cowel_floor(0.75) 11 | \cowel_floor(1.0) 12 | \cowel_floor(infinity) 13 | 14 | \cowel_floor(cowel_reinterpret_as_float(0x7ff8000000000000)) 15 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/trunc.cow: -------------------------------------------------------------------------------- 1 | \cowel_trunc(-infinity) 2 | \cowel_trunc(-1.0) 3 | \cowel_trunc(-0.75) 4 | \cowel_trunc(-0.5) 5 | \cowel_trunc(-0.25) 6 | \cowel_trunc(-0.0) 7 | \cowel_trunc(0.0) 8 | \cowel_trunc(0.25) 9 | \cowel_trunc(0.5) 10 | \cowel_trunc(0.75) 11 | \cowel_trunc(1.0) 12 | \cowel_trunc(infinity) 13 | 14 | \cowel_trunc(cowel_reinterpret_as_float(0x7ff8000000000000)) 15 | -------------------------------------------------------------------------------- /assets/sync.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/diff.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /assets/tip.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/nearest.cow: -------------------------------------------------------------------------------- 1 | \cowel_nearest(-infinity) 2 | \cowel_nearest(-1.0) 3 | \cowel_nearest(-0.75) 4 | \cowel_nearest(-0.5) 5 | \cowel_nearest(-0.25) 6 | \cowel_nearest(-0.0) 7 | \cowel_nearest(0.0) 8 | \cowel_nearest(0.25) 9 | \cowel_nearest(0.5) 10 | \cowel_nearest(0.75) 11 | \cowel_nearest(1.0) 12 | \cowel_nearest(infinity) 13 | 14 | \cowel_nearest(cowel_reinterpret_as_float(0x7ff8000000000000)) 15 | -------------------------------------------------------------------------------- /test/semantics/splice/ints.cow.html: -------------------------------------------------------------------------------- 1 | 255 2 | 255 3 | 255 4 | 255 5 | 6 | 170141183460469231731687303715884105727 7 | -170141183460469231731687303715884105728 8 | 170141183460469231731687303715884105727 9 | -170141183460469231731687303715884105728 10 | 170141183460469231731687303715884105727 11 | -170141183460469231731687303715884105728 12 | 170141183460469231731687303715884105727 13 | -170141183460469231731687303715884105728 14 | -------------------------------------------------------------------------------- /test/semantics/compare/ge.cow: -------------------------------------------------------------------------------- 1 | \cowel_ge(0, 0) 2 | \cowel_ge(0, 1) 3 | \cowel_ge(1, 0) 4 | \cowel_ge(1, 1) 5 | 6 | \cowel_ge(0.0, 0.0) 7 | \cowel_ge(1.0, 0.0) 8 | \cowel_ge(0.0, 1.0) 9 | \cowel_ge(1.0, 1.0) 10 | \cowel_ge(-0.0, 0.0) 11 | \cowel_ge(0.0, -0.0) 12 | \cowel_ge(-0.0, -0.0) 13 | 14 | \cowel_ge("", "") 15 | \cowel_ge("x", "") 16 | \cowel_ge("", "x") 17 | \cowel_ge("x", "x") 18 | \cowel_ge("x", "y") 19 | \cowel_ge("y", "x") 20 | -------------------------------------------------------------------------------- /test/semantics/compare/gt.cow: -------------------------------------------------------------------------------- 1 | \cowel_gt(0, 0) 2 | \cowel_gt(0, 1) 3 | \cowel_gt(1, 0) 4 | \cowel_gt(1, 1) 5 | 6 | \cowel_gt(0.0, 0.0) 7 | \cowel_gt(1.0, 0.0) 8 | \cowel_gt(0.0, 1.0) 9 | \cowel_gt(1.0, 1.0) 10 | \cowel_gt(-0.0, 0.0) 11 | \cowel_gt(0.0, -0.0) 12 | \cowel_gt(-0.0, -0.0) 13 | 14 | \cowel_gt("", "") 15 | \cowel_gt("x", "") 16 | \cowel_gt("", "x") 17 | \cowel_gt("x", "x") 18 | \cowel_gt("x", "y") 19 | \cowel_gt("y", "x") 20 | -------------------------------------------------------------------------------- /test/semantics/compare/le.cow: -------------------------------------------------------------------------------- 1 | \cowel_le(0, 0) 2 | \cowel_le(0, 1) 3 | \cowel_le(1, 0) 4 | \cowel_le(1, 1) 5 | 6 | \cowel_le(0.0, 0.0) 7 | \cowel_le(1.0, 0.0) 8 | \cowel_le(0.0, 1.0) 9 | \cowel_le(1.0, 1.0) 10 | \cowel_le(-0.0, 0.0) 11 | \cowel_le(0.0, -0.0) 12 | \cowel_le(-0.0, -0.0) 13 | 14 | \cowel_le("", "") 15 | \cowel_le("x", "") 16 | \cowel_le("", "x") 17 | \cowel_le("x", "x") 18 | \cowel_le("x", "y") 19 | \cowel_le("y", "x") 20 | -------------------------------------------------------------------------------- /test/semantics/compare/lt.cow: -------------------------------------------------------------------------------- 1 | \cowel_lt(0, 0) 2 | \cowel_lt(0, 1) 3 | \cowel_lt(1, 0) 4 | \cowel_lt(1, 1) 5 | 6 | \cowel_lt(0.0, 0.0) 7 | \cowel_lt(1.0, 0.0) 8 | \cowel_lt(0.0, 1.0) 9 | \cowel_lt(1.0, 1.0) 10 | \cowel_lt(-0.0, 0.0) 11 | \cowel_lt(0.0, -0.0) 12 | \cowel_lt(-0.0, -0.0) 13 | 14 | \cowel_lt("", "") 15 | \cowel_lt("x", "") 16 | \cowel_lt("", "x") 17 | \cowel_lt("x", "x") 18 | \cowel_lt("x", "y") 19 | \cowel_lt("y", "x") 20 | -------------------------------------------------------------------------------- /assets/example.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/cpp/document_file_testing.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_TEST_DOCUMENT_FILE_TESTING_HPP 2 | #define COWEL_TEST_DOCUMENT_FILE_TESTING_HPP 3 | 4 | #include 5 | 6 | #include "compilation_stage.hpp" 7 | 8 | namespace cowel { 9 | 10 | [[nodiscard]] 11 | bool test_for_success( 12 | std::u8string_view file, 13 | Compilation_Stage until_stage = Compilation_Stage::process 14 | ); 15 | 16 | } // namespace cowel 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /assets/dark-mode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/semantics/splice/floats.cow: -------------------------------------------------------------------------------- 1 | \cowel_pos(0.1) 2 | \cowel_pos(0.1000000000000000055511151231257827021181583404541015625) 3 | 4 | \cowel_pos(1125899906842624.2) 5 | \cowel_pos(1125899906842624.25) 6 | 7 | \cowel_pos(1e2) 8 | \cowel_pos(1e3) 9 | \cowel_pos(1e4) 10 | \cowel_pos(1e5) 11 | \cowel_pos(1e9) 12 | \cowel_pos(1e10) 13 | \cowel_pos(1e-10) 14 | \cowel_pos(10e99) 15 | \cowel_pos(1e100) 16 | 17 | \cowel_pos(infinity) 18 | \cowel_pos(-infinity) 19 | -------------------------------------------------------------------------------- /assets/quote.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/semantics/macro/forwarding_positional.cow: -------------------------------------------------------------------------------- 1 | \cowel_macro(cat3){\cowel_put{0}\cowel_put{1}\cowel_put{2}}\ 2 | \cowel_macro(a){\cat3(...)}\ 3 | \cowel_macro(b){\cat3(cowel_put{0}, ...)}\ 4 | \cowel_macro(c){\cat3(c, ...)}\ 5 | \cowel_macro(d){\cat3(..., d)}\ 6 | \cowel_macro(e){\cat3(e, ..., E)}\ 7 | \cowel_macro(f){\cat3(..., ..., f)}\ 8 | \cowel_macro(g){\cat3(..., X, Y, Z)}\ 9 | \a(1, 2, 3) 10 | \b(1, 2) 11 | \c(1, 2) 12 | \d(1, 2) 13 | \e(1) 14 | \f(1) 15 | \g 16 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/basic.cow: -------------------------------------------------------------------------------- 1 | \cowel_pos( 2) 2 | \cowel_pos(-2) 3 | 4 | \cowel_neg( 2) 5 | \cowel_neg(-2) 6 | 7 | \cowel_abs( 2) 8 | \cowel_abs(-2) 9 | 10 | \cowel_add(8) 11 | \cowel_add(8, 2) 12 | \cowel_add(8, 2, 5) 13 | \cowel_add(2, 8) 14 | 15 | \cowel_sub(8) 16 | \cowel_sub(8, 2) 17 | \cowel_sub(8, 2, 2) 18 | \cowel_sub(2, 8) 19 | 20 | \cowel_mul(8) 21 | \cowel_mul(8, 2) 22 | \cowel_mul(8, 2, 5) 23 | \cowel_mul(2, 8) 24 | 25 | \cowel_div_to_zero(8, 2) 26 | \cowel_div_to_zero(2, 8) 27 | -------------------------------------------------------------------------------- /test/semantics/paragraph_control.cow: -------------------------------------------------------------------------------- 1 | First paragraph. 2 | 3 | Second paragraph. 4 | 5 | \cowel_paragraph_enter third paragraph. 6 | 7 | \cowel_paragraph_leave fourth paragraph. 8 | 9 | Fifth \cowel_paragraph_leave paragraph. 10 | 11 | \cowel_paragraph_enter\cowel_paragraph_enter\cowel_paragraph_enter{}Sixth paragraph. 12 | 13 | \cowel_paragraph_leave\cowel_paragraph_leave\cowel_paragraph_leave{}Seventh paragraph. 14 | 15 | Eight paragraph.\cowel_paragraph_leave\cowel_paragraph_leave\cowel_paragraph_leave 16 | -------------------------------------------------------------------------------- /include/cowel/util/annotation_span.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_ANNOTATION_SPAN_HPP 2 | #define COWEL_ANNOTATION_SPAN_HPP 3 | 4 | #include 5 | 6 | #include "cowel/fwd.hpp" 7 | 8 | namespace cowel { 9 | 10 | template 11 | struct Annotation_Span { 12 | std::size_t begin; 13 | std::size_t length; 14 | T value; 15 | 16 | [[nodiscard]] 17 | constexpr std::size_t end() const 18 | { 19 | return begin + length; 20 | } 21 | }; 22 | 23 | } // namespace cowel 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /assets/warning.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/note.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/cowel-bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: COWEL Bug 3 | about: Something went wrong when processing a COWEL document 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the bug 11 | 12 | 13 | ### Steps to reproduce 14 | 15 | ```tex 16 | \cowel_markup_here{...} 17 | ``` 18 | 19 | ### Environment 20 | 21 | -------------------------------------------------------------------------------- /test/semantics/compare/eq.cow: -------------------------------------------------------------------------------- 1 | \cowel_eq(unit, unit) 2 | 3 | \cowel_eq(null, null) 4 | 5 | \cowel_eq(false, false) 6 | \cowel_eq(true, false) 7 | \cowel_eq(false, true) 8 | \cowel_eq(true, true) 9 | 10 | \cowel_eq(0, 0) 11 | \cowel_eq(0, 1) 12 | \cowel_eq(1, 0) 13 | \cowel_eq(1, 1) 14 | 15 | \cowel_eq(0.0, 0.0) 16 | \cowel_eq(1.0, 0.0) 17 | \cowel_eq(0.0, 1.0) 18 | \cowel_eq(1.0, 1.0) 19 | \cowel_eq(-0.0, 0.0) 20 | \cowel_eq(-0.0, -0.0) 21 | 22 | \cowel_eq("", "") 23 | \cowel_eq("x", "") 24 | \cowel_eq("", "x") 25 | \cowel_eq("x", "x") 26 | -------------------------------------------------------------------------------- /test/semantics/compare/ne.cow: -------------------------------------------------------------------------------- 1 | \cowel_ne(unit, unit) 2 | 3 | \cowel_ne(null, null) 4 | 5 | \cowel_ne(false, false) 6 | \cowel_ne(true, false) 7 | \cowel_ne(false, true) 8 | \cowel_ne(true, true) 9 | 10 | \cowel_ne(0, 0) 11 | \cowel_ne(0, 1) 12 | \cowel_ne(1, 0) 13 | \cowel_ne(1, 1) 14 | 15 | \cowel_ne(0.0, 0.0) 16 | \cowel_ne(1.0, 0.0) 17 | \cowel_ne(0.0, 1.0) 18 | \cowel_ne(1.0, 1.0) 19 | \cowel_ne(-0.0, 0.0) 20 | \cowel_ne(-0.0, -0.0) 21 | 22 | \cowel_ne("", "") 23 | \cowel_ne("x", "") 24 | \cowel_ne("", "x") 25 | \cowel_ne("x", "x") 26 | -------------------------------------------------------------------------------- /assets/light-mode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/cpp/util/tty.cpp: -------------------------------------------------------------------------------- 1 | #ifdef __unix__ 2 | #include "stdio.h" // NOLINT for fileno 3 | #include 4 | #include 5 | #endif 6 | 7 | #include "cowel/util/tty.hpp" 8 | 9 | namespace cowel { 10 | 11 | bool is_tty(std::FILE* file) noexcept 12 | { 13 | #ifdef __unix__ 14 | return isatty(fileno(file)); 15 | #else 16 | return false; 17 | #endif 18 | } 19 | 20 | const bool is_stdin_tty = is_tty(stdin); 21 | const bool is_stdout_tty = is_tty(stdout); 22 | const bool is_stderr_tty = is_tty(stderr); 23 | 24 | } // namespace cowel 25 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/nearest_away_zero.cow: -------------------------------------------------------------------------------- 1 | \cowel_nearest_away_zero(-infinity) 2 | \cowel_nearest_away_zero(-1.0) 3 | \cowel_nearest_away_zero(-0.75) 4 | \cowel_nearest_away_zero(-0.5) 5 | \cowel_nearest_away_zero(-0.25) 6 | \cowel_nearest_away_zero(-0.0) 7 | \cowel_nearest_away_zero(0.0) 8 | \cowel_nearest_away_zero(0.25) 9 | \cowel_nearest_away_zero(0.5) 10 | \cowel_nearest_away_zero(0.75) 11 | \cowel_nearest_away_zero(1.0) 12 | \cowel_nearest_away_zero(infinity) 13 | 14 | \cowel_nearest_away_zero(cowel_reinterpret_as_float(0x7ff8000000000000)) 15 | -------------------------------------------------------------------------------- /src/util/transform-package-json.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/node 2 | 3 | import { readFile, writeFile } from "fs/promises"; 4 | import { argv } from "process"; 5 | 6 | if (argv.length < 4) { 7 | console.error(`Usage: node ${argv[1]} `); 8 | process.exit(1); 9 | } 10 | 11 | const [inputPath, outputPath] = argv.slice(2); 12 | 13 | const content = await readFile(inputPath, "utf-8"); 14 | const json = JSON.parse(content); 15 | 16 | delete json.devDependencies; 17 | 18 | await writeFile(outputPath, JSON.stringify(json, null, 2) + "\n"); 19 | -------------------------------------------------------------------------------- /assets/abstract.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/cowel/policy/factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_POLICY_FACTORY_HPP 2 | #define COWEL_POLICY_FACTORY_HPP 3 | 4 | #include "cowel/policy/content_policy.hpp" 5 | #include "cowel/policy/html.hpp" 6 | 7 | namespace cowel { 8 | 9 | [[nodiscard]] 10 | inline HTML_Content_Policy ensure_html_policy(Content_Policy& out) 11 | { 12 | if (auto* const policy = dynamic_cast(&out)) { 13 | return HTML_Content_Policy { policy->parent() }; 14 | } 15 | return HTML_Content_Policy { out }; 16 | } 17 | 18 | } // namespace cowel 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/cowel/util/code_point_names.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_CODE_POINT_NAMES_HPP 2 | #define COWEL_CODE_POINT_NAMES_HPP 3 | 4 | #include 5 | 6 | namespace cowel { 7 | 8 | /// @brief Returns a Unicode code point by its character name, 9 | /// or one of its "control", "alternate", or "correction" aliases. 10 | /// 11 | /// If the name does not match that of any code point in the database, 12 | /// `char32_t(-1)` is returned. 13 | [[nodiscard]] 14 | char32_t code_point_by_name(std::u8string_view name) noexcept; 15 | 16 | } // namespace cowel 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/max.cow: -------------------------------------------------------------------------------- 1 | \cowel_max(1) 2 | 3 | \cowel_max(1, 0, -5, 3) 4 | 5 | \cowel_max(0.0, 0.0) 6 | \cowel_max(-0.0, -0.0) 7 | \cowel_max(-0.0, 0.0) 8 | \cowel_max(0.0, -0.0) 9 | 10 | \cowel_max(0.0, 1.0) 11 | \cowel_max(1.0, 0.0) 12 | \cowel_max(0.0, -infinity) 13 | \cowel_max(0.0, infinity) 14 | 15 | \cowel_max(0.0, cowel_reinterpret_as_float(0x7ff8000000000000)) 16 | \cowel_max(cowel_reinterpret_as_float(0x7ff8000000000000), cowel_reinterpret_as_float(0x7ff8000000000000)) 17 | \cowel_max(infinity, cowel_reinterpret_as_float(0x7ff8000000000000)) 18 | -------------------------------------------------------------------------------- /test/semantics/arithmetic/min.cow: -------------------------------------------------------------------------------- 1 | \cowel_min(1) 2 | 3 | \cowel_min(1, 0, -5, 3) 4 | 5 | \cowel_min(0.0, 0.0) 6 | \cowel_min(-0.0, -0.0) 7 | \cowel_min(-0.0, 0.0) 8 | \cowel_min(0.0, -0.0) 9 | 10 | \cowel_min(0.0, 1.0) 11 | \cowel_min(1.0, 0.0) 12 | \cowel_min(0.0, -infinity) 13 | \cowel_min(0.0, infinity) 14 | 15 | \cowel_min(0.0, cowel_reinterpret_as_float(0x7ff8000000000000)) 16 | \cowel_min(cowel_reinterpret_as_float(0x7ff8000000000000), cowel_reinterpret_as_float(0x7ff8000000000000)) 17 | \cowel_min(infinity, cowel_reinterpret_as_float(0x7ff8000000000000)) 18 | -------------------------------------------------------------------------------- /test/semantics/logical/ops.cow: -------------------------------------------------------------------------------- 1 | \cowel_not(true) 2 | \cowel_not(false) 3 | 4 | \cowel_and(true) 5 | \cowel_and(false) 6 | \cowel_and(true, true) 7 | \cowel_and(true, false) 8 | \cowel_and(false, true) 9 | \cowel_and(false, false) 10 | \cowel_and(true, true, true, true, true) 11 | \cowel_and(true, true, false, true, true) 12 | 13 | \cowel_or(true) 14 | \cowel_or(false) 15 | \cowel_or(true, true) 16 | \cowel_or(true, false) 17 | \cowel_or(false, true) 18 | \cowel_or(false, false) 19 | \cowel_or(true, true, true, true, true) 20 | \cowel_or(true, true, false, true, true) 21 | -------------------------------------------------------------------------------- /assets/todo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/cpp/compilation_stage.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_COMPILATION_STAGE_HPP 2 | #define COWEL_COMPILATION_STAGE_HPP 3 | 4 | #include 5 | 6 | #include "cowel/fwd.hpp" 7 | 8 | namespace cowel { 9 | 10 | enum struct Compilation_Stage : Default_Underlying { // 11 | load_file, 12 | parse, 13 | process 14 | }; 15 | 16 | [[nodiscard]] 17 | constexpr std::strong_ordering operator<=>(Compilation_Stage a, Compilation_Stage b) 18 | { 19 | return static_cast(a) <=> static_cast(b); 20 | } 21 | 22 | } // namespace cowel 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /include/cowel/theme_to_css.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_THEME_TO_CSS_HPP 2 | #define COWEL_THEME_TO_CSS_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ulight/ulight.hpp" 10 | 11 | namespace cowel { 12 | 13 | bool theme_to_css( 14 | std::pmr::vector& out, 15 | std::u8string_view theme_json, 16 | std::pmr::memory_resource* memory 17 | ); 18 | 19 | [[nodiscard]] 20 | std::optional highlight_type_by_long_string(std::u8string_view str); 21 | 22 | } // namespace cowel 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "ESNext", 5 | "incremental": true, 6 | "tsBuildInfoFile": "build/.tsbuildinfo", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "resolveJsonModule": true, 12 | "moduleResolution": "node", 13 | "outDir": "build/npm", 14 | "rootDirs": [ 15 | "src/main/ts" 16 | ] 17 | }, 18 | "include": [ 19 | "src/main" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/main/cpp/wasm_stubs.cpp: -------------------------------------------------------------------------------- 1 | // Necessary to prevent bogus wasi_snapshot_preview1 imports, 2 | // at least on debug builds, where they're not optimized out for some reason. 3 | // See https://github.com/emscripten-core/emscripten/issues/17331 4 | 5 | // NOLINTBEGIN 6 | extern "C" [[gnu::used]] 7 | int __wasi_fd_close(int) 8 | { 9 | __builtin_trap(); 10 | } 11 | 12 | extern "C" [[gnu::used]] 13 | int __wasi_fd_write(int, int, int, int) 14 | { 15 | __builtin_trap(); 16 | } 17 | 18 | extern "C" [[gnu::used]] 19 | int __wasi_fd_seek(int, long long, int, int) 20 | { 21 | __builtin_trap(); 22 | } 23 | // NOLINTEND 24 | -------------------------------------------------------------------------------- /include/cowel/assets.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_ASSETS_HPP 2 | #define COWEL_ASSETS_HPP 3 | 4 | #include 5 | 6 | namespace cowel::assets { 7 | 8 | /// @brief Generated from `assets/light-dark.js`. 9 | extern const std::u8string_view light_dark_js; 10 | /// @brief Generated from `assets/main.css`. 11 | extern const std::u8string_view main_css; 12 | /// @brief Generated from `assets/settings-widget.html`. 13 | extern const std::u8string_view settings_widget_html; 14 | /// @brief Generated from `ulight/themes/wg21.json`. 15 | extern const std::u8string_view wg21_json; 16 | 17 | } // namespace cowel::assets 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/test/cpp/test_valid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "document_file_testing.hpp" 4 | 5 | namespace cowel { 6 | namespace { 7 | 8 | TEST(Valid, empty) 9 | { 10 | EXPECT_TRUE(test_for_success(u8"syntax/empty.cow")); 11 | } 12 | 13 | TEST(Valid, hello_code) 14 | { 15 | EXPECT_TRUE(test_for_success(u8"syntax/hello_code.cow")); 16 | } 17 | 18 | TEST(Valid, hello_directive) 19 | { 20 | EXPECT_TRUE(test_for_success(u8"syntax/hello_directive.cow")); 21 | } 22 | 23 | TEST(Valid, hello_world) 24 | { 25 | EXPECT_TRUE(test_for_success(u8"syntax/hello_world.cow")); 26 | } 27 | 28 | } // namespace 29 | } // namespace cowel 30 | -------------------------------------------------------------------------------- /include/cowel/output_language.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_OUTPUT_LANGUAGE_HPP 2 | #define COWEL_OUTPUT_LANGUAGE_HPP 3 | 4 | #include "cowel/fwd.hpp" 5 | 6 | namespace cowel { 7 | 8 | enum struct Output_Language : Default_Underlying { 9 | /// @brief No output. 10 | /// However, processing of side effects still happens. 11 | none, 12 | /// @brief Plaintext output. 13 | /// This is used e.g. in the input of `\cow_char_by_name`, 14 | /// in arguments that turn into HTML attributes, and other places 15 | /// where markup cannot be provided. 16 | text, 17 | /// @brief HTML output. 18 | html, 19 | }; 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/cowel/util/severity.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_SEVERITY_HPP 2 | #define COWEL_SEVERITY_HPP 3 | 4 | #include "cowel/cowel.h" 5 | #include "cowel/fwd.hpp" 6 | 7 | namespace cowel { 8 | 9 | enum struct Severity : Default_Underlying { 10 | min = COWEL_SEVERITY_MIN, 11 | trace = COWEL_SEVERITY_TRACE, 12 | debug = COWEL_SEVERITY_DEBUG, 13 | info = COWEL_SEVERITY_INFO, 14 | soft_warning = COWEL_SEVERITY_SOFT_WARNING, 15 | warning = COWEL_SEVERITY_WARNING, 16 | error = COWEL_SEVERITY_ERROR, 17 | fatal = COWEL_SEVERITY_FATAL, 18 | max = COWEL_SEVERITY_MAX, 19 | none = COWEL_SEVERITY_NONE, 20 | }; 21 | 22 | } // namespace cowel 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | name: Clang-format check 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | clang-format-check: 11 | runs-on: ubuntu-latest 12 | timeout-minutes: 5 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@v4 16 | 17 | - name: Install clang-format 18 | run: sudo apt-get install -y clang-format-20 19 | 20 | - name: Run clang-format check 21 | run: > 22 | find include src -name '*.cpp' -o -name '*.c' -o -name '*.hpp' -o -name '*.h' | 23 | xargs clang-format-20 --color=1 --dry-run --Werror 24 | -------------------------------------------------------------------------------- /include/cowel/diagnostic_highlight.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_CODE_SPAN_TYPE_HPP 2 | #define COWEL_CODE_SPAN_TYPE_HPP 3 | 4 | #include "cowel/fwd.hpp" 5 | 6 | namespace cowel { 7 | 8 | enum struct Diagnostic_Highlight : Default_Underlying { 9 | text, 10 | error_text, 11 | code_position, 12 | error, 13 | warning, 14 | note, 15 | line_number, 16 | punctuation, 17 | position_indicator, 18 | code_citation, 19 | internal_error_notice, 20 | operand, 21 | op, 22 | tag, 23 | attribute, 24 | internal, 25 | escape, 26 | success, 27 | diff_common, 28 | diff_del, 29 | diff_ins, 30 | }; 31 | 32 | } // namespace cowel 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/cowel/util/assert.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_ASSERT_HPP 2 | #define COWEL_ASSERT_HPP 3 | 4 | #include "ulight/impl/assert.hpp" 5 | 6 | namespace cowel { 7 | 8 | using ulight::assert_fail; 9 | using ulight::Assertion_Error; 10 | using ulight::Assertion_Error_Type; 11 | using ulight::assertion_handler; 12 | using ulight::handle_assertion; 13 | 14 | #define COWEL_ASSERT(...) ULIGHT_ASSERT(__VA_ARGS__) 15 | #define COWEL_DEBUG_ASSERT(...) ULIGHT_DEBUG_ASSERT(__VA_ARGS__) 16 | 17 | #define COWEL_ASSERT_UNREACHABLE(...) ULIGHT_ASSERT_UNREACHABLE(__VA_ARGS__) 18 | #define COWEL_DEBUG_ASSERT_UNREACHABLE(...) ULIGHT_DEBUG_ASSERT_UNREACHABLE(__VA_ARGS__) 19 | 20 | } // namespace cowel 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/cowel/cowel_lib.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_LIB_HPP 2 | #define COWEL_LIB_HPP 3 | 4 | #include "cowel/util/assert.hpp" 5 | 6 | #include "cowel/cowel.h" 7 | #include "cowel/services.hpp" 8 | 9 | namespace cowel { 10 | 11 | [[nodiscard]] 12 | constexpr File_Load_Error io_status_to_load_error(cowel_io_status error) 13 | { 14 | COWEL_ASSERT(error != COWEL_IO_OK); 15 | switch (error) { 16 | case COWEL_IO_ERROR_READ: return File_Load_Error::read_error; 17 | case COWEL_IO_ERROR_NOT_FOUND: return File_Load_Error::not_found; 18 | case COWEL_IO_ERROR_PERMISSIONS: return File_Load_Error::permissions; 19 | default: return File_Load_Error::error; 20 | } 21 | } 22 | 23 | } // namespace cowel 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /docs/intro/type_grammar.ebnf: -------------------------------------------------------------------------------- 1 | type 2 | = prefix-type, { "|", prefix-type }; 3 | prefix-type 4 | = suffix-type 5 | | type-prefix, "(", type-list, ")" 6 | | type-prefix, prefixed-type; 7 | type-prefix 8 | = "group" 9 | | "pack" 10 | | "named" 11 | | "opt"; 12 | type-list 13 | = type, { ",", type }, [ "," ]; 14 | prefixed-type 15 | = prefixed-suffix-type 16 | | type-prefix, prefixed-type; 17 | suffix-type 18 | = optional-type, { "?" }; 19 | prefixed-suffix-type 20 | = basic-type, { "?" }; 21 | optional-type 22 | = basic-type 23 | | "(", type, ")"; 24 | basic-type 25 | = "any" 26 | | "nothing" 27 | | "unit" 28 | | "null" 29 | | "bool" 30 | | "int" 31 | | "float" 32 | | "str" 33 | | "block"; 34 | -------------------------------------------------------------------------------- /assets/bug.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/cpp/util/code_point_names.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ulight/impl/platform.h" 4 | 5 | ULIGHT_DIAGNOSTIC_PUSH() 6 | ULIGHT_DIAGNOSTIC_IGNORED("-Wconversion") 7 | ULIGHT_DIAGNOSTIC_IGNORED("-Wsign-conversion") 8 | #ifdef ULIGHT_CLANG 9 | ULIGHT_DIAGNOSTIC_IGNORED("-Wshorten-64-to-32") 10 | #endif 11 | #include "cowel/cedilla/name_to_cp.hpp" 12 | ULIGHT_DIAGNOSTIC_POP() 13 | 14 | #include "cowel/util/code_point_names.hpp" 15 | #include "cowel/util/strings.hpp" 16 | 17 | namespace cowel { 18 | 19 | char32_t code_point_by_name(std::u8string_view name) noexcept 20 | { 21 | const char32_t result = uni::cp_from_name(as_string_view(name)); 22 | return result > 0x10'FFFF ? char32_t(-1) : result; 23 | } 24 | 25 | } // namespace cowel 26 | -------------------------------------------------------------------------------- /docs/directives/comments.cow: -------------------------------------------------------------------------------- 1 | \h3{Comments} 2 | 3 | In addition to the \cowdoc_c{\\:} syntax for single-line comments, 4 | there exists a \cowdoc_dir{comment} directive which 5 | discards all of its contents. 6 | This can be used for multi-line comments. 7 | 8 | \h4(id=dir-comment){\cowdoc_dir{comment} \c{mdash} Comments} 9 | 10 | The \cowdoc_dir{comment} directive does not process its arguments or content. 11 | It outputs no plaintext or HTML. 12 | 13 | \Bex{ 14 | While comments don't output anything, 15 | \ref("#paragraph-splitting") is based on blank lines in the source, 16 | so comments don't split paragraphs: 17 | \cowblock{ 18 | Text 19 | \\comment{This is \\directive{comment} content.} 20 | Text 21 | } 22 | Generated HTML: 23 | \htmlblock{ 24 |

Text 25 | 26 | Text

27 | } 28 | } 29 | -------------------------------------------------------------------------------- /docs/intro/themes.cow: -------------------------------------------------------------------------------- 1 | \h2{Themes} 2 | 3 | COWEL outputs documents that can be viewed in \dfn{light mode} and \dfn{dark mode}. 4 | 5 | When the document is opened with support for JavaScript, 6 | there is an button in the top-right that can be used to switch between three modes: 7 | \ul{ 8 | \li{Sync the theme with the OS (default)} 9 | \li{Light mode (ignoring system preference)} 10 | \li{Dark mode (ignoring system preference)} 11 | } 12 | 13 | Forced light/dark mode works by adding a \tt{light} or \tt{dark} 14 | class to the \cowdoc_html{} element in the DOM. 15 | 16 | \Bimp{ 17 | If you want to customize colors with CSS, 18 | remember to make them respond to theme and OS preference changes. 19 | 20 | For reference, you can look at the CSS in the COWEL source code to see how it's done properly. 21 | } 22 | -------------------------------------------------------------------------------- /test/semantics/splice/ints.cow: -------------------------------------------------------------------------------- 1 | \: These should all generate 255. 2 | \cowel_pos(0b11111111) 3 | \cowel_pos(0o377) 4 | \cowel_pos(255) 5 | \cowel_pos(0xff) 6 | 7 | \: Verify that at least signed 128-bit integer range is supported. 8 | \cowel_pos( 0b1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111) 9 | \cowel_pos(-0b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) 10 | \cowel_pos( 0o1777777777777777777777777777777777777777777) 11 | \cowel_pos(-0o2000000000000000000000000000000000000000000) 12 | \cowel_pos( 170141183460469231731687303715884105727) 13 | \cowel_pos(-170141183460469231731687303715884105728) 14 | \cowel_pos( 0x7fffffffffffffffffffffffffffffff) 15 | \cowel_pos(-0x80000000000000000000000000000000) 16 | -------------------------------------------------------------------------------- /include/cowel/directive_display.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_DIRECTIVE_DISPLAY_HPP 2 | #define COWEL_DIRECTIVE_DISPLAY_HPP 3 | 4 | #include "cowel/fwd.hpp" 5 | 6 | namespace cowel { 7 | 8 | /// @brief Specifies how a directive should be displayed. 9 | /// This is used to configure in certain directives 10 | /// how they interact with paragraph splitting. 11 | enum struct Directive_Display : Default_Underlying { 12 | /// @brief Nothing is displayed. 13 | none, 14 | /// @brief The directive is a block, such as `\\h1` or `\\codeblock`. 15 | /// Such directives are not integrated into other paragraphs or surround text. 16 | block, 17 | /// @brief The directive is inline, such as `\\b` or `\\code`. 18 | /// This means that it will be displayed within paragraphs and as part of other text. 19 | in_line, 20 | }; 21 | 22 | } // namespace cowel 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/test/cpp/diagnostic_policy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_DIAGNOSTIC_POLICY_HPP 2 | #define COWEL_DIAGNOSTIC_POLICY_HPP 3 | 4 | #include "cowel/fwd.hpp" 5 | 6 | #include "compilation_stage.hpp" 7 | 8 | namespace cowel { 9 | 10 | enum struct Policy_Action : Default_Underlying { 11 | /// @brief Immediate success. 12 | success, 13 | /// @brief Immediate failure. 14 | failure, 15 | /// @brief Keep going. 16 | keep_going 17 | }; 18 | 19 | [[nodiscard]] 20 | constexpr bool is_exit(Policy_Action action) 21 | { 22 | return action != Policy_Action::keep_going; 23 | } 24 | 25 | struct Diagnostic_Policy { 26 | [[nodiscard]] 27 | virtual bool is_success() const 28 | = 0; 29 | 30 | virtual Policy_Action error(IO_Error_Code) = 0; 31 | 32 | virtual Policy_Action done(Compilation_Stage) = 0; 33 | }; 34 | 35 | } // namespace cowel 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /docs/npm/README.md: -------------------------------------------------------------------------------- 1 | # COWEL 2 | 3 | COWEL (Compact Web Language) is a markup language 4 | with TeX-like syntax, 5 | intended to produce HTML documents. 6 | See for language documentation. 7 | 8 | This package provides the COWEL processor, 9 | in the form of a small Node.js CLI, 10 | backed by a WASM library which does basically all of the work. 11 | 12 | ## Installation 13 | 14 | COWEL is usually installed globally: 15 | 16 | ```sh 17 | npm i -g cowel 18 | ``` 19 | 20 | **Note**: 21 | If you're on Linux, 22 | you may need to elevate permissions with `sudo` for global installations. 23 | 24 | ## Usage 25 | 26 | After installing, 27 | you can simply run `cowel` or `cowel --help` 28 | to see available commands and options. 29 | 30 | To process 31 | a COWEL document located at `input.cow` 32 | into an output HTML file located at `output.html`, use: 33 | 34 | ```sh 35 | cowel run input.cow output.html 36 | ``` 37 | -------------------------------------------------------------------------------- /src/util/generate-html-entities-cpp.py: -------------------------------------------------------------------------------- 1 | #!/bin/python 2 | import json 3 | import sys 4 | 5 | data = json.load(sys.stdin) 6 | 7 | def format_code_points(code_points) -> str: 8 | formatted_code_points = [] 9 | for code_point in code_points: 10 | if code_point > 0xFFFF: 11 | formatted_code_points.append(f"U'\\U{code_point:08X}'") 12 | else: 13 | formatted_code_points.append(f"U'\\u{code_point:04X}'") 14 | return ",".join(formatted_code_points) 15 | 16 | output = [] 17 | 18 | for name, entry in data.items(): 19 | name_cropped = name[1:-1] 20 | code_points_formatted = format_code_points(entry["codepoints"]) 21 | output.append(f'{{u8"{name_cropped}",{len(name_cropped)},{{{code_points_formatted}}}}},') 22 | 23 | output.sort() 24 | print("// NOLINTBEGIN") 25 | print("// clang-format off") 26 | print("\n".join(output)) 27 | print("// clang-format on") 28 | print("// NOLINTEND") 29 | -------------------------------------------------------------------------------- /include/cowel/util/tty.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_TTY_HPP 2 | #define COWEL_TTY_HPP 3 | 4 | #include "cowel/fwd.hpp" 5 | 6 | #ifdef COWEL_EMSCRIPTEN 7 | #error "This file should not be included on emscripten builds." 8 | #endif 9 | 10 | #include 11 | 12 | namespace cowel { 13 | 14 | // https://pubs.opengroup.org/onlinepubs/009695399/functions/isatty.html 15 | [[nodiscard]] 16 | bool is_tty(std::FILE*) noexcept; 17 | 18 | // These convenience constants aren't really necessary. 19 | // Their purpose is to reduce the number of individual calls to `is_tty`, 20 | // so that effectively, globally, just one call per file is made. 21 | 22 | /// @brief True if `is_tty(stdin)` is `true`. 23 | extern const bool is_stdin_tty; 24 | /// @brief True if `is_tty(stdout)` is `true`. 25 | extern const bool is_stdout_tty; 26 | /// @brief True if `is_tty(stderr)` is `true`. 27 | extern const bool is_stderr_tty; 28 | 29 | } // namespace cowel 30 | #endif 31 | -------------------------------------------------------------------------------- /src/test/cpp/test_data.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_TEST_DATA_HPP 2 | #define COWEL_TEST_DATA_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "cowel/content_status.hpp" 9 | #include "cowel/fwd.hpp" 10 | 11 | namespace cowel { 12 | 13 | enum struct Test_Behavior : Default_Underlying { 14 | trivial, 15 | paragraphs, 16 | empty_head, 17 | wg21, 18 | }; 19 | 20 | struct Path { 21 | std::u8string_view value; 22 | }; 23 | 24 | struct Source { 25 | std::u8string_view contents; 26 | }; 27 | 28 | struct Basic_Test { 29 | std::variant document; 30 | std::variant expected_html; 31 | Processing_Status expected_status = Processing_Status::ok; 32 | std::initializer_list expected_diagnostics = {}; 33 | Test_Behavior behavior = Test_Behavior::trivial; 34 | }; 35 | 36 | extern const std::span basic_tests; 37 | 38 | } // namespace cowel 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CMake build status][badge-cmake]][build-cmake] 2 | [![clang-format build status][badge-format]][build-format] 3 | 4 | # Compact Web Language (COWEL) 5 | 6 | COWEL is a markup language with TeX-like syntax, 7 | intended to generate HTML documents, 8 | mainly for proposals and technical text. 9 | Many of its features are purpose-built for use in WG21, 10 | such as for writing C++ proposals. 11 | 12 | See [GitHub pages for documentation](https://cowel.org). 13 | 14 | Get support on [our official Discord server][discord]. 15 | 16 | [build-cmake]: https://github.com/eisenwave/cowel/actions/workflows/cmake-multi-platform.yml/ 17 | [badge-cmake]: https://github.com/eisenwave/cowel/actions/workflows/cmake-multi-platform.yml/badge.svg 18 | [build-format]: https://github.com/eisenwave/cowel/actions/workflows/clang-format.yml/ 19 | [badge-format]: https://github.com/eisenwave/cowel/actions/workflows/clang-format.yml/badge.svg 20 | [discord]: https://discord.gg/fx8r5mP3Y9 21 | -------------------------------------------------------------------------------- /test/semantics/convert/int_to_str.cow.html: -------------------------------------------------------------------------------- 1 | 255 2 | 3 | 11111111 4 | 377 5 | 255 6 | ff 7 | 7v 8 | 9 | 10000000000000000000000000000000000000000000000000000000000000000 10 | 2000000000000000000000 11 | 18446744073709551616 12 | 10000000000000000 13 | g000000000000 14 | 15 | 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 16 | 1777777777777777777777777777777777777777777 17 | 170141183460469231731687303715884105727 18 | 7fffffffffffffffffffffffffffffff 19 | 3vvvvvvvvvvvvvvvvvvvvvvvvv 20 | 21 | -10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 22 | -2000000000000000000000000000000000000000000 23 | -170141183460469231731687303715884105728 24 | -80000000000000000000000000000000 25 | -40000000000000000000000000 26 | 27 | 255 28 | 255 29 | 255 30 | 255 31 | 0255 32 | 00255 33 | 0000000255 34 | 35 | -255 36 | -255 37 | -255 38 | -255 39 | -0255 40 | -00255 41 | -0000000255 42 | -------------------------------------------------------------------------------- /include/cowel/grammar.ebnf: -------------------------------------------------------------------------------- 1 | document 2 | = { content }; 3 | content 4 | = directive | text; 5 | 6 | (* not matched if immediately following "\", except if following "\\" *) 7 | directive 8 | = "\", directive_name, [ arguments ], [ block ]; 9 | directive_name 10 | = /[-a-zA-Z][-a-zA-Z0-9]*/; 11 | 12 | argument_list 13 | = "[", [ argument ], { ",", [ argument ] }, "]"; 14 | argument 15 | = [ ws ], argument_name, [ ws ], "=", [ ws ], [ argument_value ], [ ws ] 16 | | [ ws ], [ argument_value ], [ ws ]; 17 | argument_name 18 | = /[-_a-zA-Z][-_a-zA-Z0-9]*/; 19 | 20 | (* terminated by "," or unbalanced "]" *) 21 | argument_value 22 | = { content }; 23 | 24 | (* Lazy. 25 | Brace matching is performed, 26 | where escaped braces ("\}" and "\{") do not count, 27 | except that "\\{" and "\\}" do count *) 28 | block 29 | = "{", { content }, "}"; 30 | 31 | text 32 | = (* sequence of characters not containing any match of directive *); 33 | ws 34 | = (* sequence of whitespace characters *); 35 | -------------------------------------------------------------------------------- /include/cowel/policy/unprocessed.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_POLICY_UNPROCESSED_HPP 2 | #define COWEL_POLICY_UNPROCESSED_HPP 3 | 4 | #include "cowel/policy/content_policy.hpp" 5 | #include "cowel/policy/plaintext.hpp" 6 | 7 | #include "cowel/content_status.hpp" 8 | #include "cowel/fwd.hpp" 9 | #include "cowel/output_language.hpp" 10 | 11 | namespace cowel { 12 | 13 | struct Unprocessed_Content_Policy : virtual Plaintext_Content_Policy { 14 | private: 15 | public: 16 | [[nodiscard]] 17 | explicit Unprocessed_Content_Policy(Text_Sink& parent) 18 | : Text_Sink { Output_Language::text } 19 | , Content_Policy { Output_Language::text } 20 | , Plaintext_Content_Policy { parent } 21 | 22 | { 23 | } 24 | 25 | [[nodiscard]] 26 | Processing_Status consume(const ast::Directive& directive, Frame_Index, Context&) override 27 | { 28 | write(directive.get_source(), Output_Language::text); 29 | return Processing_Status::ok; 30 | } 31 | }; 32 | 33 | } // namespace cowel 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/test/cpp/io.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_TEST_IO_HPP 2 | #define COWEL_TEST_IO_HPP 3 | 4 | #include "cowel/fwd.hpp" 5 | 6 | #ifdef COWEL_EMSCRIPTEN 7 | #error "This file should not be included when using emscripten." 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "cowel/util/annotated_string.hpp" 15 | #include "cowel/util/io.hpp" 16 | #include "cowel/util/result.hpp" 17 | 18 | #include "cowel/print.hpp" 19 | 20 | namespace cowel { 21 | 22 | [[nodiscard]] 23 | inline bool load_utf8_file_or_error( 24 | std::pmr::vector& out, 25 | std::u8string_view path, 26 | std::pmr::memory_resource* memory 27 | ) 28 | { 29 | const Result result = load_utf8_file(out, path); 30 | if (result) { 31 | return true; 32 | } 33 | 34 | Basic_Annotated_String error { memory }; 35 | print_io_error(error, path, result.error()); 36 | print_code_string_stdout(error); 37 | return false; 38 | } 39 | 40 | } // namespace cowel 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/cowel/policy/ignorant.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_POLICY_IGNORANT_HPP 2 | #define COWEL_POLICY_IGNORANT_HPP 3 | 4 | #include "cowel/util/char_sequence.hpp" 5 | 6 | #include "cowel/policy/content_policy.hpp" 7 | 8 | #include "cowel/content_status.hpp" 9 | #include "cowel/fwd.hpp" 10 | #include "cowel/output_language.hpp" 11 | 12 | namespace cowel { 13 | 14 | struct Ignorant_Content_Policy : virtual Content_Policy { 15 | 16 | [[nodiscard]] 17 | explicit Ignorant_Content_Policy() 18 | : Text_Sink { Output_Language::none } 19 | , Content_Policy { Output_Language::none } 20 | 21 | { 22 | } 23 | 24 | bool write(Char_Sequence8, Output_Language) override 25 | { 26 | return true; 27 | } 28 | 29 | [[nodiscard]] 30 | Processing_Status consume(const ast::Primary&, Frame_Index, Context&) override 31 | { 32 | return Processing_Status::ok; 33 | } 34 | [[nodiscard]] 35 | Processing_Status consume(const ast::Directive&, Frame_Index, Context&) override 36 | { 37 | return Processing_Status::ok; 38 | } 39 | }; 40 | 41 | } // namespace cowel 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Jan Schultke 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/npm/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Jan Schultke 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /include/cowel/policy/literally.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_POLICY_LITERALLY_HPP 2 | #define COWEL_POLICY_LITERALLY_HPP 3 | 4 | #include "cowel/policy/plaintext.hpp" 5 | 6 | #include "cowel/content_status.hpp" 7 | #include "cowel/fwd.hpp" 8 | #include "cowel/output_language.hpp" 9 | 10 | namespace cowel { 11 | 12 | struct To_Source_Content_Policy : virtual Plaintext_Content_Policy { 13 | private: 14 | public: 15 | [[nodiscard]] 16 | explicit To_Source_Content_Policy(Text_Sink& parent) 17 | : Text_Sink { Output_Language::text } 18 | , Content_Policy { Output_Language::text } 19 | , Plaintext_Content_Policy { parent } 20 | 21 | { 22 | } 23 | 24 | [[nodiscard]] 25 | Processing_Status consume(const ast::Primary& text, Frame_Index, Context&) override 26 | { 27 | write(text.get_source(), Output_Language::text); 28 | return Processing_Status::ok; 29 | } 30 | [[nodiscard]] 31 | Processing_Status consume(const ast::Directive& directive, Frame_Index, Context&) override 32 | { 33 | write(directive.get_source(), Output_Language::text); 34 | return Processing_Status::ok; 35 | } 36 | }; 37 | 38 | } // namespace cowel 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | AlignAfterOpenBracket: BlockIndent 2 | AlignConsecutiveAssignments: None 3 | AllowAllParametersOfDeclarationOnNextLine: No 4 | AllowShortCaseLabelsOnASingleLine: Yes 5 | AllowShortFunctionsOnASingleLine: Empty 6 | AlwaysBreakTemplateDeclarations: Yes 7 | BasedOnStyle: WebKit 8 | BinPackParameters: OnePerLine 9 | BreakAfterAttributes: Always 10 | BreakBeforeBraces: Custom 11 | BreakInheritanceList: BeforeComma 12 | BreakTemplateDeclarations: Yes 13 | BraceWrapping: 14 | AfterFunction: Yes 15 | BeforeElse: Yes 16 | ColumnLimit: 100 17 | CompactNamespaces: false 18 | Cpp11BracedListStyle: false 19 | FixNamespaceComments: Yes 20 | IndentWidth: 4 21 | IndentCaseLabels: false 22 | LineEnding: LF 23 | NamespaceIndentation: None 24 | PackConstructorInitializers: Never 25 | PointerAlignment: Left 26 | QualifierAlignment: Left 27 | RemoveSemicolon: true 28 | SpaceAfterTemplateKeyword: true 29 | SpaceBeforeAssignmentOperators: true 30 | SpaceBeforeCpp11BracedList: true 31 | SpaceBeforeCtorInitializerColon: true 32 | SpaceBeforeRangeBasedForLoopColon: true 33 | SpaceBeforeSquareBrackets: false 34 | SpaceInEmptyBlock: true 35 | SpaceInEmptyParentheses: false 36 | SpacesInAngles: Never 37 | WrapNamespaceBodyWithEmptyLines: Always 38 | -------------------------------------------------------------------------------- /include/cowel/ulight_highlighter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_ULIGHT_HIGHLIGHTER_HPP 2 | #define COWEL_ULIGHT_HIGHLIGHTER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "cowel/util/result.hpp" 10 | #include "cowel/util/typo.hpp" 11 | 12 | #include "cowel/services.hpp" 13 | 14 | namespace cowel { 15 | 16 | /// @brief A `Syntax_Highlighter` that uses the µlight library. 17 | struct Ulight_Syntax_Highlighter final : Syntax_Highlighter { 18 | 19 | [[nodiscard]] 20 | std::span get_supported_languages() const final; 21 | 22 | [[nodiscard]] 23 | Distant match_supported_language( 24 | std::u8string_view language, 25 | std::pmr::memory_resource* memory 26 | ) const final; 27 | 28 | [[nodiscard]] 29 | Result operator()( // 30 | std::pmr::vector& out, 31 | std::u8string_view code, 32 | std::u8string_view language, 33 | std::pmr::memory_resource* memory 34 | ) final; 35 | }; 36 | 37 | inline constinit Ulight_Syntax_Highlighter ulight_syntax_highlighter; 38 | 39 | } // namespace cowel 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/cowel/policy/phantom.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_POLICY_PHANTOM_HPP 2 | #define COWEL_POLICY_PHANTOM_HPP 3 | 4 | #include "cowel/util/assert.hpp" 5 | #include "cowel/util/char_sequence.hpp" 6 | 7 | #include "cowel/policy/content_policy.hpp" 8 | #include "cowel/policy/plaintext.hpp" 9 | #include "cowel/policy/syntax_highlight.hpp" 10 | 11 | #include "cowel/fwd.hpp" 12 | #include "cowel/output_language.hpp" 13 | 14 | namespace cowel { 15 | 16 | struct Phantom_Content_Policy : virtual Plaintext_Content_Policy { 17 | 18 | [[nodiscard]] 19 | explicit Phantom_Content_Policy(Text_Sink& parent) 20 | : Text_Sink { Output_Language::text } 21 | , Content_Policy { Output_Language::text } 22 | , Plaintext_Content_Policy { parent } 23 | 24 | { 25 | } 26 | 27 | bool write(Char_Sequence8 chars, Output_Language language) override 28 | { 29 | COWEL_ASSERT(language != Output_Language::none); 30 | if (language != Output_Language::text) { 31 | return false; 32 | } 33 | auto* const highlight_policy = dynamic_cast(&m_parent); 34 | return highlight_policy && highlight_policy->write_phantom(chars); 35 | } 36 | }; 37 | 38 | } // namespace cowel 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/cowel/policy/actions.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_POLICY_ACTIONS_HPP 2 | #define COWEL_POLICY_ACTIONS_HPP 3 | 4 | #include "cowel/util/char_sequence.hpp" 5 | 6 | #include "cowel/policy/content_policy.hpp" 7 | 8 | #include "cowel/fwd.hpp" 9 | #include "cowel/output_language.hpp" 10 | 11 | namespace cowel { 12 | 13 | struct Actions_Content_Policy : virtual Content_Policy { 14 | protected: 15 | Content_Policy& m_parent; 16 | 17 | public: 18 | [[nodiscard]] 19 | explicit Actions_Content_Policy(Content_Policy& parent) 20 | : Text_Sink { parent.get_language() } 21 | , Content_Policy { parent.get_language() } 22 | , m_parent { parent } 23 | { 24 | } 25 | 26 | bool write(Char_Sequence8 chars, Output_Language language) override 27 | { 28 | return m_parent.write(chars, language); 29 | } 30 | 31 | [[nodiscard]] 32 | Processing_Status consume(const ast::Primary&, Frame_Index, Context&) override 33 | { 34 | return Processing_Status::ok; 35 | } 36 | [[nodiscard]] 37 | Processing_Status 38 | consume(const ast::Directive& directive, Frame_Index frame, Context& context) override 39 | { 40 | return m_parent.consume(directive, frame, context); 41 | } 42 | }; 43 | 44 | } // namespace cowel 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/cowel/util/typo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_TYPO_HPP 2 | #define COWEL_TYPO_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace cowel { 11 | 12 | template 13 | struct Distant { 14 | T value {}; 15 | std::size_t distance = std::size_t(-1); 16 | 17 | [[nodiscard]] 18 | constexpr operator bool() const 19 | { 20 | return distance != std::size_t(-1); 21 | } 22 | 23 | [[nodiscard]] 24 | friend constexpr bool operator==(const Distant& x, const Distant& y) 25 | = default; 26 | 27 | [[nodiscard]] 28 | friend constexpr std::strong_ordering operator<=>(const Distant& x, const Distant& y) noexcept 29 | { 30 | return x.distance <=> y.distance; 31 | } 32 | }; 33 | 34 | /// @brief Searches for the given `needle` in the `haystack` based on Levenshtein distance. 35 | /// There may be multiple equally good matches, 36 | // in which case earlier elements are preferred over later elements in the `haystack`. 37 | [[nodiscard]] 38 | Distant closest_match( 39 | std::span haystack, 40 | std::u8string_view needle, 41 | std::pmr::memory_resource* memory 42 | ); 43 | 44 | } // namespace cowel 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cowel", 3 | "version": "0.6.0", 4 | "description": "COWEL (Compact Web Language) command line utility", 5 | "main": "cowel.js", 6 | "type": "module", 7 | "bin": "cowel.js", 8 | "directories": {}, 9 | "scripts": {}, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/eisenwave/cowel.git" 13 | }, 14 | "keywords": [ 15 | "markup", 16 | "cowel" 17 | ], 18 | "author": { 19 | "name": "Jan Schultke", 20 | "email": "me@eisenwave.net", 21 | "url": "https://github.com/eisenwave/" 22 | }, 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/eisenwave/cowel/issues" 26 | }, 27 | "homepage": "https://cowel.org", 28 | "devDependencies": { 29 | "@stylistic/eslint-plugin": "^5.2.2", 30 | "@types/node": "^24.1.0", 31 | "@typescript-eslint/eslint-plugin": "^8.38.0", 32 | "@typescript-eslint/parser": "^8.38.0", 33 | "eslint": "^9.32.0", 34 | "globals": "^16.3.0", 35 | "typescript": "^5.8.3", 36 | "typescript-eslint": "^8.38.0", 37 | "@types/yargs": "^17.0.0" 38 | }, 39 | "engines": { 40 | "node": ">=18.19.1" 41 | }, 42 | "dependencies": { 43 | "yargs": "^17.0.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /include/cowel/util/ansi.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COWEL_ANSI_HPP 2 | #define COWEL_ANSI_HPP 3 | 4 | #include 5 | 6 | namespace cowel::ansi { 7 | 8 | // Regular colors 9 | 10 | inline constexpr std::u8string_view black = u8"\x1B[30m"; 11 | inline constexpr std::u8string_view red = u8"\x1B[31m"; 12 | inline constexpr std::u8string_view green = u8"\x1B[32m"; 13 | inline constexpr std::u8string_view yellow = u8"\x1B[33m"; 14 | inline constexpr std::u8string_view blue = u8"\x1B[34m"; 15 | inline constexpr std::u8string_view magenta = u8"\x1B[35m"; 16 | inline constexpr std::u8string_view cyan = u8"\x1B[36m"; 17 | inline constexpr std::u8string_view white = u8"\x1B[37m"; 18 | 19 | // High-intensity colors 20 | 21 | inline constexpr std::u8string_view h_black = u8"\x1B[0;90m"; 22 | inline constexpr std::u8string_view h_red = u8"\x1B[0;91m"; 23 | inline constexpr std::u8string_view h_green = u8"\x1B[0;92m"; 24 | inline constexpr std::u8string_view h_yellow = u8"\x1B[0;93m"; 25 | inline constexpr std::u8string_view h_blue = u8"\x1B[0;94m"; 26 | inline constexpr std::u8string_view h_magenta = u8"\x1B[0;95m"; 27 | inline constexpr std::u8string_view h_cyan = u8"\x1B[0;96m"; 28 | inline constexpr std::u8string_view h_white = u8"\x1B[0;97m"; 29 | 30 | // Other sequences 31 | 32 | inline constexpr std::u8string_view reset = u8"\033[0m"; 33 | 34 | }; // namespace cowel::ansi 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/util/file-to-array.py: -------------------------------------------------------------------------------- 1 | #!/bin/python 2 | 3 | import sys 4 | 5 | def emit_cpp_array(in_path, outfile, var_name): 6 | with open(in_path, "rb") as input: 7 | data = input.read() 8 | 9 | with open(outfile, "w", encoding="utf-8") as output: 10 | output.write("#include \n") 11 | output.write("#include \n\n") 12 | output.write("#include \"cowel/assets.hpp\"\n\n") 13 | output.write("namespace cowel::assets {\n") 14 | output.write("namespace {\n") 15 | output.write(f"constexpr char8_t {var_name}_data[] = {{\n ") 16 | 17 | for i, b in enumerate(data): 18 | output.write(f"0x{b:02x}, ") 19 | if (i + 1) % 16 == 0: 20 | output.write("\n ") 21 | 22 | output.write("\n};\n") 23 | output.write(f"constexpr std::size_t {var_name}_size = sizeof({var_name}_data);\n") 24 | output.write("}\n") 25 | output.write(f"constinit const std::u8string_view {var_name} {{ {var_name}_data, {var_name}_size }};\n") 26 | 27 | output.write("}\n") 28 | 29 | if __name__ == "__main__": 30 | if len(sys.argv) < 4: 31 | print(f"Usage: {sys.argv[0]} IN_FILE OUT_FILE VAR_NAME") 32 | exit(1) 33 | in_path = sys.argv[1] 34 | out_path = sys.argv[2] 35 | var_name = sys.argv[3] 36 | emit_cpp_array(in_path, out_path, var_name) 37 | -------------------------------------------------------------------------------- /docs/directives/foreign.cow: -------------------------------------------------------------------------------- 1 | \h3{Foreign languages} 2 | 3 | \h4(id=dir-script){\cowdoc_dir{script} \c{mdash} JavaScript blocks} 4 | 5 | The content of a \cowdoc_dir{script} directive is a plaintext context, 6 | where the input is treated as JavaScript code 7 | and surrounded in \cowdoc_html{} tags. 8 | 9 | \cowdoc_dir{script} displays as meta content (like \cowdoc_dir{comment}). 10 | 11 | \Bex{ 12 | COWEL markup: 13 | \cowblock{ 14 | \\script{ 15 | console.log("hello"); 16 | } 17 | } 18 | Generated HTML: 19 | \htmlblock{ 20 | 23 | } 24 | } 25 | 26 | \h4(id=dir-noscript){\cowdoc_dir{noscript} \c{mdash} No-JavaScript content} 27 | 28 | The \cowdoc_dir{noscript} directive corresponds to the \cowdoc_html{