Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ Lexer (logos) + parser (rowan) are resilient: collect errors, don't fail-fast.
crates/
plotnik-lib/ # Core library
src/
ast/ # Syntax infrastructure
parser/ # Syntax infrastructure
lexer.rs # Token definitions (logos)
syntax_kind.rs # SyntaxKind enum
nodes.rs # Typed AST wrappers over CST
parser/
core.rs # Parser infrastructure
grammar.rs # Grammar rules
error.rs # Parse errors
tests/ # Parser tests (snapshots)
cst.rs # SyntaxKind enum
ast.rs # Typed AST wrappers over CST
core.rs # Parser infrastructure
grammar.rs # Grammar rules
error.rs # Parse errors
invariants.rs # Parser invariant checks
mod.rs # Re-exports, Parse struct, parse()
tests/ # Parser tests (snapshots)
query/ # Query processing
mod.rs # Query struct, new(), pipeline
dump.rs # dump_* debug output methods
Expand All @@ -38,7 +39,7 @@ docs/
## Pipeline

```rust
ast::parse() // Parse → CST
parser::parse() // Parse → CST
alt_kind::validate() // Validate alternation kinds
named_defs::resolve() // Resolve names → SymbolTable
ref_cycles::validate() // Validate recursion termination
Expand Down Expand Up @@ -97,7 +98,7 @@ Stages: `Parse` → `Validate` → `Resolve` → `Escape`. Use `Query::errors_fo
- New scopes only from captured `{...}@s` or `[...]@c`
- `?`/`*`/`+` = optional/list/non-empty list

## AST Layer (`ast/nodes.rs`)
## AST Layer (`parser/ast.rs`)

Types: `Root`, `Def`, `Tree`, `Ref`, `Str`, `Alt`, `Branch`, `Seq`, `Capture`, `Type`, `Quantifier`, `Field`, `NegatedField`, `Wildcard`, `Anchor`, `Expr`

Expand Down
2 changes: 1 addition & 1 deletion crates/plotnik-cli/src/commands/debug/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::fs;
use std::io::{self, Read};

use plotnik_lib::Query;
use plotnik_lib::ast::RenderOptions;
use plotnik_lib::RenderOptions;

use source::{dump_source, load_source, parse_tree, resolve_lang};

Expand Down
27 changes: 0 additions & 27 deletions crates/plotnik-lib/src/ast/mod.rs

This file was deleted.

4 changes: 2 additions & 2 deletions crates/plotnik-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

#![cfg_attr(coverage_nightly, feature(coverage_attribute))]

pub mod ast;
pub mod parser;
pub mod query;

pub use ast::{Diagnostic, RenderOptions, Severity};
pub use parser::{Diagnostic, RenderOptions, Severity};
pub use query::{Query, QueryBuilder};

/// Errors that can occur during query parsing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Each struct wraps a `SyntaxNode` and provides typed accessors.
//! Cast is infallible for correct `SyntaxKind` - validation happens elsewhere.

use super::syntax_kind::{SyntaxKind, SyntaxNode, SyntaxToken};
use super::cst::{SyntaxKind, SyntaxNode, SyntaxToken};

macro_rules! ast_node {
($name:ident, $kind:ident) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@

use rowan::{Checkpoint, GreenNode, GreenNodeBuilder, TextRange, TextSize};

use super::cst::token_sets::ROOT_EXPR_FIRST;
use super::cst::{SyntaxKind, TokenSet};
use super::error::{Diagnostic, Fix, RelatedInfo};
use super::lexer::{Token, token_text};

use crate::Error;
use crate::ast::lexer::{Token, token_text};
use crate::ast::syntax_kind::token_sets::ROOT_EXPR_FIRST;
use crate::ast::syntax_kind::{SyntaxKind, TokenSet};

const DEFAULT_EXEC_FUEL: u32 = 1_000_000;
const DEFAULT_RECURSION_FUEL: u32 = 4096;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::ast::syntax_kind::{QLang, SyntaxKind::*, TokenSet};
use crate::parser::cst::{QLang, SyntaxKind::*, TokenSet};
use rowan::Language;

#[test]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::*;
use super::error::*;
use rowan::TextRange;

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ use super::core::Parser;
use super::error::{Fix, RelatedInfo};
use super::invariants::assert_nonempty;

use crate::ast::lexer::token_text;
use crate::ast::syntax_kind::token_sets::{
use super::cst::token_sets::{
ALT_RECOVERY, EXPR_FIRST, QUANTIFIERS, SEPARATORS, SEQ_RECOVERY, TREE_RECOVERY,
};
use crate::ast::syntax_kind::{SyntaxKind, TokenSet};
use super::cst::{SyntaxKind, TokenSet};
use super::lexer::token_text;

impl Parser<'_> {
pub fn parse_root(&mut self) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#![cfg_attr(coverage_nightly, coverage(off))]

use super::core::Parser;
use crate::ast::syntax_kind::SyntaxKind;
use super::cst::SyntaxKind;

impl Parser<'_> {
#[inline]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use logos::Logos;
use rowan::TextRange;
use std::ops::Range;

use super::syntax_kind::SyntaxKind;
use super::cst::SyntaxKind;

/// Zero-copy token: kind + span, text retrieved via [`token_text`] when needed.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Resilient LL parser for the query language.
//! Parser infrastructure for the query language.
//!
//! # Architecture
//!
Expand All @@ -20,43 +20,47 @@
//! 4. On recursion limit, remaining input goes into single Error node
//!
//! However, fuel exhaustion (exec_fuel, recursion_fuel) returns an error immediately.
//!
//! # Grammar (EBNF-ish)
//!
//! ```text
//! root = expr*
//! expr = tree | alternation | wildcard | anon_node
//! | anchor | negated_field | field | ident
//! tree = "(" [node_type] expr* ")"
//! alternation= "[" expr* "]"
//! wildcard = "_"
//! anon_node = STRING
//! capture = "@" LOWER_IDENT
//! anchor = "."
//! negated_field = "!" IDENT
//! field = IDENT ":" expr
//! quantifier = expr ("*" | "+" | "?" | "*?" | "+?" | "??")
//! capture = expr "@" IDENT ["::" TYPE]
//! ```

pub mod ast;
pub mod cst;
pub mod lexer;

mod core;
mod error;
mod grammar;
mod invariants;

#[cfg(test)]
mod ast_tests;
#[cfg(test)]
mod cst_tests;
#[cfg(test)]
mod error_tests;
#[cfg(test)]
mod lexer_tests;
#[cfg(test)]
mod tests;

// Re-exports from cst (was syntax_kind)
pub use cst::{SyntaxKind, SyntaxNode, SyntaxToken};

// Re-exports from ast (was nodes)
pub use ast::{
Alt, AltKind, Anchor, Branch, Capture, Def, Expr, Field, NegatedField, Quantifier, Ref, Root,
Seq, Str, Tree, Type, Wildcard,
};

// Re-exports from error
pub use error::{
Diagnostic, ErrorStage, Fix, RelatedInfo, RenderOptions, Severity, SyntaxError,
render_diagnostics, render_errors,
};

// Internal use
pub(crate) use core::Parser;

use super::lexer::lex;
use super::syntax_kind::SyntaxNode;
use crate::Result;

#[cfg(test)]
mod error_tests;
use lexer::lex;

/// Parse result containing the green tree and any errors.
///
Expand All @@ -79,7 +83,7 @@ impl Parse {
SyntaxNode::new_root(self.inner.green.clone())
}

pub fn errors(&self) -> &[SyntaxError] {
pub fn errors(&self) -> &[Diagnostic] {
&self.inner.errors
}

Expand All @@ -106,6 +110,3 @@ pub(crate) fn parse_with_parser(mut parser: Parser) -> Result<Parse> {
inner: parser.finish()?,
})
}

#[cfg(test)]
mod tests;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::ast::parser::parse;
use crate::parser::parse;

#[test]
fn error_json_serialization() {
Expand Down
4 changes: 2 additions & 2 deletions crates/plotnik-lib/src/query/alt_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use rowan::TextRange;
use super::invariants::{
assert_alt_no_bare_exprs, assert_root_no_bare_exprs, ensure_both_branch_kinds,
};
use crate::ast::{Alt, AltKind, Branch, Expr, Root};
use crate::ast::{Diagnostic, ErrorStage, RelatedInfo};
use crate::parser::{Alt, AltKind, Branch, Expr, Root};
use crate::parser::{Diagnostic, ErrorStage, RelatedInfo};

pub fn validate(root: &Root) -> Vec<Diagnostic> {
let mut errors = Vec::new();
Expand Down
2 changes: 1 addition & 1 deletion crates/plotnik-lib/src/query/dump.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[cfg(test)]
mod test_helpers {
use crate::Query;
use crate::ast::{RenderOptions, render_diagnostics};
use crate::parser::{RenderOptions, render_diagnostics};

impl Query<'_> {
pub fn dump_cst(&self) -> String {
Expand Down
2 changes: 1 addition & 1 deletion crates/plotnik-lib/src/query/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::ast::{Diagnostic, ErrorStage, RenderOptions, Severity, render_diagnostics};
use crate::parser::{Diagnostic, ErrorStage, RenderOptions, Severity, render_diagnostics};

use super::Query;

Expand Down
2 changes: 1 addition & 1 deletion crates/plotnik-lib/src/query/errors_tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::Query;
use crate::ast::{ErrorStage, RenderOptions, Severity};
use crate::parser::{ErrorStage, RenderOptions, Severity};

#[test]
fn diagnostics_alias() {
Expand Down
2 changes: 1 addition & 1 deletion crates/plotnik-lib/src/query/invariants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#![cfg_attr(coverage_nightly, coverage(off))]

use crate::ast::{Alt, Branch, Ref, Root, SyntaxNode, SyntaxToken};
use crate::parser::{Alt, Branch, Ref, Root, SyntaxNode, SyntaxToken};

#[inline]
pub fn assert_root_no_bare_exprs(root: &Root) {
Expand Down
6 changes: 3 additions & 3 deletions crates/plotnik-lib/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ mod shape_cardinalities_tests;
use std::collections::HashMap;

use crate::Result;
use crate::ast::lexer::lex;
use crate::ast::parser::{self, Parser};
use crate::ast::{Diagnostic, Parse, Root, SyntaxNode};
use crate::parser::lexer::lex;
use crate::parser::{self, Parser};
use crate::parser::{Diagnostic, Parse, Root, SyntaxNode};
use named_defs::SymbolTable;
use shape_cardinalities::ShapeCardinality;

Expand Down
4 changes: 2 additions & 2 deletions crates/plotnik-lib/src/query/named_defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use indexmap::{IndexMap, IndexSet};
use rowan::TextRange;

use crate::ast::{Diagnostic, ErrorStage};
use crate::ast::{Expr, Ref, Root};
use crate::parser::{Diagnostic, ErrorStage};
use crate::parser::{Expr, Ref, Root};

#[derive(Debug, Clone)]
pub struct SymbolTable {
Expand Down
2 changes: 1 addition & 1 deletion crates/plotnik-lib/src/query/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt::Write;

use rowan::NodeOrToken;

use crate::ast::{self, SyntaxNode};
use crate::parser::{self as ast, SyntaxNode};

use super::Query;
use super::shape_cardinalities::ShapeCardinality;
Expand Down
4 changes: 2 additions & 2 deletions crates/plotnik-lib/src/query/ref_cycles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use indexmap::{IndexMap, IndexSet};
use rowan::TextRange;

use super::named_defs::SymbolTable;
use crate::ast::{Def, Expr, Root, SyntaxKind};
use crate::ast::{Diagnostic, ErrorStage, RelatedInfo};
use crate::parser::{Def, Expr, Root, SyntaxKind};
use crate::parser::{Diagnostic, ErrorStage, RelatedInfo};

pub fn validate(root: &Root, symbols: &SymbolTable) -> Vec<Diagnostic> {
let sccs = find_sccs(symbols);
Expand Down
4 changes: 2 additions & 2 deletions crates/plotnik-lib/src/query/shape_cardinalities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use super::invariants::{
assert_ref_in_symbols, ensure_ref_body, ensure_ref_name, panic_unexpected_node,
};
use super::named_defs::SymbolTable;
use crate::ast::{Branch, Def, Expr, Field, Ref, Root, Seq, SyntaxNode, Type};
use crate::ast::{Diagnostic, ErrorStage};
use crate::parser::{Branch, Def, Expr, Field, Ref, Root, Seq, SyntaxNode, Type};
use crate::parser::{Diagnostic, ErrorStage};
use std::collections::HashMap;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down