Syntax

This page summarizes the syntax implemented by lexer/lexer.l and parser/parser.y.

Lexical rules

Identifiers start with an ASCII letter or underscore and may then contain letters, digits, or underscores. Keywords are lowercase. Whitespace is ignored.

count
_temporary
item2

Comments

A single-line comment starts with #. A multiline comment is enclosed by #{ and }#.

# one line

#{
  more than
  one line
}#

Comments do not nest.

Program structure

program        ::= function_definition*
function       ::= type identifier "(" parameters? ")" block
parameters     ::= parameter ("," parameter)*
parameter      ::= type identifier
block          ::= "{" statement* "}"

Only complete function definitions are allowed at file scope. Forward declarations such as void work(); are rejected. An empty source file parses, although a useful executable defines void main().

Declarations

scalar         ::= type declarator ("," declarator)* ";"
declarator     ::= identifier "=" expression
array          ::= type identifier "[" array_size "]"
                   ("=" "{" expression ("," expression)* "}")? ";"
array_size     ::= integer_literal | identifier
int x = 1, y = 2;
string label = "sum";
int values[3] = {10, 20, 30};

Only one array may be declared in a declaration, and an array declaration cannot be mixed with scalar declarators. Arrays are one-dimensional. An array size is an integer literal or identifier and must evaluate to a positive int.

Statements

Simple statements end in semicolons:

int x = 1;
x = 2;
x += 3;
x++;
print(x);
return x;
break;
continue;

Blocks and control-flow statements do not take a trailing semicolon. A bare identifier, array access, unary expression, or binary expression is not a valid statement.

Operator precedence

From lowest to highest:

Level Operators Associativity
logical OR || left
logical AND && left
equality == != left
relational < > <= >= left
additive + - left
multiplicative * / left
unary ! + - right

Assignment is a statement, except that a parenthesized assignment such as (x = 1); is accepted. Array subscripts are restricted to an integer literal or identifier.

Literal forms

  • integer: one or more digits, such as 42
  • double: digits on both sides of one decimal point, such as 3.14
  • boolean: true or false
  • character: zero or one ordinary/escaped character in single quotes
  • string: zero or more ordinary/escaped characters in double quotes

Recognized escapes include newline, tab, carriage return, backspace, form feed, null, backslash, double quote, and single quote escapes.