pub struct Sketch { /* private fields */ }Expand description
A sketch made of several files: the entry and the parts its
[sketch] modules lists (LSF2 §3.2).
Add the entry first, then its parts, each under its project-relative path
(/-separated, no .. that leaves the root, portable to every OS). The
files go into a SourceMap in the order they are added, so every
diagnostic forging reports — and every span in the forged language’s
warnings — points into the right file: render them with
source_map. A one-file sketch forged from a
Sketch gets the same spans as from Language::from_lsf, since the
first file starts at position 0.
The parts merge as if the files were one document: a table may be
continued in another file ([rules] in two files adds rules to one
table), and a key or table defined twice, in one file or two, is an error
naming both places. When rules come from more than one file,
[language] start is required.
§Examples
use lang_forge::{Language, Sketch};
let mut sketch = Sketch::new();
sketch.add("calc.lsf", r#"
[sketch]
format = 2
modules = ["rules/expr.lsf"]
[language]
name = "calc"
version = "1.0.0"
start = "program"
[rules]
program = "stmts:stmt*"
stmt = "value:expr ';'"
"#)?;
sketch.add("rules/expr.lsf", r#"
[sketch]
format = 2
kind = "part"
[rules.expr]
operand = "NUMBER"
levels = [{ left = ["+"] }]
"#)?;
let calc = Language::from_sketch(&sketch)?;
assert!(!calc.parse("1 + 2; 3;").has_errors());A problem in a part is reported in that part:
use lang_forge::{Language, Sketch};
let mut sketch = Sketch::new();
sketch.add("a.lsf", "[sketch]\nformat = 2\nmodules = [\"b.lsf\"]\n[language]\nname = \"a\"\nversion = \"1.0.0\"\nstart = \"x\"\n[rules]\nx = \"y\"\n")?;
sketch.add("b.lsf", "[sketch]\nformat = 2\nkind = \"part\"\n[rules]\ny = \"undefined_rule\"\n")?;
let err = Language::from_sketch(&sketch).unwrap_err();
assert_eq!(err.to_string(), "b.lsf:5:6: undefined rule `undefined_rule`");Implementations§
Source§impl Sketch
impl Sketch
Sourcepub fn new() -> Self
pub fn new() -> Self
An empty sketch.
§Examples
use lang_forge::Sketch;
let mut sketch = Sketch::new();
assert!(sketch.is_empty());
sketch.add("main.lsf", "[language]\nname = \"m\"\n[rules]\nm = \"IDENT\"\n")?;
assert_eq!(sketch.len(), 1);
assert_eq!(sketch.source_map().iter().next().map(|(_, f)| f.name()), Some("main.lsf"));Sourcepub fn add(
&mut self,
path: &str,
text: impl Into<Box<str>>,
) -> Result<(), Error>
pub fn add( &mut self, path: &str, text: impl Into<Box<str>>, ) -> Result<(), Error>
Adds a file under its project-relative path. The first file added
is the entry.
§Errors
Returns an Error if the path is not a portable project-relative
path (LSF8001, LSF8002), is already in the sketch, or differs
from one only by ASCII case (LSF2005, LSF8003), or if the file is
larger than 8 MiB (LSF9001), the sketch would pass 64 MiB in total
(LSF9002), or it would have more than 1024 files (LSF9003). The
sketch is unchanged.
§Examples
use lang_forge::Sketch;
let mut sketch = Sketch::new();
assert!(sketch.add("lang/main.lsf", "").is_ok());
assert!(sketch.add("../outside.lsf", "").is_err());
assert!(sketch.add("C:/abs.lsf", "").is_err());
assert!(sketch.add("lang/main.lsf", "").is_err());
assert_eq!(sketch.len(), 1);Sourcepub fn source_map(&self) -> &SourceMap
pub fn source_map(&self) -> &SourceMap
The sketch’s files, for rendering diagnostics with
Renderer.