├── 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 | inner text
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{