Tighten label name parsing
This includes some custom syntax I'm pretty sure about, such as namespaces and local labels.
This commit is contained in:
+54
-9
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
|
|
||||||
pub fn print_labels(b: &Stat) {
|
pub fn print_labels(b: &Stat) {
|
||||||
let mut parser = Parser::new(&b.code);
|
let mut parser = Parser::new(&b.code);
|
||||||
if !parse_program().parse(&mut parser) {
|
if !program.parse(&mut parser) {
|
||||||
eprintln!("Couldn't parse stat's code: {:?}", b.code);
|
eprintln!("Couldn't parse stat's code: {:?}", b.code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -19,23 +19,68 @@ pub fn print_labels(b: &Stat) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_program() -> impl Rule {
|
fn program() -> impl Rule {
|
||||||
(Opt((parse_line, star!(("\n", parse_line)))), EOF)
|
(Opt((line, star!(("\n", line)))), EOF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_line() -> impl Rule {
|
fn line() -> impl Rule {
|
||||||
Alt((parse_label_line, parse_any_line))
|
Alt((label_line, any_line))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_any_line() -> impl Rule {
|
fn any_line() -> impl Rule {
|
||||||
(star!(Not("\n"), Dot), eol)
|
(star!(Not("\n"), Dot), eol)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_label_line() -> impl Rule {
|
fn label_line() -> impl Rule {
|
||||||
let allowed = Alt(('A'..='Z', 'a'..='z', '0'..='9', "_", "@", "~"));
|
(":", Tag("label", label_name), eol)
|
||||||
(":", Tag("label", plus!(allowed)), eol)
|
}
|
||||||
|
|
||||||
|
fn label_name() -> impl Rule {
|
||||||
|
let namespace = (plus!(word_char), "~");
|
||||||
|
(
|
||||||
|
Opt(namespace),
|
||||||
|
star!(word_char),
|
||||||
|
Opt((".", plus!(word_char))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn word_char() -> impl Rule {
|
||||||
|
Alt(('A'..='Z', 'a'..='z', '0'..='9', "_"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eol() -> impl Rule {
|
fn eol() -> impl Rule {
|
||||||
Alt((And("\n"), EOF))
|
Alt((And("\n"), EOF))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::preprocess::peg::Ref;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn parse<T: Rule>(rule: &T, input: &str) {
|
||||||
|
let mut p = Parser::new(input);
|
||||||
|
let rule = (Ref(rule), EOF);
|
||||||
|
assert!(rule.parse(&mut p));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_err<T: Rule>(rule: &T, input: &str) {
|
||||||
|
let mut p = Parser::new(input);
|
||||||
|
let rule = (Ref(rule), EOF);
|
||||||
|
assert!(!rule.parse(&mut p));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_label_name() {
|
||||||
|
parse(&label_name, "foo");
|
||||||
|
parse(&label_name, ".loop");
|
||||||
|
parse(&label_name, "foo.loop");
|
||||||
|
parse(&label_name, "ns~foo");
|
||||||
|
parse(&label_name, "ns~.loop");
|
||||||
|
|
||||||
|
parse_err(&label_name, "foo.");
|
||||||
|
parse_err(&label_name, "foo.bar.baz");
|
||||||
|
parse_err(&label_name, "foo~bar~baz");
|
||||||
|
parse_err(&label_name, "~foo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ macro_rules! impl_rule_for_tuple {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Alt<T>(pub T);
|
pub struct Alt<T>(pub T);
|
||||||
|
|
||||||
macro_rules! impl_rule_for_alt {
|
macro_rules! impl_rule_for_alt {
|
||||||
|
|||||||
Reference in New Issue
Block a user