aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/build.md2
-rw-r--r--doc/cpsc.1.md (renamed from doc/cpsc.md)28
-rw-r--r--doc/install.md2
-rw-r--r--doc/language/cpsc-function-asc.7.md28
-rw-r--r--doc/language/cpsc-function-chr.7.md28
-rw-r--r--doc/language/cpsc-function-eof.7.md34
-rw-r--r--doc/language/cpsc-function-is_num.7.md28
-rw-r--r--doc/language/cpsc-function-lcase.7.md28
-rw-r--r--doc/language/cpsc-function-left.7.md27
-rw-r--r--doc/language/cpsc-function-length.7.md27
-rw-r--r--doc/language/cpsc-function-mid.7.md28
-rw-r--r--doc/language/cpsc-function-num_to_str.7.md27
-rw-r--r--doc/language/cpsc-function-right.7.md27
-rw-r--r--doc/language/cpsc-function-str_to_num.7.md28
-rw-r--r--doc/language/cpsc-function-ucase.7.md28
-rw-r--r--doc/language/cpsc-keyword-and.7.md28
-rw-r--r--doc/language/cpsc-keyword-call.7.md31
-rw-r--r--doc/language/cpsc-keyword-class.7.md43
-rw-r--r--doc/language/cpsc-keyword-closefile.7.md29
-rw-r--r--doc/language/cpsc-keyword-declare.7.md40
-rw-r--r--doc/language/cpsc-keyword-div.7.md28
-rw-r--r--doc/language/cpsc-keyword-for.7.md35
-rw-r--r--doc/language/cpsc-keyword-function.7.md41
-rw-r--r--doc/language/cpsc-keyword-if.7.md35
-rw-r--r--doc/language/cpsc-keyword-input.7.md31
-rw-r--r--doc/language/cpsc-keyword-mod.7.md29
-rw-r--r--doc/language/cpsc-keyword-not.7.md27
-rw-r--r--doc/language/cpsc-keyword-openfile.7.md37
-rw-r--r--doc/language/cpsc-keyword-or.7.md28
-rw-r--r--doc/language/cpsc-keyword-output.7.md32
-rw-r--r--doc/language/cpsc-keyword-procedure.7.md43
-rw-r--r--doc/language/cpsc-keyword-readfile.7.md34
-rw-r--r--doc/language/cpsc-keyword-repeat.7.md34
-rw-r--r--doc/language/cpsc-keyword-type.7.md53
-rw-r--r--doc/language/cpsc-keyword-while.7.md34
-rw-r--r--doc/language/cpsc-keyword-writefile.7.md30
-rw-r--r--doc/language/cpsc-language-overview.7.md100
37 files changed, 1166 insertions, 26 deletions
diff --git a/doc/build.md b/doc/build.md
index ca1c30a..ce87eb6 100644
--- a/doc/build.md
+++ b/doc/build.md
@@ -185,7 +185,7 @@ export PATH="$PWD/build/deps/root/opt/llvm@18/bin:$PATH"
## Manual
-The quick reference is in [cpsc.md](cpsc.md). Pandoc is required only for the
+The quick reference is in [cpsc.1.md](cpsc.1.md). Pandoc is required only for the
`doc`, installation and release targets. Recommended local downloads follow;
an existing system Pandoc works with the same manual-generation command.
diff --git a/doc/cpsc.md b/doc/cpsc.1.md
index 8a57a63..228fd66 100644
--- a/doc/cpsc.md
+++ b/doc/cpsc.1.md
@@ -66,30 +66,6 @@ Save IR and run it:
cpsc test.cps -r -o result.ir
```
-# CLASSES
-
-Declare classes at top level. Every field must explicitly specify `PUBLIC` or
-`PRIVATE`, without `DECLARE`:
-
-```text
-CLASS Person
- PUBLIC Name : STRING
- PRIVATE Age : INTEGER
-ENDCLASS
-
-DECLARE p : Person
-p.Name <- "Alice"
-OUTPUT p.Name
-```
-
-Classes use record value semantics: zero initialization, whole-value copying,
-arrays, pointers and ordinary function/procedure parameters. Private fields cannot
-be read, written or addressed externally; they are still initialized and copied
-with the whole value. Record `TYPE` fields remain implicitly public and cannot
-specify access levels. Class methods, constructors, destructors, `NEW` and
-`INHERITS` are not supported. Array fields remain unsupported in both records and
-classes.
-
# EXIT STATUS
**0**
@@ -105,3 +81,7 @@ With **-r**, return the executed program's exit status. In PATH mode, failure to
Compiler diagnostics go to stderr. Failed compilation does not write IR. Successful compilation overwrites an existing output file, but an output path that refers to the source file (including a symbolic or hard link) is rejected.
Missing input, including invoking `cpsc` without arguments, reports `cpsc: fatal error: no input files`. Ordinary lexical, syntax and semantic errors use `error:`; failures that prevent compilation, such as file I/O errors, use `fatal error:`. Compilation and argument failures end with one `compilation terminated.` line. Execution-stage failures do not print that line.
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](language/cpsc-language-overview.7.md) describes supported syntax and links to the keyword and built-in function manuals.
diff --git a/doc/install.md b/doc/install.md
index f1746e5..8101684 100644
--- a/doc/install.md
+++ b/doc/install.md
@@ -1,6 +1,6 @@
# Installing and packaging cpsc
-To build from source, follow [build.md](build.md). For command-line usage, see [cpsc.md](cpsc.md). Run build commands from the project root; package installation commands run from the extracted package directory.
+To build from source, follow [build.md](build.md). For command-line usage, see [cpsc.1.md](cpsc.1.md). Run build commands from the project root; package installation commands run from the extracted package directory.
## Linux installation
diff --git a/doc/language/cpsc-function-asc.7.md b/doc/language/cpsc-function-asc.7.md
new file mode 100644
index 0000000..0600599
--- /dev/null
+++ b/doc/language/cpsc-function-asc.7.md
@@ -0,0 +1,28 @@
+% CPSC-FUNCTION-ASC(7)
+
+# NAME
+
+cpsc-function-asc - find a character's byte code
+
+# SYNOPSIS
+
+```text
+ASC(character : CHAR) RETURNS INTEGER
+ASC(text : STRING) RETURNS INTEGER
+```
+
+# DESCRIPTION
+
+Return the unsigned byte code of the character, or of the first byte of a
+string. Use a nonempty string; for ASCII characters this is the ASCII code.
+
+# EXAMPLE
+
+```text
+OUTPUT ASC('A')
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-chr(7)](cpsc-function-chr.7.md).
+
diff --git a/doc/language/cpsc-function-chr.7.md b/doc/language/cpsc-function-chr.7.md
new file mode 100644
index 0000000..5062468
--- /dev/null
+++ b/doc/language/cpsc-function-chr.7.md
@@ -0,0 +1,28 @@
+% CPSC-FUNCTION-CHR(7)
+
+# NAME
+
+cpsc-function-chr - convert a byte code to text
+
+# SYNOPSIS
+
+```text
+CHR(code : INTEGER) RETURNS STRING
+```
+
+# DESCRIPTION
+
+Convert the low eight bits of code to a one-byte string.
+The result is STRING, not CHAR. Use ASCII codes 1 to 127 for
+ordinary text; code 0 produces an empty string.
+
+# EXAMPLE
+
+```text
+OUTPUT CHR(65)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-asc(7)](cpsc-function-asc.7.md).
+
diff --git a/doc/language/cpsc-function-eof.7.md b/doc/language/cpsc-function-eof.7.md
new file mode 100644
index 0000000..721e667
--- /dev/null
+++ b/doc/language/cpsc-function-eof.7.md
@@ -0,0 +1,34 @@
+% CPSC-FUNCTION-EOF(7)
+
+# NAME
+
+cpsc-function-eof - test for the end of a text file
+
+# SYNOPSIS
+
+```text
+EOF(filename : STRING) RETURNS BOOLEAN
+```
+
+# DESCRIPTION
+
+Return true when no further characters remain in a file opened FOR READ.
+The test does not consume the next character. Testing an unopened file or
+a file in the wrong mode terminates execution.
+
+# EXAMPLE
+
+```text
+DECLARE Line : STRING
+OPENFILE "notes.txt" FOR READ
+WHILE NOT EOF("notes.txt") DO
+ READFILE "notes.txt", Line
+ OUTPUT Line
+ENDWHILE
+CLOSEFILE "notes.txt"
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md).
+
diff --git a/doc/language/cpsc-function-is_num.7.md b/doc/language/cpsc-function-is_num.7.md
new file mode 100644
index 0000000..de37b71
--- /dev/null
+++ b/doc/language/cpsc-function-is_num.7.md
@@ -0,0 +1,28 @@
+% CPSC-FUNCTION-IS_NUM(7)
+
+# NAME
+
+cpsc-function-is_num - test whether text represents a number
+
+# SYNOPSIS
+
+```text
+IS_NUM(text : STRING) RETURNS BOOLEAN
+```
+
+# DESCRIPTION
+
+Return true for a nonempty string fully consumed by the runtime's
+numeric conversion. Leading whitespace is accepted; trailing whitespace
+or other trailing text is rejected.
+
+# EXAMPLE
+
+```text
+OUTPUT IS_NUM("12.5")
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-str_to_num(7)](cpsc-function-str_to_num.7.md).
+
diff --git a/doc/language/cpsc-function-lcase.7.md b/doc/language/cpsc-function-lcase.7.md
new file mode 100644
index 0000000..f6ca334
--- /dev/null
+++ b/doc/language/cpsc-function-lcase.7.md
@@ -0,0 +1,28 @@
+% CPSC-FUNCTION-LCASE(7)
+
+# NAME
+
+cpsc-function-lcase - convert text to lower case
+
+# SYNOPSIS
+
+```text
+LCASE(text : STRING) RETURNS STRING
+```
+
+# DESCRIPTION
+
+Return a copy with letters converted to lower case. Unlike guide section 5.5's
+CHAR-to-CHAR signature, cpsc accepts text and returns STRING. Use ASCII
+text for predictable character conversion.
+
+# EXAMPLE
+
+```text
+OUTPUT LCASE("HELLO")
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-ucase(7)](cpsc-function-ucase.7.md).
+
diff --git a/doc/language/cpsc-function-left.7.md b/doc/language/cpsc-function-left.7.md
new file mode 100644
index 0000000..b4542d6
--- /dev/null
+++ b/doc/language/cpsc-function-left.7.md
@@ -0,0 +1,27 @@
+% CPSC-FUNCTION-LEFT(7)
+
+# NAME
+
+cpsc-function-left - extract the beginning of a string
+
+# SYNOPSIS
+
+```text
+LEFT(text : STRING, count : INTEGER) RETURNS STRING
+```
+
+# DESCRIPTION
+
+Return up to count bytes from the beginning. Counts larger than the string
+length return the whole string; negative counts return an empty string.
+
+# EXAMPLE
+
+```text
+OUTPUT LEFT("Hello", 2)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-right(7)](cpsc-function-right.7.md), [cpsc-function-mid(7)](cpsc-function-mid.7.md).
+
diff --git a/doc/language/cpsc-function-length.7.md b/doc/language/cpsc-function-length.7.md
new file mode 100644
index 0000000..a7f6acf
--- /dev/null
+++ b/doc/language/cpsc-function-length.7.md
@@ -0,0 +1,27 @@
+% CPSC-FUNCTION-LENGTH(7)
+
+# NAME
+
+cpsc-function-length - find a string's length
+
+# SYNOPSIS
+
+```text
+LENGTH(text : STRING) RETURNS INTEGER
+```
+
+# DESCRIPTION
+
+Return the number of bytes before the string terminator. String operations
+are byte-based, so this is not a Unicode character count.
+
+# EXAMPLE
+
+```text
+OUTPUT LENGTH("Hello")
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-mid(7)](cpsc-function-mid.7.md), [cpsc-function-left(7)](cpsc-function-left.7.md), [cpsc-function-right(7)](cpsc-function-right.7.md).
+
diff --git a/doc/language/cpsc-function-mid.7.md b/doc/language/cpsc-function-mid.7.md
new file mode 100644
index 0000000..3a6bc71
--- /dev/null
+++ b/doc/language/cpsc-function-mid.7.md
@@ -0,0 +1,28 @@
+% CPSC-FUNCTION-MID(7)
+
+# NAME
+
+cpsc-function-mid - extract part of a string
+
+# SYNOPSIS
+
+```text
+MID(text : STRING, start : INTEGER, count : INTEGER) RETURNS STRING
+```
+
+# DESCRIPTION
+
+Return up to count bytes starting at the one-based position start.
+Positions below 1 clamp to 1; positions beyond the end return an empty string.
+The count clamps to the available bytes; negative counts return an empty string.
+
+# EXAMPLE
+
+```text
+OUTPUT MID("ABCDEFGH", 2, 3)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-left(7)](cpsc-function-left.7.md), [cpsc-function-right(7)](cpsc-function-right.7.md), [cpsc-function-length(7)](cpsc-function-length.7.md).
+
diff --git a/doc/language/cpsc-function-num_to_str.7.md b/doc/language/cpsc-function-num_to_str.7.md
new file mode 100644
index 0000000..30dc39b
--- /dev/null
+++ b/doc/language/cpsc-function-num_to_str.7.md
@@ -0,0 +1,27 @@
+% CPSC-FUNCTION-NUM_TO_STR(7)
+
+# NAME
+
+cpsc-function-num_to_str - convert a number to text
+
+# SYNOPSIS
+
+```text
+NUM_TO_STR(number : INTEGER or REAL) RETURNS STRING
+```
+
+# DESCRIPTION
+
+Format INTEGER as signed decimal text and REAL with six digits after the
+decimal point.
+
+# EXAMPLE
+
+```text
+OUTPUT NUM_TO_STR(42), " ", NUM_TO_STR(3.5)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-str_to_num(7)](cpsc-function-str_to_num.7.md).
+
diff --git a/doc/language/cpsc-function-right.7.md b/doc/language/cpsc-function-right.7.md
new file mode 100644
index 0000000..ae9114b
--- /dev/null
+++ b/doc/language/cpsc-function-right.7.md
@@ -0,0 +1,27 @@
+% CPSC-FUNCTION-RIGHT(7)
+
+# NAME
+
+cpsc-function-right - extract the end of a string
+
+# SYNOPSIS
+
+```text
+RIGHT(text : STRING, count : INTEGER) RETURNS STRING
+```
+
+# DESCRIPTION
+
+Return up to count bytes from the end. Use a nonnegative count.
+Counts larger than the string length return the whole string.
+
+# EXAMPLE
+
+```text
+OUTPUT RIGHT("Hello", 2)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-left(7)](cpsc-function-left.7.md), [cpsc-function-mid(7)](cpsc-function-mid.7.md).
+
diff --git a/doc/language/cpsc-function-str_to_num.7.md b/doc/language/cpsc-function-str_to_num.7.md
new file mode 100644
index 0000000..6128a13
--- /dev/null
+++ b/doc/language/cpsc-function-str_to_num.7.md
@@ -0,0 +1,28 @@
+% CPSC-FUNCTION-STR_TO_NUM(7)
+
+# NAME
+
+cpsc-function-str_to_num - convert text to a real number
+
+# SYNOPSIS
+
+```text
+STR_TO_NUM(text : STRING) RETURNS REAL
+```
+
+# DESCRIPTION
+
+Return REAL, including for integer-looking text. Conversion can stop at
+trailing text; invalid text returns zero. Use IS_NUM first when the whole
+string must be a valid number.
+
+# EXAMPLE
+
+```text
+OUTPUT STR_TO_NUM("12.5")
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-is_num(7)](cpsc-function-is_num.7.md), [cpsc-function-num_to_str(7)](cpsc-function-num_to_str.7.md).
+
diff --git a/doc/language/cpsc-function-ucase.7.md b/doc/language/cpsc-function-ucase.7.md
new file mode 100644
index 0000000..dd44892
--- /dev/null
+++ b/doc/language/cpsc-function-ucase.7.md
@@ -0,0 +1,28 @@
+% CPSC-FUNCTION-UCASE(7)
+
+# NAME
+
+cpsc-function-ucase - convert text to upper case
+
+# SYNOPSIS
+
+```text
+UCASE(text : STRING) RETURNS STRING
+```
+
+# DESCRIPTION
+
+Return a copy with letters converted to upper case. Unlike guide section 5.5's
+CHAR-to-CHAR signature, cpsc accepts text and returns STRING. Use ASCII
+text for predictable character conversion.
+
+# EXAMPLE
+
+```text
+OUTPUT UCASE("Hello")
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-function-lcase(7)](cpsc-function-lcase.7.md).
+
diff --git a/doc/language/cpsc-keyword-and.7.md b/doc/language/cpsc-keyword-and.7.md
new file mode 100644
index 0000000..6b98abf
--- /dev/null
+++ b/doc/language/cpsc-keyword-and.7.md
@@ -0,0 +1,28 @@
+% CPSC-KEYWORD-AND(7)
+
+# NAME
+
+cpsc-keyword-and - combine conditions with logical AND
+
+# SYNOPSIS
+
+```text
+left AND right
+```
+
+# DESCRIPTION
+
+Return BOOLEAN: true when both operands are true. Both operands are
+evaluated; AND does not short-circuit. AND binds more tightly than OR
+and less tightly than comparisons. Use parentheses for clarity.
+
+# EXAMPLE
+
+```text
+OUTPUT (3 > 2) AND (4 > 1)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-or(7)](cpsc-keyword-or.7.md), [cpsc-keyword-not(7)](cpsc-keyword-not.7.md), [cpsc-keyword-if(7)](cpsc-keyword-if.7.md).
+
diff --git a/doc/language/cpsc-keyword-call.7.md b/doc/language/cpsc-keyword-call.7.md
new file mode 100644
index 0000000..b17b3f4
--- /dev/null
+++ b/doc/language/cpsc-keyword-call.7.md
@@ -0,0 +1,31 @@
+% CPSC-KEYWORD-CALL(7)
+
+# NAME
+
+cpsc-keyword-call - invoke a procedure
+
+# SYNOPSIS
+
+```text
+CALL name(arguments)
+```
+
+# DESCRIPTION
+
+Invoke a previously declared procedure with its parameters. Empty argument
+lists may be written `CALL name()` or `CALL name`.
+Use function calls in expressions to obtain their results.
+
+# EXAMPLE
+
+```text
+PROCEDURE Hello()
+ OUTPUT "Hello"
+ENDPROCEDURE
+CALL Hello()
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-procedure(7)](cpsc-keyword-procedure.7.md), [cpsc-keyword-function(7)](cpsc-keyword-function.7.md).
+
diff --git a/doc/language/cpsc-keyword-class.7.md b/doc/language/cpsc-keyword-class.7.md
new file mode 100644
index 0000000..7ff32ba
--- /dev/null
+++ b/doc/language/cpsc-keyword-class.7.md
@@ -0,0 +1,43 @@
+% CPSC-KEYWORD-CLASS(7)
+
+# NAME
+
+cpsc-keyword-class - define a class with public and private fields
+
+# SYNOPSIS
+
+```text
+CLASS name
+ PUBLIC field : type
+ PRIVATE field : type
+ENDCLASS
+```
+
+# DESCRIPTION
+
+Declare a class at top level with at least one field. Every field explicitly
+requires PUBLIC or PRIVATE, without DECLARE. This differs from guide
+section 10's default-public rule. ENDCLASS closes the declaration.
+
+Classes use record value semantics: zero initialization, whole-value copying,
+arrays, pointers, and ordinary function/procedure parameters. Only PUBLIC
+fields can be accessed externally. PRIVATE fields still initialize and copy
+with the whole value. Methods, constructors, destructors, NEW, INHERITS,
+and array fields are unsupported.
+
+# EXAMPLE
+
+```text
+CLASS Person
+ PUBLIC Name : STRING
+ PRIVATE Age : INTEGER
+ENDCLASS
+DECLARE PersonValue : Person
+PersonValue.Name <- "Alice"
+OUTPUT PersonValue.Name
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-type(7)](cpsc-keyword-type.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md).
+
diff --git a/doc/language/cpsc-keyword-closefile.7.md b/doc/language/cpsc-keyword-closefile.7.md
new file mode 100644
index 0000000..b986b86
--- /dev/null
+++ b/doc/language/cpsc-keyword-closefile.7.md
@@ -0,0 +1,29 @@
+% CPSC-KEYWORD-CLOSEFILE(7)
+
+# NAME
+
+cpsc-keyword-closefile - close a text file
+
+# SYNOPSIS
+
+```text
+CLOSEFILE filename
+```
+
+# DESCRIPTION
+
+Close the file associated with this filename string and release its open-file
+slot. Closing a filename that is not open terminates execution.
+
+# EXAMPLE
+
+```text
+OPENFILE "notes.txt" FOR WRITE
+WRITEFILE "notes.txt", "Done"
+CLOSEFILE "notes.txt"
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md), [cpsc-keyword-writefile(7)](cpsc-keyword-writefile.7.md).
+
diff --git a/doc/language/cpsc-keyword-declare.7.md b/doc/language/cpsc-keyword-declare.7.md
new file mode 100644
index 0000000..887ae12
--- /dev/null
+++ b/doc/language/cpsc-keyword-declare.7.md
@@ -0,0 +1,40 @@
+% CPSC-KEYWORD-DECLARE(7)
+
+# NAME
+
+cpsc-keyword-declare - declare variables and arrays
+
+# SYNOPSIS
+
+```text
+DECLARE name : type
+DECLARE name : ARRAY[lower:upper, ...] OF type
+```
+
+# DESCRIPTION
+
+Declare one variable per statement. Built-in types are INTEGER (signed 64-bit),
+REAL, BOOLEAN, CHAR (one byte), and STRING. User-defined TYPE and CLASS names
+are also accepted. Variables start with zero, FALSE, an empty string, or a
+zero-initialized user-defined value.
+
+ARRAY bounds are inclusive and may be expressions; multiple ranges create
+multiple dimensions. Access elements with `name[index, ...]`. Bounds are
+checked at run time. Whole-array assignment is unsupported. Declare arrays
+before using them; arrays declared inside a control-flow block stay in that
+block.
+
+# EXAMPLE
+
+```text
+DECLARE Count : INTEGER
+DECLARE Names : ARRAY[1:3] OF STRING
+Count <- 2
+Names[Count] <- "Alice"
+OUTPUT Names[Count]
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-type(7)](cpsc-keyword-type.7.md), [cpsc-keyword-class(7)](cpsc-keyword-class.7.md), [cpsc-keyword-output(7)](cpsc-keyword-output.7.md).
+
diff --git a/doc/language/cpsc-keyword-div.7.md b/doc/language/cpsc-keyword-div.7.md
new file mode 100644
index 0000000..78715e1
--- /dev/null
+++ b/doc/language/cpsc-keyword-div.7.md
@@ -0,0 +1,28 @@
+% CPSC-KEYWORD-DIV(7)
+
+# NAME
+
+cpsc-keyword-div - perform integer division
+
+# SYNOPSIS
+
+```text
+left DIV right
+```
+
+# DESCRIPTION
+
+Both operands must be INTEGER. Return the quotient truncated toward zero.
+A zero divisor terminates execution. DIV has the same precedence as
+multiplication. Use `/` for division returning REAL.
+
+# EXAMPLE
+
+```text
+OUTPUT 7 DIV 2
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-mod(7)](cpsc-keyword-mod.7.md).
+
diff --git a/doc/language/cpsc-keyword-for.7.md b/doc/language/cpsc-keyword-for.7.md
new file mode 100644
index 0000000..201a492
--- /dev/null
+++ b/doc/language/cpsc-keyword-for.7.md
@@ -0,0 +1,35 @@
+% CPSC-KEYWORD-FOR(7)
+
+# NAME
+
+cpsc-keyword-for - iterate over an integer range
+
+# SYNOPSIS
+
+```text
+FOR variable <- start TO finish [STEP increment]
+ statements
+NEXT variable
+```
+
+# DESCRIPTION
+
+The loop variable must already be declared INTEGER. Both endpoints are
+inclusive. STEP defaults to 1; use a negative value to count down.
+STEP is evaluated once, while the finish expression is evaluated each
+iteration. NEXT must name the same variable. Use a nonzero STEP.
+TO, STEP, and NEXT belong to this syntax.
+
+# EXAMPLE
+
+```text
+DECLARE Index : INTEGER
+FOR Index <- 3 TO 1 STEP -1
+ OUTPUT Index
+NEXT Index
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md), [cpsc-keyword-while(7)](cpsc-keyword-while.7.md).
+
diff --git a/doc/language/cpsc-keyword-function.7.md b/doc/language/cpsc-keyword-function.7.md
new file mode 100644
index 0000000..c37754c
--- /dev/null
+++ b/doc/language/cpsc-keyword-function.7.md
@@ -0,0 +1,41 @@
+% CPSC-KEYWORD-FUNCTION(7)
+
+# NAME
+
+cpsc-keyword-function - define a function that returns a value
+
+# SYNOPSIS
+
+```text
+FUNCTION name(parameters) RETURNS type
+ statements
+ RETURN expression
+ENDFUNCTION
+```
+
+# DESCRIPTION
+
+Call a function in an expression as `name(arguments)`. A call may precede its
+top-level definition. RETURNS specifies the result type; omitting it defaults
+to INTEGER. RETURN supplies a value of that type. Whole-array results are
+unsupported.
+
+Parameters use `name : type`, optionally prefixed by BYVAL. BYVAL is the
+default; BYREF is forbidden for functions (guide section 8.3).
+Array parameters accept `ARRAY OF type` (one dimension) or
+`ARRAY[lower:upper, ...] OF type` (integer literal bounds).
+BYVAL arrays are copied. RETURNS, RETURN, BYVAL, and ENDFUNCTION belong here.
+
+# EXAMPLE
+
+```text
+FUNCTION Double(Value : INTEGER) RETURNS INTEGER
+ RETURN Value * 2
+ENDFUNCTION
+OUTPUT Double(4)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-procedure(7)](cpsc-keyword-procedure.7.md), [cpsc-keyword-call(7)](cpsc-keyword-call.7.md).
+
diff --git a/doc/language/cpsc-keyword-if.7.md b/doc/language/cpsc-keyword-if.7.md
new file mode 100644
index 0000000..9f14959
--- /dev/null
+++ b/doc/language/cpsc-keyword-if.7.md
@@ -0,0 +1,35 @@
+% CPSC-KEYWORD-IF(7)
+
+# NAME
+
+cpsc-keyword-if - choose between branches
+
+# SYNOPSIS
+
+```text
+IF condition THEN
+ statements
+ELSE
+ statements
+ENDIF
+```
+
+# DESCRIPTION
+
+Execute the THEN branch when the condition is true, otherwise the optional
+ELSE branch. Blocks may be nested. THEN, ELSE, and ENDIF belong to this syntax.
+
+# EXAMPLE
+
+```text
+IF 3 > 2 THEN
+ OUTPUT "yes"
+ELSE
+ OUTPUT "no"
+ENDIF
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-and(7)](cpsc-keyword-and.7.md), [cpsc-keyword-or(7)](cpsc-keyword-or.7.md), [cpsc-keyword-not(7)](cpsc-keyword-not.7.md).
+
diff --git a/doc/language/cpsc-keyword-input.7.md b/doc/language/cpsc-keyword-input.7.md
new file mode 100644
index 0000000..f31731f
--- /dev/null
+++ b/doc/language/cpsc-keyword-input.7.md
@@ -0,0 +1,31 @@
+% CPSC-KEYWORD-INPUT(7)
+
+# NAME
+
+cpsc-keyword-input - read a value from standard input
+
+# SYNOPSIS
+
+```text
+INPUT variable
+```
+
+# DESCRIPTION
+
+Read into a previously declared INTEGER, REAL, BOOLEAN, CHAR, or STRING
+variable. STRING input reads one whitespace-delimited word. The target must
+be a plain variable; array elements and record/class fields are unsupported,
+unlike the wider INPUT syntax in guide section 5.1.
+
+# EXAMPLE
+
+```text
+DECLARE Name : STRING
+INPUT Name
+OUTPUT Name
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md), [cpsc-keyword-output(7)](cpsc-keyword-output.7.md).
+
diff --git a/doc/language/cpsc-keyword-mod.7.md b/doc/language/cpsc-keyword-mod.7.md
new file mode 100644
index 0000000..cb437a4
--- /dev/null
+++ b/doc/language/cpsc-keyword-mod.7.md
@@ -0,0 +1,29 @@
+% CPSC-KEYWORD-MOD(7)
+
+# NAME
+
+cpsc-keyword-mod - find the integer division remainder
+
+# SYNOPSIS
+
+```text
+left MOD right
+```
+
+# DESCRIPTION
+
+Both operands must be INTEGER. Return the remainder after division truncated
+toward zero; a nonzero remainder has the dividend's sign.
+A zero divisor terminates execution. MOD has the same precedence as
+multiplication.
+
+# EXAMPLE
+
+```text
+OUTPUT 7 MOD 2
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-div(7)](cpsc-keyword-div.7.md).
+
diff --git a/doc/language/cpsc-keyword-not.7.md b/doc/language/cpsc-keyword-not.7.md
new file mode 100644
index 0000000..5bb1c18
--- /dev/null
+++ b/doc/language/cpsc-keyword-not.7.md
@@ -0,0 +1,27 @@
+% CPSC-KEYWORD-NOT(7)
+
+# NAME
+
+cpsc-keyword-not - negate a condition
+
+# SYNOPSIS
+
+```text
+NOT expression
+```
+
+# DESCRIPTION
+
+Return BOOLEAN with the opposite truth value. NOT is a unary operator;
+parenthesize comparisons, for example `NOT (Count = 0)`.
+
+# EXAMPLE
+
+```text
+OUTPUT NOT (3 = 2)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-and(7)](cpsc-keyword-and.7.md), [cpsc-keyword-or(7)](cpsc-keyword-or.7.md), [cpsc-keyword-if(7)](cpsc-keyword-if.7.md).
+
diff --git a/doc/language/cpsc-keyword-openfile.7.md b/doc/language/cpsc-keyword-openfile.7.md
new file mode 100644
index 0000000..a13b3f4
--- /dev/null
+++ b/doc/language/cpsc-keyword-openfile.7.md
@@ -0,0 +1,37 @@
+% CPSC-KEYWORD-OPENFILE(7)
+
+# NAME
+
+cpsc-keyword-openfile - open a text file
+
+# SYNOPSIS
+
+```text
+OPENFILE filename FOR READ
+OPENFILE filename FOR WRITE
+OPENFILE filename FOR APPEND
+```
+
+# DESCRIPTION
+
+The filename is a STRING expression. READ opens an existing file for reading;
+WRITE creates or truncates a file; APPEND writes at the end, creating the file
+if needed. READ, WRITE, APPEND, and this use of FOR belong here.
+
+At most 16 files may be open at once. Use the same filename string for
+subsequent operations. Reopening an open filename, failed opens, and wrong-mode
+operations terminate execution with a fatal diagnostic. RANDOM is reserved
+but unsupported.
+
+# EXAMPLE
+
+```text
+OPENFILE "notes.txt" FOR WRITE
+WRITEFILE "notes.txt", "Hello"
+CLOSEFILE "notes.txt"
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md), [cpsc-keyword-writefile(7)](cpsc-keyword-writefile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md).
+
diff --git a/doc/language/cpsc-keyword-or.7.md b/doc/language/cpsc-keyword-or.7.md
new file mode 100644
index 0000000..7fca628
--- /dev/null
+++ b/doc/language/cpsc-keyword-or.7.md
@@ -0,0 +1,28 @@
+% CPSC-KEYWORD-OR(7)
+
+# NAME
+
+cpsc-keyword-or - combine conditions with logical OR
+
+# SYNOPSIS
+
+```text
+left OR right
+```
+
+# DESCRIPTION
+
+Return BOOLEAN: true when either operand is true. Both operands are
+evaluated; OR does not short-circuit. OR binds less tightly than AND
+and comparisons.
+
+# EXAMPLE
+
+```text
+OUTPUT (3 < 2) OR (4 > 1)
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-and(7)](cpsc-keyword-and.7.md), [cpsc-keyword-not(7)](cpsc-keyword-not.7.md), [cpsc-keyword-if(7)](cpsc-keyword-if.7.md).
+
diff --git a/doc/language/cpsc-keyword-output.7.md b/doc/language/cpsc-keyword-output.7.md
new file mode 100644
index 0000000..9ee2133
--- /dev/null
+++ b/doc/language/cpsc-keyword-output.7.md
@@ -0,0 +1,32 @@
+% CPSC-KEYWORD-OUTPUT(7)
+
+# NAME
+
+cpsc-keyword-output - print values to standard output
+
+# SYNOPSIS
+
+```text
+OUTPUT expression, ...
+```
+
+# DESCRIPTION
+
+Print expressions from left to right without automatic separators, then add
+a newline. Strings print their contents; BOOLEAN prints TRUE or FALSE.
+Whole arrays and partially indexed arrays print their elements one per line;
+a final array adds no extra newline. Records, classes, and pointers cannot
+be printed directly.
+
+# EXAMPLE
+
+```text
+DECLARE Score : INTEGER
+Score <- 10
+OUTPUT "Score: ", Score
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-input(7)](cpsc-keyword-input.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md).
+
diff --git a/doc/language/cpsc-keyword-procedure.7.md b/doc/language/cpsc-keyword-procedure.7.md
new file mode 100644
index 0000000..b2e6108
--- /dev/null
+++ b/doc/language/cpsc-keyword-procedure.7.md
@@ -0,0 +1,43 @@
+% CPSC-KEYWORD-PROCEDURE(7)
+
+# NAME
+
+cpsc-keyword-procedure - define a procedure and parameter modes
+
+# SYNOPSIS
+
+```text
+PROCEDURE name(parameters)
+ statements
+ENDPROCEDURE
+```
+
+# DESCRIPTION
+
+Invoke with CALL. Parameters use `name : type`, optionally prefixed by
+BYVAL or BYREF. The default is BYVAL (copy); BYREF modifies the caller's
+variable and requires an exact type match. Scalar BYREF arguments must be
+plain variables. A mode remains in effect for following parameters until
+another mode is specified.
+
+Arrays accept `ARRAY OF type` or `ARRAY[lower:upper, ...] OF type`;
+explicit bounds must be integer literals. BYVAL copies the array; BYREF
+shares it. Bare RETURN can exit a procedure before a block terminator;
+RETURN with a value is invalid. BYVAL, BYREF, RETURN, and ENDPROCEDURE
+belong here. Calls may precede top-level definitions.
+
+# EXAMPLE
+
+```text
+PROCEDURE Increment(BYREF Value : INTEGER)
+ Value <- Value + 1
+ENDPROCEDURE
+DECLARE Count : INTEGER
+CALL Increment(Count)
+OUTPUT Count
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-call(7)](cpsc-keyword-call.7.md), [cpsc-keyword-function(7)](cpsc-keyword-function.7.md).
+
diff --git a/doc/language/cpsc-keyword-readfile.7.md b/doc/language/cpsc-keyword-readfile.7.md
new file mode 100644
index 0000000..71cd3db
--- /dev/null
+++ b/doc/language/cpsc-keyword-readfile.7.md
@@ -0,0 +1,34 @@
+% CPSC-KEYWORD-READFILE(7)
+
+# NAME
+
+cpsc-keyword-readfile - read a line from a text file
+
+# SYNOPSIS
+
+```text
+READFILE filename, variable
+```
+
+# DESCRIPTION
+
+Read one line from a file opened FOR READ, removing the line ending.
+The target must be a plain, previously declared STRING variable.
+Guard reads with EOF; reading past the end terminates execution.
+
+# EXAMPLE
+
+```text
+DECLARE Line : STRING
+OPENFILE "notes.txt" FOR READ
+WHILE NOT EOF("notes.txt") DO
+ READFILE "notes.txt", Line
+ OUTPUT Line
+ENDWHILE
+CLOSEFILE "notes.txt"
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md), [cpsc-function-eof(7)](cpsc-function-eof.7.md).
+
diff --git a/doc/language/cpsc-keyword-repeat.7.md b/doc/language/cpsc-keyword-repeat.7.md
new file mode 100644
index 0000000..42fdd2d
--- /dev/null
+++ b/doc/language/cpsc-keyword-repeat.7.md
@@ -0,0 +1,34 @@
+% CPSC-KEYWORD-REPEAT(7)
+
+# NAME
+
+cpsc-keyword-repeat - repeat until a condition is true
+
+# SYNOPSIS
+
+```text
+REPEAT
+ statements
+UNTIL condition
+```
+
+# DESCRIPTION
+
+Test after each iteration, so the body runs at least once.
+Stop when the condition becomes true. UNTIL belongs to this syntax.
+
+# EXAMPLE
+
+```text
+DECLARE Count : INTEGER
+Count <- 0
+REPEAT
+ Count <- Count + 1
+ OUTPUT Count
+UNTIL Count = 3
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-while(7)](cpsc-keyword-while.7.md), [cpsc-keyword-for(7)](cpsc-keyword-for.7.md).
+
diff --git a/doc/language/cpsc-keyword-type.7.md b/doc/language/cpsc-keyword-type.7.md
new file mode 100644
index 0000000..d630403
--- /dev/null
+++ b/doc/language/cpsc-keyword-type.7.md
@@ -0,0 +1,53 @@
+% CPSC-KEYWORD-TYPE(7)
+
+# NAME
+
+cpsc-keyword-type - define enumerations, pointers, and records
+
+# SYNOPSIS
+
+```text
+TYPE name = (value, ...)
+TYPE name = ^type
+TYPE name
+ DECLARE field : type
+ENDTYPE
+```
+
+# DESCRIPTION
+
+Define types at top level. Enumeration values have globally reserved names;
+OUTPUT prints their zero-based ordinals. Enumerations support comparisons
+with the same type and addition/subtraction of INTEGER offsets; invalid
+ordinals terminate execution.
+
+A prefix caret takes an address (`^variable`); a suffix caret dereferences
+a pointer (`pointer^`). Pointee types must match exactly, even where guide
+section 4.2's example mixes types. Pointers start null; dereferencing null
+terminates execution. There is no NULL literal. Avoid pointers to local
+variables after the function returns.
+
+Records contain one or more DECLARE fields and end with ENDTYPE. Access
+fields with a dot. Whole records copy by value; array fields are unsupported.
+Distinct user-defined type names remain distinct types. SET/DEFINE are
+reserved but unsupported.
+
+# EXAMPLE
+
+```text
+TYPE Point
+ DECLARE X : INTEGER
+ DECLARE Y : INTEGER
+ENDTYPE
+TYPE PointPtr = ^Point
+DECLARE Position : Point
+DECLARE Pointer : PointPtr
+Pointer <- ^Position
+Pointer^.X <- 3
+OUTPUT Position.X
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md), [cpsc-keyword-class(7)](cpsc-keyword-class.7.md).
+
diff --git a/doc/language/cpsc-keyword-while.7.md b/doc/language/cpsc-keyword-while.7.md
new file mode 100644
index 0000000..e6707b4
--- /dev/null
+++ b/doc/language/cpsc-keyword-while.7.md
@@ -0,0 +1,34 @@
+% CPSC-KEYWORD-WHILE(7)
+
+# NAME
+
+cpsc-keyword-while - repeat while a condition is true
+
+# SYNOPSIS
+
+```text
+WHILE condition DO
+ statements
+ENDWHILE
+```
+
+# DESCRIPTION
+
+Test before each iteration; the body may run zero times.
+DO and ENDWHILE belong to this syntax.
+
+# EXAMPLE
+
+```text
+DECLARE Count : INTEGER
+Count <- 1
+WHILE Count <= 3 DO
+ OUTPUT Count
+ Count <- Count + 1
+ENDWHILE
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-repeat(7)](cpsc-keyword-repeat.7.md), [cpsc-keyword-for(7)](cpsc-keyword-for.7.md).
+
diff --git a/doc/language/cpsc-keyword-writefile.7.md b/doc/language/cpsc-keyword-writefile.7.md
new file mode 100644
index 0000000..a00be5e
--- /dev/null
+++ b/doc/language/cpsc-keyword-writefile.7.md
@@ -0,0 +1,30 @@
+% CPSC-KEYWORD-WRITEFILE(7)
+
+# NAME
+
+cpsc-keyword-writefile - write a line to a text file
+
+# SYNOPSIS
+
+```text
+WRITEFILE filename, expression
+```
+
+# DESCRIPTION
+
+Write one value as text followed by a newline. Open the file FOR WRITE or
+APPEND first. Exactly one data expression is accepted; join strings with
+`&` when needed. Records, classes, and pointers are unsupported as data.
+
+# EXAMPLE
+
+```text
+OPENFILE "notes.txt" FOR APPEND
+WRITEFILE "notes.txt", "Score: " & NUM_TO_STR(10)
+CLOSEFILE "notes.txt"
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md), [cpsc-function-num_to_str(7)](cpsc-function-num_to_str.7.md).
+
diff --git a/doc/language/cpsc-language-overview.7.md b/doc/language/cpsc-language-overview.7.md
new file mode 100644
index 0000000..8adf362
--- /dev/null
+++ b/doc/language/cpsc-language-overview.7.md
@@ -0,0 +1,100 @@
+% CPSC-LANGUAGE-OVERVIEW(7)
+
+# NAME
+
+cpsc-language-overview - supported cpsc pseudocode syntax
+
+# DESCRIPTION
+
+Keywords and built-in function names are uppercase and case-sensitive.
+Indentation is for readability; blocks use explicit closing keywords.
+Identifiers begin with a letter and continue with letters,
+digits, or underscores.
+
+Assign with ASCII `<-`: `Count <- Count + 1`. Compare with `=`, `<>`,
+`<`, `>`, `<=`, and `>=`. STRING comparisons compare contents,
+case-sensitively. Use `+`, `-`, `*`, and `/` for arithmetic;
+`/` always returns REAL. Use `&` to join strings.
+
+Precedence, from highest to lowest: unary operators, `* / DIV MOD`,
+`+ - &`, comparisons, AND, OR. Parentheses override precedence.
+
+Literals include integers, decimal real numbers, TRUE/FALSE, strings in
+double quotes, and single-byte characters in single quotes. Negative
+numbers use unary minus. There are no string or character escape sequences.
+Comments begin with `//` and continue to the end of the line.
+
+Declare variables before use. See DECLARE for built-in types and arrays,
+TYPE for records/enumerations/pointers, and CLASS for public/private fields.
+
+# KEYWORDS
+
+- [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md): declare variables and arrays.
+- [cpsc-keyword-input(7)](cpsc-keyword-input.7.md): read a value from standard input.
+- [cpsc-keyword-output(7)](cpsc-keyword-output.7.md): print values to standard output.
+- [cpsc-keyword-if(7)](cpsc-keyword-if.7.md): choose between branches.
+- [cpsc-keyword-while(7)](cpsc-keyword-while.7.md): repeat while a condition is true.
+- [cpsc-keyword-repeat(7)](cpsc-keyword-repeat.7.md): repeat until a condition is true.
+- [cpsc-keyword-for(7)](cpsc-keyword-for.7.md): iterate over an integer range.
+- [cpsc-keyword-function(7)](cpsc-keyword-function.7.md): define a function that returns a value.
+- [cpsc-keyword-procedure(7)](cpsc-keyword-procedure.7.md): define a procedure and parameter modes.
+- [cpsc-keyword-call(7)](cpsc-keyword-call.7.md): invoke a procedure.
+- [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md): open a text file.
+- [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md): read a line from a text file.
+- [cpsc-keyword-writefile(7)](cpsc-keyword-writefile.7.md): write a line to a text file.
+- [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md): close a text file.
+- [cpsc-keyword-type(7)](cpsc-keyword-type.7.md): define enumerations, pointers, and records.
+- [cpsc-keyword-class(7)](cpsc-keyword-class.7.md): define a class with public and private fields.
+- [cpsc-keyword-and(7)](cpsc-keyword-and.7.md): combine conditions with logical AND.
+- [cpsc-keyword-or(7)](cpsc-keyword-or.7.md): combine conditions with logical OR.
+- [cpsc-keyword-not(7)](cpsc-keyword-not.7.md): negate a condition.
+- [cpsc-keyword-div(7)](cpsc-keyword-div.7.md): perform integer division.
+- [cpsc-keyword-mod(7)](cpsc-keyword-mod.7.md): find the integer division remainder.
+
+Closing and auxiliary keywords are documented with their main constructs:
+THEN/ELSE/ENDIF with IF; DO/ENDWHILE with WHILE; UNTIL with REPEAT;
+TO/STEP/NEXT with FOR; RETURN/RETURNS/BYVAL/BYREF and function/procedure
+closing keywords with FUNCTION/PROCEDURE; READ/WRITE/APPEND with OPENFILE;
+ARRAY/OF and INTEGER/REAL/BOOLEAN/CHAR/STRING with DECLARE;
+ENDTYPE with TYPE; PUBLIC/PRIVATE/ENDCLASS with CLASS.
+TRUE/FALSE are BOOLEAN literals.
+
+# BUILT-IN FUNCTIONS
+
+- [cpsc-function-length(7)](cpsc-function-length.7.md): find a string's length.
+- [cpsc-function-mid(7)](cpsc-function-mid.7.md): extract part of a string.
+- [cpsc-function-left(7)](cpsc-function-left.7.md): extract the beginning of a string.
+- [cpsc-function-right(7)](cpsc-function-right.7.md): extract the end of a string.
+- [cpsc-function-lcase(7)](cpsc-function-lcase.7.md): convert text to lower case.
+- [cpsc-function-ucase(7)](cpsc-function-ucase.7.md): convert text to upper case.
+- [cpsc-function-asc(7)](cpsc-function-asc.7.md): find a character's byte code.
+- [cpsc-function-chr(7)](cpsc-function-chr.7.md): convert a byte code to text.
+- [cpsc-function-is_num(7)](cpsc-function-is_num.7.md): test whether text represents a number.
+- [cpsc-function-num_to_str(7)](cpsc-function-num_to_str.7.md): convert a number to text.
+- [cpsc-function-str_to_num(7)](cpsc-function-str_to_num.7.md): convert text to a real number.
+- [cpsc-function-eof(7)](cpsc-function-eof.7.md): test for the end of a text file.
+
+# UNSUPPORTED FEATURES
+
+CASE OF, CONSTANT, DATE, SET types and DEFINE, random-file operations
+(RANDOM/SEEK/GETRECORD/PUTRECORD), INT, RAND, INPUT into array elements or
+fields, string escapes, whole-array assignment or return, array fields,
+and class methods/constructors/destructors/inheritance (NEW/INHERITS/SUPER).
+
+The individual pages note relevant differences from the Cambridge 2026
+pseudocode guide. This manual describes the compiler's current support.
+
+# EXAMPLE
+
+```text
+DECLARE Count : INTEGER
+Count <- 2
+IF Count > 0 THEN
+ OUTPUT "Count: " & NUM_TO_STR(Count)
+ENDIF
+```
+
+# SEE ALSO
+
+[cpsc(1)](../cpsc.1.md).
+