Parser API
The Parser API provides a comprehensive parser for the Prism language, transforming source code into an Abstract Syntax Tree (AST) that can be executed by the runtime.
Overview
The parser handles:
- Tokenization of source code
- Parsing of all Prism language constructs
- Error handling with detailed error messages
- Support for confidence expressions and uncertain control flow
- Pipeline operators and placeholders
- Destructuring patterns with confidence thresholds
Parser Class
Constructor
class Parser {
constructor(tokens: Token[], sourceCode?: string)
}
Parameters:
tokens
: Array of tokens from the tokenizersourceCode
: Optional source code for enhanced error messages
Methods
parse()
parse(): Program
Parses the tokens into a complete program AST.
Returns: A Program
node containing all parsed statements
Example:
import { tokenize, Parser } from '@prism-lang/core';
const source = `
x = 42;
if (x > 40) {
console.log("Large number");
}
`;
const tokens = tokenize(source);
const parser = new Parser(tokens, source);
const ast = parser.parse();
parse() Function
export function parse(source: string): Program
Convenience function that handles tokenization and parsing in one step.
Parameters:
source
: The source code string to parse
Returns: A Program
AST node
Example:
import { parse } from '@prism-lang/core';
const ast = parse('x = 10 ~> 0.9;');
Error Handling
ParseError
class ParseError extends Error {
constructor(message: string, token: Token, sourceCode?: string)
token: Token
sourceCode?: string
}
Thrown when the parser encounters invalid syntax.
Properties:
message
: Detailed error message with locationtoken
: The token where the error occurredsourceCode
: The original source code (if provided)
Error Format:
ParseError at line 2, column 5: Expected ')' after expression
2 | if (x > 10
^
Found: '{' (LEFT_BRACE)
Supported Language Features
Expressions
Literals
- Numbers:
42
,3.14
- Strings:
"hello"
,'world'
- Interpolated strings:
`Hello ${name}`
- Booleans:
true
,false
- Null:
null
- Undefined:
undefined
Operators
- Arithmetic:
+
,-
,*
,/
,%
,**
- Comparison:
>
,<
,>=
,<=
,==
,!=
- Logical:
&&
,||
,!
- Confidence operators:
~>
,~~
,~&&
,~||
- Pipeline:
|>
,~|>
,~?>
- Nullish coalescing:
??
- Confidence coalescing:
~??
Complex Expressions
- Arrays:
[1, 2, 3]
,[...arr, 4]
- Objects:
{x: 10, y: 20}
,{...obj, z: 30}
- Property access:
obj.prop
,obj?.prop
,obj~.prop
- Index access:
arr[0]
- Function calls:
fn(arg1, arg2)
- Lambda expressions:
x => x * 2
,(x, y) => x + y
- Ternary:
condition ? true : false
- Placeholders:
_
(for use in pipelines)
Statements
Variable Assignment
x = 42;
y = "hello" ~> 0.9; // with confidence
Compound Assignment
x += 5; // x = x + 5
y *= 2; // y = y * 2
Control Flow
// Regular if
if (condition) {
// statements
} else {
// statements
}
// Uncertain if
uncertain if (condition ~> 0.8) {
high {
// high confidence branch
}
medium {
// medium confidence branch
}
low {
// low confidence branch
}
}
Loops
// C-style for loop
for i = 0; i < 10; i++ {
// statements
}
// For-in loop
for item in array {
// statements
}
// For-in with index
for item, index in array {
// statements
}
// While loop
while condition {
// statements
}
// Do-while loop
do {
// statements
} while condition;
// Uncertain loops
uncertain for i = 0; i < 10; i++ {
high { /* high confidence */ }
low { /* low confidence */ }
}
uncertain while condition {
high { /* high confidence */ }
low { /* low confidence */ }
}
Loop Control
break; // Exit loop
continue; // Skip to next iteration
Context Management
in context "user_input" {
// statements
}
in context "analysis" {
// statements
} shifting to "report" {
// statements
}
Agent Declarations
agents {
assistant: Agent {
confidence: 0.9,
role: "helpful assistant"
}
}
Destructuring
Array Destructuring
[a, b, c] = array;
[first, ...rest] = array;
[a, , c] = array; // Skip element
// With confidence thresholds
[a, b] ~> 0.8 = array;
[a ~> 0.9, b ~> 0.7] = array;
Object Destructuring
{x, y} = point;
{name: userName, age} = user;
{a, ...rest} = obj;
// With confidence thresholds
{x, y} ~> 0.8 = point;
{x ~> 0.9, y ~> 0.7} = point;
// With default values
{x = 0, y = 0} = point;
Nested Destructuring
[{x, y}, [a, b]] = data;
{user: {name, age}} = response;
Pipeline Operations
// Regular pipeline
value |> transform(_) |> format(_);
// Confidence pipeline (preserves confidence)
value ~|> transform(_) ~|> format(_);
// Threshold gate
value ~?> 0.8; // Pass through only if confidence >= 0.8
AST Node Types
The parser generates various AST node types. Each node extends the base ASTNode
class:
abstract class ASTNode {
abstract type: NodeType;
location?: { line: number; column: number };
setLocation(line: number, column: number): this;
}
Common Properties
type
: The node type identifierlocation
: Optional source location information
Expression Nodes
IdentifierExpression
: Variable referencesNumberLiteral
,StringLiteral
,BooleanLiteral
: Literal valuesInterpolatedString
: Template strings with expressionsArrayLiteral
,ObjectLiteral
: Collection literalsBinaryExpression
: Binary operationsUnaryExpression
: Unary operationsCallExpression
: Function callsConfidenceExpression
: Expression with confidence valueLambdaExpression
: Arrow functions
Statement Nodes
Program
: Root node containing all statementsAssignmentStatement
: Variable assignmentsIfStatement
,UncertainIfStatement
: Conditional executionForLoop
,ForInLoop
,WhileLoop
: Loop constructsContextStatement
: Context managementBlockStatement
: Statement blocksExpressionStatement
: Expression as statement
Best Practices
-
Error Recovery: The parser includes synchronization points to recover from errors and continue parsing
-
Source Code Tracking: Always provide source code to the parser for better error messages
-
Location Information: AST nodes include location information for debugging and error reporting
-
Validation: The parser performs syntactic validation but not semantic validation (that's done by the runtime)
Example: Custom AST Traversal
import { parse, ASTNode, IdentifierExpression } from '@prism-lang/core';
function findIdentifiers(node: ASTNode): string[] {
const identifiers: string[] = [];
function traverse(n: ASTNode) {
if (n instanceof IdentifierExpression) {
identifiers.push(n.name);
}
// Traverse child nodes based on type
// (implementation depends on node type)
}
traverse(node);
return identifiers;
}
const ast = parse('x = y + z;');
const vars = findIdentifiers(ast);
console.log(vars); // ['x', 'y', 'z']