Skip to content

tags: - grammar - syntax - reference - bnf


Grammar Reference

This document provides the complete formal grammar specification for EverSharp, including BNF notation and syntax diagrams.

BNF Grammar

EverSharp's grammar is defined using Backus-Naur Form (BNF) notation. The grammar is implemented as a recursive descent parser.

Complete Grammar

program                 → declaration* EOF ;

declaration             → function_declaration | statement ;

function_declaration    → "function" function ;

function                → identifier "(" parameters* ")" block ;

parameters              → identifier ( "," identifier )* ;

statement               → expression_statement
                        | if_statement
                        | return_statement
                        | exit_statement
                        | throw_statement
                        | while_statement
                        | block ;

expression_statement    → expression ";" ;

if_statement            → "if" "(" expression ")" statement ( "else" statement )? ;

return_statement        → "return" expression? ";" ;

exit_statement          → "exit" ";" ;

throw_statement         → "throw" expression? ";" ;

while_statement         → "while" "(" expression ")" statement ;

block                   → "{" declaration* "}" ;

expression              → assignment ;

assignment              → ( call "." ) identifier ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" ) assignment
                        | logical_or ;

logical_or              → logical_and ( "||" logical_and )* ;

logical_and             → equality ( "&&" equality )* ;

equality                → comparison ( ( "!=" | "==" ) comparison )* ;

comparison              → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;

term                    → factor ( ( "-" | "+" ) factor )* ;

factor                  → unary ( ( "/" | "*" | "%" ) unary )* ;

unary                   → ( "!" | "-" ) unary
                        | postfix ;

postfix                 → call ( "++" | "--" )* ;

call                    → "{" properties? "}"
                        | "[" expression ( "," expression )* "]"
                        | primary ( "(" arguments? ")" | "." identifier | "[" expression "]" )* ;

properties              → property_initialization ( "," property_initialization )* ;

property_initialization → string ":" expression ;

arguments               → argument ( "," argument )* ;

argument                → lambda | ternary | expression ;

lambda                  → ( identifier | "(" parameters* ")" ) "=>" lambda_body ;

lambda_body             → expression | block ;

ternary                 → expression "?" expression ":" expression ;

primary                 → identifier
                        | NUMBER
                        | STRING
                        | "true"
                        | "false"
                        | "null"
                        | "(" expression ")" ;

Grammar Notation

Symbols

Symbol Meaning Example
Produces/expands to statement → if_statement
\| Or (alternative) statement \| expression
* Zero or more declaration*
+ One or more digit+
? Optional (zero or one) "else" statement?
( ) Grouping ( "," identifier )*
"text" Terminal (literal) "function"
lowercase Non-terminal expression
UPPERCASE Token type IDENTIFIER

Terminal Symbols

Terminals are literal tokens in the language:

  • Keywords: function, if, else, while, return, true, false, null
  • Operators: +, -, *, /, %, =, ==, !=, <, >, <=, >=, &&, ||, !, ++, --
  • Delimiters: (, ), {, }, [, ], ;, ,, ., :
  • Literals: Numbers, strings, identifiers

Production Rules Explained

Program Structure

program → declaration* EOF

A program consists of zero or more declarations followed by end-of-file.

Example:

x = 10;
function add(a, b) {
  return a + b;
}
result = add(5, 3);

Declarations

declaration → function_declaration | statement

A declaration is either a function declaration or a statement.

Function Declaration:

function calculateTotal(amount, rate) {
  return amount * rate;
}

Statement as Declaration:

x = 5;

Statements

statement → expression_statement
          | if_statement
          | return_statement
          | while_statement
          | block

Expression Statement

expression_statement → expression ";"

Any expression followed by a semicolon.

Examples:

x = 10;
calculateTotal(100, 0.08);
items.Push(5);

If Statement

if_statement → "if" "(" expression ")" statement ( "else" statement )?

Examples:

if (age >= 18) {
  status = "Adult";
}

if (score >= 90) {
  grade = "A";
} else if (score >= 80) {
  grade = "B";
} else {
  grade = "C";
}

While Statement

while_statement → "while" "(" expression ")" statement

Example:

i = 0;
while (i < 10) {
  sum = sum + i;
  i = i + 1;
}

Return Statement

return_statement → "return" expression? ";"

Examples:

return; // Return null
return 42; // Return value
return a + b; // Return expression result

Block Statement

block → "{" declaration* "}"

Example:

{
  x = 10;
  y = 20;
  result = x + y;
}

Expressions

Expressions are evaluated in order of precedence (highest to lowest):

  1. Primary (literals, identifiers, grouping)
  2. Postfix (++, --)
  3. Unary (!, -)
  4. Factor (*, /, %)
  5. Term (+, -)
  6. Comparison (<, <=, >, >=)
  7. Equality (==, !=)
  8. Logical AND (&&)
  9. Logical OR (||)
  10. Ternary (? :)
  11. Assignment (=, +=, -=, *=, /=, %=)

Assignment

assignment → ( call "." ) identifier ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" ) assignment
           | logical_or

Examples:

x = 10; // Simple assignment
x += 5; // Compound assignment
person.age = 30; // Property assignment

Logical Operators

logical_or  → logical_and ( "||" logical_and )*
logical_and → equality ( "&&" equality )*

Examples:

isValid = age >= 18 && hasLicense;
canProceed = isApproved || isOverride;

Equality and Comparison

equality   → comparison ( ( "!=" | "==" ) comparison )*
comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )*

Examples:

isEqual = x == y;
isGreater = a > b;
inRange = value >= min && value <= max;

Arithmetic

term   → factor ( ( "-" | "+" ) factor )*
factor → unary ( ( "/" | "*" | "%" ) unary )*

Examples:

sum = a + b;
product = x * y;
remainder = value % 10;

Unary and Postfix

unary   → ( "!" | "-" ) unary | postfix
postfix → call ( "++" | "--" )*

Examples:

negative = -value;
inverted = !flag;
count++;
index--;

Call Expressions

call → "{" properties? "}"                                    // Object literal
     | "[" expression ( "," expression )* "]"                 // Array literal
     | primary ( "(" arguments? ")" | "." identifier | "[" expression "]" )*

Examples:

// Function call
result = calculate(10, 20);

// Method call
upper = name.ToUpper();

// Array access
item = items[0];

// Chained calls
result = items.Filter((x) => x > 5).Map((x) => x * 2);

Object Literals

call → "{" properties? "}"
properties → property_initialization ( "," property_initialization )*
property_initialization → string ":" expression

Example:

person = {
  name: "John",
  age: 30,
  email: "john@example.com",
};

Array Literals

call → "[" expression ( "," expression )* "]"

Example:

numbers = [1, 2, 3, 4, 5];
names = ["Alice", "Bob", "Charlie"];
mixed = [1, "hello", true];

Lambda Expressions

lambda → ( identifier | "(" parameters* ")" ) "=>" lambda_body
lambda_body → expression | block

Examples:

// Single parameter, expression body
square = (n) => n * n;

// Multiple parameters
add = (a, b) => a + b;

// No parameters
getRandomNumber = () => 42;

// Block body
process = (x) => {
  result = x * 2;
  return result + 1;
};

Ternary Operator

ternary → expression "?" expression ":" expression

Example:

status = age >= 18 ? "Adult" : "Minor";
max = a > b ? a : b;

Primary Expressions

primary → identifier
        | NUMBER
        | STRING
        | "true"
        | "false"
        | "null"
        | "(" expression ")"

Examples:

x; // identifier
42; // number
("hello"); // string
true; // boolean literal
false; // boolean literal
null(
  // null literal
  a + b
); // grouped expression

Syntax Diagrams

Function Declaration

function ───→ identifier ───→ ( ───→ parameters ───→ ) ───→ block
                                     (optional)

If Statement

if ───→ ( ───→ expression ───→ ) ───→ statement ───┬───→
                                                     └───→ else ───→ statement ───→

While Statement

while ───→ ( ───→ expression ───→ ) ───→ statement ───→

Assignment Expression

                        ┌───→ = ───┐
identifier ───→ ───────┼───→ += ──┼───→ assignment ───→
                        ├───→ -= ──┤
                        ├───→ *= ──┤
                        ├───→ /= ──┤
                        └───→ %= ──┘

Binary Operators

expression ───→ operator ───→ expression ───→

Where operator can be:

  • Arithmetic: +, -, *, /, %
  • Comparison: <, <=, >, >=
  • Equality: ==, !=
  • Logical: &&, ||

Call Expression

                     ┌──────────────────────────────────────┐
                     │                                      │
primary ───→ ───────┼───→ ( ───→ arguments ───→ ) ─────────┼───→
                     │                                      │
                     ├───→ . ───→ identifier ───────────────┤
                     │                                      │
                     └───→ [ ───→ expression ───→ ] ────────┘

Associativity and Precedence

Left-Associative Operators

Most binary operators are left-associative:

a + b + c    →    (a + b) + c
a - b - c    →    (a - b) - c
a * b * c    →    (a * b) * c

Right-Associative Operators

Assignment operators are right-associative:

a = b = c    →    a = (b = c)

Non-Associative Operators

Comparison operators do not chain:

// Invalid:
a < b < c

// Must be:
a < b && b < c

Operator Precedence Table

| Level | Operators | Description | Associativity | | ----- | ---------------------------- | -------------------------------- | ------------- | ---------- | ---- | | 1 | () [] . | Call, subscript, member access | Left | | 2 | ++ -- | Postfix increment/decrement | Left | | 3 | ! - | Logical NOT, unary minus | Right | | 4 | * / % | Multiplication, division, modulo | Left | | 5 | + - | Addition, subtraction | Left | | 6 | < <= > >= | Comparison | Left | | 7 | == != | Equality | Left | | 8 | && | Logical AND | Left | | 9 | | | | Logical OR | Left | | 10 | ? : | Ternary conditional | Right | | 11 | = += -= *= /= %= | Assignment | Right |

Lexical Structure

Tokens

EverSharp recognizes the following token types:

Keywords

function  if  else  while  return  true  false  null

Identifiers

identifier → letter ( letter | digit | "_" )*
letter     → "a"..."z" | "A"..."Z" | "_"
digit      → "0"..."9"

Examples: x, myVariable, calculate_total, Item123

Numbers

NUMBER → digit+ ( "." digit+ )?

Examples: 42, 3.14159, 0.5, 1000

Strings

STRING → '"' character* '"'

Examples: "hello", "John Smith", "123 Main St"

Operators

+ - * / % = == != < > <= >= && || ! ++ -- += -= *= /= %=

Delimiters

( ) { } [ ] ; , . : =>

Comments

EverSharp supports single-line comments:

// This is a comment
x = 10; // Comment after statement

Note: Multi-line comments are not supported.

Whitespace

Whitespace (spaces, tabs, newlines) is ignored except:

  • To separate tokens
  • Inside string literals

Grammar Properties

Unambiguous

The grammar is designed to be unambiguous - each valid program has exactly one parse tree.

Predictable

The grammar uses predictable parsing - the parser can determine which production to use by looking at the current token (one token lookahead).

Recursive

The grammar is recursive, allowing:

  • Nested expressions: (a + (b * (c - d)))
  • Nested blocks: { { { x = 1; } } }
  • Recursive function calls

Complete

The grammar covers all language constructs:

  • Declarations (functions)
  • Statements (if, while, return, block, expression)
  • Expressions (all operators, literals, calls, lambdas)

Parsing Strategy

EverSharp uses recursive descent parsing:

  1. Each non-terminal has a corresponding parsing function
  2. The parser maintains a token stream
  3. Functions consume tokens and return AST nodes
  4. Precedence is encoded in the grammar structure

Error Recovery

The parser performs minimal error recovery:

  • Syntax errors are collected
  • Parsing continues after errors when possible
  • Multiple errors can be reported in a single pass

See Also