basic_dsl/lib.rs
1// SPDX-License-Identifier: EUPL-1.2
2// Copyright (c) 2025 The BASIC DSL Contributors
3
4/*!
5# BASIC DSL
6
7A procedural macro crate that provides a BASIC interpreter DSL embedded in Rust.
8
9## Usage
10
11```rust
12use basic_dsl::basic;
13
14basic! {
15 10 FOR I = 1 TO 5
16 20 PRINT I
17 30 NEXT I
18 40 PRINT "DONE"
19 50 END
20}
21```
22
23The macro supports classic BASIC programming constructs:
24
25### Control Flow
26- **FOR...NEXT loops**: `FOR variable = start TO end [STEP increment]` and `NEXT [variable]`
27- **Conditional jumps**: `IF condition THEN GOTO line`
28- **Unconditional jumps**: `GOTO line`
29- **Program termination**: `END`
30
31### Variables and Expressions
32- **Variable assignment**: `LET variable = expression`
33- **Arithmetic**: `+`, `-`, `*`, `/`
34- **Comparisons**: `<`, `<=`, `=`, `>=`, `>`
35- **Numbers and string literals**: `42`, `"Hello World"`
36
37### Input/Output
38- **Printing**: `PRINT expression` (numbers and strings)
39
40### Advanced Features
41- **Nested loops**: Full support for nested FOR...NEXT constructs
42- **Expression evaluation**: Complex arithmetic and string handling
43- **Runtime error checking**: Proper error handling for invalid operations
44*/
45
46mod ast;
47mod codegen;
48mod token_parser;
49
50use proc_macro::TokenStream;
51use syn::Result;
52
53use crate::codegen::generate_runtime_code;
54use crate::token_parser::parse_basic_program_tokens;
55
56/// Main entry point for the BASIC DSL macro.
57///
58/// Accepts BASIC program code as direct tokens.
59#[proc_macro]
60pub fn basic(input: TokenStream) -> TokenStream {
61 match expand_from_tokens(input) {
62 Ok(ts) => ts.into(),
63 Err(e) => e.to_compile_error().into(),
64 }
65}
66
67fn expand_from_tokens(input: TokenStream) -> Result<proc_macro2::TokenStream> {
68 let tokens = proc_macro2::TokenStream::from(input);
69 let stmts = parse_basic_program_tokens(tokens)?;
70 generate_runtime_code(stmts, &syn::LitStr::new("", proc_macro2::Span::call_site()))
71}