1use std::{
63 collections::{HashMap, HashSet, VecDeque},
64 fmt::Display,
65 hash::Hash,
66};
67
68use super::dependency_parser::parse as parse_dependency;
69use super::expr_parser::parse as parse_expr;
70use super::structs::*;
71use crate::lex::{
72 structs::{Keyword, Lexicon, Token},
73 LexerBase,
74};
75use crate::parse_string;
76
77#[derive(Clone, Debug, Eq, PartialEq)]
78pub struct Error {
79 token: Token,
80 msg: String,
81}
82
83impl Display for Error {
84 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
85 write!(
86 f,
87 "{} at {}:{}, found: {}",
88 self.msg,
89 self.token.line(),
90 self.token.column(),
91 self.token,
92 )
93 }
94}
95
96impl Error {
97 pub(super) fn new(token: Token, msg: &str) -> Self {
98 Self {
99 token,
100 msg: msg.to_string(),
101 }
102 }
103}
104
105#[derive(Clone, Debug, Eq, PartialEq, Default)]
110pub struct Ast {
111 main_menu: Option<String>,
112 elements: Vec<(String, Element)>,
113 comment: String,
114 conditions: Vec<Condition>,
115}
116
117#[derive(Clone, Debug, Eq, PartialEq)]
120pub struct ConfigElement {
121 config: Config,
122}
123
124#[derive(Clone, Debug, Eq, PartialEq)]
127pub struct MenuConfigElement {
128 config: Config,
129}
130
131#[derive(Clone, Debug, Eq, PartialEq)]
133pub struct Menu {
134 config: Config,
135 visible_if: HashSet<Dependency>,
136 elements: Vec<(String, Element)>,
137 comment: String,
138 conditions: Vec<Condition>,
139}
140
141#[derive(Clone, Debug, Eq, PartialEq)]
145pub struct Condition {
146 dependency: Dependency,
147 elements: Vec<(String, Element)>,
148 conditions: Vec<Condition>,
149}
150
151impl Condition {
152 pub fn new(dependency: &Dependency) -> Self {
153 Self {
154 dependency: dependency.clone(),
155 elements: Vec::new(),
156 conditions: Vec::new(),
157 }
158 }
159
160 pub fn dependency(&self) -> Dependency {
161 self.dependency.clone()
162 }
163
164 pub fn elements(&self) -> Vec<(String, Element)> {
165 self.elements.clone()
166 }
167}
168
169pub trait WithComment {
170 fn comment(&self) -> String;
171}
172
173impl WithComment for Ast {
174 fn comment(&self) -> String {
175 self.comment.clone()
176 }
177}
178
179impl WithComment for Menu {
180 fn comment(&self) -> String {
181 self.comment.clone()
182 }
183}
184
185trait Commentable {
186 fn set_comment(&mut self, s: &str);
187}
188
189impl Commentable for Ast {
190 fn set_comment(&mut self, s: &str) {
191 self.comment = s.to_string()
192 }
193}
194
195impl Commentable for Menu {
196 fn set_comment(&mut self, s: &str) {
197 self.comment = s.to_string()
198 }
199}
200
201pub trait ConditionContainer {
202 fn len_conditional_blocks(&self) -> usize;
203 fn conditional_blocks(&self) -> Vec<Condition>;
204}
205
206impl ConditionContainer for Ast {
207 fn len_conditional_blocks(&self) -> usize {
208 self.conditions.len()
209 }
210 fn conditional_blocks(&self) -> Vec<Condition> {
211 self.conditions.clone()
212 }
213}
214
215impl ConditionContainer for Menu {
216 fn len_conditional_blocks(&self) -> usize {
217 self.conditions.len()
218 }
219
220 fn conditional_blocks(&self) -> Vec<Condition> {
221 self.conditions.clone()
222 }
223}
224
225impl ConditionContainer for Condition {
226 fn len_conditional_blocks(&self) -> usize {
227 self.conditions.len()
228 }
229
230 fn conditional_blocks(&self) -> Vec<Condition> {
231 self.conditions.clone()
232 }
233}
234
235pub trait Container {
236 fn element_names(&self) -> Box<dyn Iterator<Item = String>>;
237}
238
239trait MutableContainer: Container {
240 fn insert_child(&mut self, name: &str, e: Element);
241 fn insert_condition(&mut self, e: Condition);
242 fn len(&self) -> usize;
243}
244
245impl Container for Ast {
246 fn element_names(&self) -> Box<dyn Iterator<Item = String>> {
247 Box::new(
248 self.elements
249 .clone()
250 .into_iter()
251 .map(|(name, _)| name.clone()),
252 )
253 }
254}
255
256impl Container for Menu {
257 fn element_names(&self) -> Box<dyn Iterator<Item = String>> {
258 Box::new(
259 self.elements
260 .clone()
261 .into_iter()
262 .map(|(name, _)| name.clone()),
263 )
264 }
265}
266
267impl Container for Condition {
268 fn element_names(&self) -> Box<dyn Iterator<Item = String>> {
269 Box::new(
270 self.elements
271 .clone()
272 .into_iter()
273 .map(|(name, _)| name.clone()),
274 )
275 }
276}
277
278impl MutableContainer for Ast {
279 fn insert_child(&mut self, name: &str, e: Element) {
280 self.elements.push((name.to_string(), e));
281 }
282
283 fn insert_condition(&mut self, e: Condition) {
284 self.conditions.push(e);
285 }
286
287 fn len(&self) -> usize {
288 self.elements.len()
289 }
290}
291
292impl MutableContainer for Menu {
293 fn insert_child(&mut self, name: &str, e: Element) {
294 self.elements.push((name.to_string(), e));
295 }
296
297 fn insert_condition(&mut self, e: Condition) {
298 self.conditions.push(e);
299 }
300
301 fn len(&self) -> usize {
302 self.elements.len()
303 }
304}
305
306impl MutableContainer for Condition {
307 fn insert_child(&mut self, name: &str, e: Element) {
308 self.elements.push((name.to_string(), e));
309 }
310
311 fn insert_condition(&mut self, e: Condition) {
312 self.conditions.push(e);
313 }
314
315 fn len(&self) -> usize {
316 self.elements.len()
317 }
318}
319
320trait BaseConfigElement {
321 fn create(name: &str) -> Self;
322 fn config(&mut self) -> &mut Config;
323 fn insert_into_hierarchy<I>(&mut self, hierarchy: &mut I)
324 where
325 I: MutableContainer;
326}
327
328impl BaseConfigElement for ConfigElement {
329 fn create(name: &str) -> Self {
330 let config = Config::create(name);
331 Self { config }
332 }
333
334 fn config(&mut self) -> &mut Config {
335 &mut self.config
336 }
337
338 fn insert_into_hierarchy<I>(&mut self, hierarchy: &mut I)
339 where
340 I: MutableContainer,
341 {
342 hierarchy.insert_child(&self.config().name.clone(), Element::Config(self.clone()));
343 }
344}
345
346impl BaseConfigElement for MenuConfigElement {
347 fn create(name: &str) -> Self {
348 let config = Config::create(name);
349 Self { config }
350 }
351
352 fn config(&mut self) -> &mut Config {
353 &mut self.config
354 }
355
356 fn insert_into_hierarchy<I>(&mut self, hierarchy: &mut I)
357 where
358 I: MutableContainer,
359 {
360 hierarchy.insert_child(
361 &self.config().name.clone(),
362 Element::MenuConfig(self.clone()),
363 );
364 }
365}
366
367impl BaseConfigElement for Menu {
368 fn create(name: &str) -> Self {
369 let config = Config::create(name);
370 Self {
371 config,
372 visible_if: HashSet::new(),
373 elements: Vec::new(),
374 comment: String::new(),
375 conditions: Vec::new(),
376 }
377 }
378
379 fn config(&mut self) -> &mut Config {
380 &mut self.config
381 }
382
383 fn insert_into_hierarchy<I>(&mut self, hierarchy: &mut I)
384 where
385 I: MutableContainer,
386 {
387 hierarchy.insert_child(&self.config().name.clone(), Element::Menu(self.clone()));
388 }
389}
390
391impl Hash for ConfigElement {
392 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
393 self.config.name.hash(state);
394 }
395}
396
397impl Hash for MenuConfigElement {
398 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
399 self.config.name.hash(state);
400 }
401}
402
403impl Hash for Menu {
404 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
405 self.config.name.hash(state);
406 }
407}
408
409impl Hash for Condition {
410 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
411 self.dependency.hash(state);
412 }
413}
414
415#[derive(Hash, Clone, Debug, Eq, PartialEq)]
416pub enum ElementType {
417 Config,
418 MenuConfig,
419 Menu,
420}
421
422#[derive(Hash, Clone, Debug, Eq, PartialEq)]
425pub enum Element {
426 Config(ConfigElement),
427 MenuConfig(MenuConfigElement),
428 Menu(Menu),
429}
430
431impl Element {
432 pub fn len_conditional_blocks(&self) -> usize {
433 match self {
434 Element::Menu(elt) => elt.len_conditional_blocks(),
435 _ => 0,
436 }
437 }
438
439 pub fn conditional_blocks(&self) -> Vec<Condition> {
440 match self {
441 Element::Menu(elt) => elt.conditional_blocks(),
442 _ => Vec::new(),
443 }
444 }
445
446 pub fn dependencies(&self) -> HashSet<Dependency> {
447 match self {
448 Element::Config(elt) => elt.config.dependencies.clone(),
449 Element::MenuConfig(elt) => elt.config.dependencies.clone(),
450 Element::Menu(elt) => elt.config.dependencies.clone(),
451 }
452 }
453
454 pub fn name(&self) -> String {
455 match self {
456 Element::Config(elt) => elt.config.name.clone(),
457 Element::MenuConfig(elt) => elt.config.name.clone(),
458 Element::Menu(elt) => elt.config.name.clone(),
459 }
460 }
461
462 pub fn prompt(&self) -> Option<String> {
463 match self {
464 Element::Config(elt) => elt.config.prompt.as_ref().map(|s| s.to_string()),
465 Element::MenuConfig(elt) => elt.config.prompt.as_ref().map(|s| s.to_string()),
466 _ => None,
467 }
468 }
469
470 pub fn elt_type(&self) -> ElementType {
471 match self {
472 Element::Config(_) => ElementType::Config,
473 Element::MenuConfig(_) => ElementType::MenuConfig,
474 Element::Menu(_) => ElementType::Menu,
475 }
476 }
477
478 pub fn types(&self) -> Option<&HashMap<ConfigType, Option<Dependency>>> {
479 match self {
480 Element::Config(elt) => Some(&elt.config.types),
481 Element::MenuConfig(elt) => Some(&elt.config.types),
482 _ => None,
483 }
484 }
485
486 pub fn defaults(&self) -> Option<&HashMap<Expr, Option<Dependency>>> {
487 match self {
488 Element::Config(elt) => Some(&elt.config.defaults),
489 Element::MenuConfig(elt) => Some(&elt.config.defaults),
490 _ => None,
491 }
492 }
493
494 pub fn reverse_dependencies(&self) -> Option<&HashMap<String, Option<Dependency>>> {
495 match self {
496 Element::Config(elt) => Some(&elt.config.reverse_dependencies),
497 Element::MenuConfig(elt) => Some(&elt.config.reverse_dependencies),
498 Element::Menu(elt) => Some(&elt.config.reverse_dependencies),
499 }
500 }
501
502 pub fn weak_dependencies(&self) -> Option<&HashMap<String, Option<Dependency>>> {
503 match self {
504 Element::Config(elt) => Some(&elt.config.weak_dependencies),
505 Element::MenuConfig(elt) => Some(&elt.config.weak_dependencies),
506 Element::Menu(elt) => Some(&elt.config.weak_dependencies),
507 }
508 }
509
510 pub fn range(&self) -> Option<Range> {
511 match self {
512 Element::Config(elt) => elt.config.range.clone(),
513 Element::MenuConfig(elt) => elt.config.range.clone(),
514 _ => None,
515 }
516 }
517
518 pub fn help(&self) -> VecDeque<String> {
519 match self {
520 Element::Config(elt) => elt.config.help.clone(),
521 Element::MenuConfig(elt) => elt.config.help.clone(),
522 Element::Menu(elt) => elt.config.help.clone(),
523 }
524 }
525
526 pub fn visible_if(&self) -> HashSet<Dependency> {
527 match self {
528 Element::Menu(elt) => elt.visible_if.clone(),
529 _ => HashSet::new(),
530 }
531 }
532
533 pub fn sub_element(&self, s: &str) -> Option<&Element> {
534 match self {
535 Element::Menu(elt) => {
538 for (subname, subelt) in &elt.elements {
539 if subname == s {
540 return Some(subelt);
541 };
542 }
543 None
544 }
545 _ => None,
546 }
547 }
548
549 pub fn sub_elements(&self) -> Vec<(String, Element)> {
550 match self {
551 Element::Menu(elt) => elt.elements.clone(),
554 _ => Vec::new(),
555 }
556 }
557
558 pub fn len(&self) -> usize {
559 match self {
560 Element::Menu(elt) => elt.len(),
563 _ => 0,
564 }
565 }
566}
567
568fn has_error(t: &Token) -> Result<(), Error> {
572 if let Lexicon::Error(e) = t.term() {
573 let msg = format!("Erroneous element: {}", e);
574 Err(Error::new(t.clone(), &msg))
575 } else {
576 Ok(())
577 }
578}
579
580fn result_unexpected(t: &Token, type_name: &str) -> Error {
583 let msg = format!("Expected {}", type_name);
584 Error::new(t.clone(), &msg)
585}
586
587fn should_be_string(t: &Token) -> Result<String, Error> {
590 has_error(t)?;
591 match t.term() {
592 Lexicon::String(s) => Ok(s),
593 _ => Err(result_unexpected(t, "Prompt")),
594 }
595}
596
597fn parse_prompt<LB, F>(lexer: &mut LB, mut closure: F) -> Result<Token, Error>
599where
600 LB: LexerBase,
601 F: FnMut(&str),
602{
603 let next_token = lexer.next_token();
604 match next_token.term() {
605 Lexicon::String(s) => match parse_string(&s) {
606 Ok(v) => closure(&v),
607 Err(e) => return Err(Error::new(next_token.clone(), &e)),
608 },
609 _ => return Err(Error::new(next_token.clone(), "Expected string")),
610 };
611 Ok(lexer.next_token())
612}
613
614fn parse_type<LB, Fp, Fd>(
616 lexer: &mut LB,
617 token: Token,
618 mut prompt_closure: Fp,
619 mut dependency_closure: Fd,
620) -> Result<Token, Error>
621where
622 LB: LexerBase,
623 Fp: FnMut(&str),
624 Fd: FnMut(&Dependency),
625{
626 let mut next_token = lexer.next_token();
627 let mut line = token.line();
628 if let Lexicon::String(s) = next_token.term() {
629 match parse_string(&s) {
630 Ok(v) => prompt_closure(&v),
631 Err(e) => return Err(Error::new(next_token.clone(), &e)),
632 }
633 line = next_token.line();
634 next_token = lexer.next_token();
635 };
636 if let Lexicon::Keyword(Keyword::If) = next_token.term() {
637 if line == next_token.line() {
640 let (dependency, result_token) = parse_dependency(lexer)?;
641 next_token = result_token;
642 dependency_closure(&dependency);
643 }
644 };
645 Ok(next_token)
646}
647
648fn parse_default<LB, F>(lexer: &mut LB, token: Token, mut closure: F) -> Result<Token, Error>
651where
652 LB: LexerBase,
653 F: FnMut(&Expr, Option<Dependency>),
654{
655 let line = token.line();
656 let (maybe_expr, mut next_token) = parse_expr(lexer)?;
657 let expr = match maybe_expr {
658 None => return Err(Error::new(token.clone(), "Expected expression")),
659 Some(expr) => expr,
660 };
661 let mut dep_result: Option<Dependency> = None;
662 if let Lexicon::Keyword(k) = next_token.term() {
663 if let Keyword::If = k {
664 if line == token.line() {
665 let (dep, new_token) = parse_dependency(lexer)?;
666
667 dep_result = Some(dep);
668 next_token = new_token;
669 }
670 }
671 }
672 closure(&expr, dep_result);
673 Ok(next_token)
674}
675
676fn parse_def_type<LB, F>(lexer: &mut LB, token: Token, mut closure: F) -> Result<Token, Error>
680where
681 LB: LexerBase,
682 F: FnMut(&Expr, Option<Dependency>),
683{
684 let line = token.line();
685 let (maybe_expr, mut next_token) = parse_expr(lexer)?;
686 let expr = match maybe_expr {
687 None => return Err(Error::new(token.clone(), "Expected expression")),
688 Some(expr) => expr,
689 };
690 let mut dep_result: Option<Dependency> = None;
691 if let Lexicon::Keyword(k) = next_token.term() {
692 if let Keyword::If = k {
693 if line == token.line() {
694 let (dep, new_token) = parse_dependency(lexer)?;
695
696 dep_result = Some(dep);
697 next_token = new_token;
698 }
699 }
700 }
701 closure(&expr, dep_result);
702 Ok(next_token)
703}
704
705fn parse_select<LB, F>(lexer: &mut LB, token: Token, mut closure: F) -> Result<Token, Error>
711where
712 LB: LexerBase,
713 F: FnMut(&str, Option<Dependency>),
714{
715 let line = token.line();
716 let mut next_token = lexer.next_token();
717 let sym = match next_token.term() {
718 Lexicon::Identifier(s) => {
719 next_token = lexer.next_token();
720 s
721 }
722 _ => return Err(Error::new(next_token.clone(), "Expected identifier")),
723 };
724
725 let mut dep_result: Option<Dependency> = None;
726 if let Lexicon::Keyword(k) = next_token.term() {
727 if let Keyword::If = k {
728 if line == token.line() {
729 let (dep, new_token) = parse_dependency(lexer)?;
730
731 dep_result = Some(dep);
732 next_token = new_token;
733 }
734 }
735 }
736 closure(&sym, dep_result);
737 Ok(next_token)
738}
739
740fn parse_range<LB, F>(lexer: &mut LB, token: Token, mut closure: F) -> Result<Token, Error>
744where
745 LB: LexerBase,
746 F: FnMut(i64, i64, Option<Dependency>),
747{
748 let line = token.line();
749 let mut next_token = lexer.next_token();
750 let sym1 = match next_token.term() {
751 Lexicon::Identifier(s) => {
752 next_token = lexer.next_token();
753 s
754 }
755 _ => return Err(Error::new(next_token.clone(), "Expected symbol")),
756 };
757 let i164 = match sym1.parse::<i64>() {
758 Ok(s) => s,
759 Err(_) => return Err(Error::new(next_token.clone(), "Expected integer symbol")),
760 };
761 let sym2 = match next_token.term() {
762 Lexicon::Identifier(s) => {
763 next_token = lexer.next_token();
764 s
765 }
766 _ => return Err(Error::new(next_token.clone(), "Expected symbol")),
767 };
768 let i264 = match sym2.parse::<i64>() {
769 Ok(s) => s,
770 Err(_) => return Err(Error::new(next_token.clone(), "Expected integer symbol")),
771 };
772
773 let mut dep_result: Option<Dependency> = None;
774 if let Lexicon::Keyword(k) = next_token.term() {
775 if let Keyword::If = k {
776 if line == token.line() {
777 let (dep, new_token) = parse_dependency(lexer)?;
778
779 dep_result = Some(dep);
780 next_token = new_token;
781 }
782 }
783 }
784 closure(i164, i264, dep_result);
785 Ok(next_token)
786}
787
788fn token_to_config_type(t: &Token) -> Result<ConfigType, Error> {
791 match t.term() {
792 Lexicon::Keyword(k) => match k {
793 Keyword::Bool => Ok(ConfigType::Bool),
794 Keyword::Tristate => Ok(ConfigType::Tristate),
795 Keyword::String => Ok(ConfigType::String),
796 Keyword::Hex => Ok(ConfigType::Hex),
797 Keyword::Int => Ok(ConfigType::Int),
798 _ => Err(Error::new(
799 t.clone(),
800 "Expected type keyword bool, tristate, string, int or hex",
801 )),
802 },
803 _ => Err(Error::new(t.clone(), "Expected keyword")),
804 }
805}
806
807fn parse_config<I, LB, CE>(hierarchy: &mut I, lexer: &mut LB) -> Result<Token, Error>
810where
811 I: MutableContainer,
812 LB: LexerBase,
813 CE: BaseConfigElement,
814{
815 let name_token = lexer.next_token();
818
819 let mut config_element = match name_token.term() {
821 Lexicon::Identifier(n) => CE::create(&n),
822 _ => return Err(Error::new(name_token.clone(), "Expected identifier")),
823 };
824
825 let mut has_more = true;
826 let mut next_token = lexer.next_token();
827 while has_more {
830 let start_token = next_token.clone();
831 match start_token.term() {
832 Lexicon::Help(s) => {
833 config_element.config().help.push_back(s);
834 next_token = lexer.next_token();
835 }
836 Lexicon::Keyword(k) => match k {
837 Keyword::Depends => {
838 next_token = lexer.next_token();
841 match next_token.term() {
842 Lexicon::Keyword(k) => match k {
843 Keyword::On => {
844 let (d, new_token) = parse_dependency(lexer)?;
845 config_element.config().dependencies.insert(d);
846 next_token = new_token;
847 }
848 _ => {
849 return Err(Error::new(name_token.clone(), "Expected keyword 'on'"))
850 }
851 },
852 _ => return Err(Error::new(name_token.clone(), "Expected keyword 'on'")),
853 }
854 }
855 Keyword::Select => {
856 next_token = parse_select(lexer, next_token, |s, d| {
857 config_element
858 .config()
859 .reverse_dependencies
860 .insert(s.to_string(), d.clone());
861 ()
862 })?;
863 }
864 Keyword::Imply => {
865 next_token = parse_select(lexer, next_token, |s, d| {
866 config_element
867 .config()
868 .weak_dependencies
869 .insert(s.to_string(), d.clone());
870 ()
871 })?;
872 }
873 Keyword::Prompt => {
874 next_token = parse_prompt(lexer, |s| {
875 config_element.config().prompt = Some(s.to_string());
876 })?
877 }
878 Keyword::Bool
879 | Keyword::Tristate
880 | Keyword::String
881 | Keyword::Hex
882 | Keyword::Int => {
883 let mut dependency: Option<Dependency> = None;
884 next_token = parse_type(
885 lexer,
886 next_token,
887 |s| config_element.config().prompt = Some(s.to_string()),
888 |d| dependency = Some(d.clone()),
889 )?;
890 config_element
891 .config()
892 .types
893 .insert(token_to_config_type(&start_token)?, dependency);
894 }
895 Keyword::Default => {
896 next_token = parse_default(lexer, next_token, |e, d| {
897 config_element
898 .config()
899 .defaults
900 .insert(e.clone(), d.map(|x| x.to_owned()));
901 })?
902 }
903 Keyword::DefBool | Keyword::DefTristate => {
904 next_token = parse_def_type(lexer, next_token, |e, d| {
905 match k {
906 Keyword::DefBool => config_element
907 .config()
908 .types
909 .insert(ConfigType::Bool, d.clone()),
910 _ => config_element
911 .config()
912 .types
913 .insert(ConfigType::Tristate, d.clone()),
914 };
915 config_element
916 .config()
917 .defaults
918 .insert(e.clone(), d.map(|x| x.to_owned()));
919 })?
920 }
921 Keyword::Range => {
922 next_token = parse_range(lexer, next_token, |lhs, rhs, dependency| {
923 config_element.config().range = Some(Range {
924 lhs,
925 rhs,
926 dependency,
927 })
928 })?
929 }
930 _ => {
931 has_more = false;
932 }
933 },
934 _ => {
935 has_more = false;
936 }
937 }
938 }
939
940 config_element.insert_into_hierarchy(hierarchy);
941
942 Ok(next_token)
943}
944
945fn parse_comment<C, LB>(commentable: &mut C, lexer: &mut LB) -> Result<Token, Error>
947where
948 C: Commentable,
949 LB: LexerBase,
950{
951 let next_token = lexer.next_token();
952 match next_token.term() {
953 Lexicon::String(s) => {
954 match parse_string(&s) {
955 Ok(v) => commentable.set_comment(&v),
956 Err(e) => return Err(Error::new(next_token.clone(), &e)),
957 };
958 Ok(lexer.next_token())
959 }
960 _ => Err(Error::new(next_token.clone(), "Expected string")),
961 }
962}
963
964fn parse_if<I, LB>(hierarchy: &mut I, lexer: &mut LB) -> Result<Token, Error>
965where
966 I: MutableContainer,
967 LB: LexerBase,
968{
969 let (dependency, mut next_token) = parse_dependency(lexer)?;
972 let mut condition = Condition::new(&dependency);
973 let mut has_more = true;
974 while has_more {
977 let start_token = next_token.clone();
978 match start_token.term() {
979 Lexicon::Keyword(k) => match k {
980 Keyword::Config => {
981 next_token =
982 parse_config::<Condition, LB, ConfigElement>(&mut condition, lexer)?
983 }
984 Keyword::Menuconfig => {
985 next_token =
986 parse_config::<Condition, LB, MenuConfigElement>(&mut condition, lexer)?
987 }
988 Keyword::Menu => {
989 next_token = parse_menu::<Condition, LB>(&mut condition, lexer)?;
995 match next_token.term() {
997 Lexicon::Keyword(k) => match k {
998 Keyword::Endmenu => next_token = lexer.next_token(),
999 _ => {
1000 return Err(Error::new(
1001 next_token.clone(),
1002 "Keyword not expected, expected 'endmenu'",
1003 ))
1004 }
1005 },
1006 _ => return Err(Error::new(next_token.clone(), "Expected keyword")),
1007 }
1008 }
1009 Keyword::If => {
1010 next_token = parse_if::<Condition, LB>(&mut condition, lexer)?;
1016 match next_token.term() {
1018 Lexicon::Keyword(k) => match k {
1019 Keyword::Endif => next_token = lexer.next_token(),
1020 _ => {
1021 return Err(Error::new(
1022 next_token.clone(),
1023 "Keyword not expected, expected 'endif'",
1024 ))
1025 }
1026 },
1027 _ => return Err(Error::new(next_token.clone(), "Expected keyword")),
1028 }
1029 }
1030 _ => {
1031 has_more = false;
1032 }
1033 },
1034 _ => {
1035 has_more = false;
1036 }
1037 }
1038 }
1039
1040 hierarchy.insert_condition(condition);
1041 Ok(next_token)
1042}
1043
1044fn parse_menu<I, LB>(hierarchy: &mut I, lexer: &mut LB) -> Result<Token, Error>
1045where
1046 I: MutableContainer,
1047 LB: LexerBase,
1048{
1049 let name_token = lexer.next_token();
1051 let mut menu = match name_token.term() {
1052 Lexicon::String(s) => match parse_string(&s) {
1053 Ok(v) => Menu::create(&v),
1054 Err(e) => return Err(Error::new(name_token.clone(), &e)),
1055 },
1056 _ => {
1057 return Err(Error::new(
1058 name_token.clone(),
1059 "Expected character string identifying the menu's name",
1060 ))
1061 }
1062 };
1063
1064 let mut has_more = true;
1065 let mut next_token = lexer.next_token();
1066 while has_more {
1069 let start_token = next_token.clone();
1070 match start_token.term() {
1071 Lexicon::Help(s) => {
1072 menu.config().help.push_back(s);
1073 next_token = lexer.next_token();
1074 }
1075 Lexicon::Keyword(k) => match k {
1076 Keyword::Depends => {
1077 next_token = lexer.next_token();
1080 match next_token.term() {
1081 Lexicon::Keyword(k) => match k {
1082 Keyword::On => {
1083 let (d, new_token) = parse_dependency(lexer)?;
1084 menu.config().dependencies.insert(d);
1085 next_token = new_token;
1086 }
1087 _ => {
1088 return Err(Error::new(name_token.clone(), "Expected keyword 'on'"))
1089 }
1090 },
1091 _ => return Err(Error::new(name_token.clone(), "Expected keyword 'on'")),
1092 }
1093 }
1094 Keyword::Visible => {
1095 next_token = lexer.next_token();
1098 match next_token.term() {
1099 Lexicon::Keyword(k) => match k {
1100 Keyword::If => {
1101 let (d, new_token) = parse_dependency(lexer)?;
1102 menu.visible_if.insert(d);
1103 next_token = new_token;
1104 }
1105 _ => {
1106 return Err(Error::new(name_token.clone(), "Expected keyword 'if'"))
1107 }
1108 },
1109 _ => return Err(Error::new(name_token.clone(), "Expected keyword 'if'")),
1110 }
1111 }
1112 Keyword::Comment => next_token = parse_comment::<Menu, LB>(&mut menu, lexer)?,
1113 Keyword::Config => {
1114 next_token = parse_config::<Menu, LB, ConfigElement>(&mut menu, lexer)?
1115 }
1116 Keyword::Menuconfig => {
1117 next_token = parse_config::<Menu, LB, MenuConfigElement>(&mut menu, lexer)?
1118 }
1119 Keyword::Menu => {
1120 next_token = parse_menu::<Menu, LB>(&mut menu, lexer)?;
1126 match next_token.term() {
1128 Lexicon::Keyword(k) => match k {
1129 Keyword::Endmenu => next_token = lexer.next_token(),
1130 _ => {
1131 return Err(Error::new(
1132 next_token.clone(),
1133 "Keyword not expected, expected 'endmenu'",
1134 ))
1135 }
1136 },
1137 _ => return Err(Error::new(next_token.clone(), "Expected keyword")),
1138 }
1139 }
1140 Keyword::If => {
1141 next_token = parse_if::<Menu, LB>(&mut menu, lexer)?;
1147 match next_token.term() {
1149 Lexicon::Keyword(k) => match k {
1150 Keyword::Endif => next_token = lexer.next_token(),
1151 _ => {
1152 return Err(Error::new(
1153 next_token.clone(),
1154 "Keyword not expected, expected 'endif'",
1155 ))
1156 }
1157 },
1158 _ => return Err(Error::new(next_token.clone(), "Expected keyword")),
1159 }
1160 }
1161 _ => {
1162 has_more = false;
1163 }
1164 },
1165 _ => {
1166 has_more = false;
1167 }
1168 }
1169 }
1170
1171 menu.insert_into_hierarchy(hierarchy);
1172 Ok(next_token)
1173}
1174
1175impl Ast {
1176 fn read_main_menu<LB>(&mut self, lexer: &mut LB) -> Result<Token, Error>
1177 where
1178 LB: LexerBase,
1179 {
1180 let t = lexer.next_token();
1181 match t.term() {
1182 Lexicon::Keyword(k) => match k {
1183 Keyword::Mainmenu => {
1184 self.main_menu = match parse_string(&should_be_string(&lexer.next_token())?) {
1185 Ok(v) => Some(v),
1186 Err(e) => return Err(Error::new(t.clone(), &e)),
1187 };
1188 Ok(lexer.next_token())
1189 }
1190 _ => Ok(t),
1191 },
1192 _ => Ok(t),
1193 }
1194 }
1195
1196 pub fn element(&self, name: &str) -> Option<&Element> {
1197 for (elt_name, elt) in &self.elements {
1198 if elt_name == name {
1199 return Some(&elt);
1200 }
1201 }
1202 None
1203 }
1204
1205 pub fn contains_element(&self, name: &str) -> bool {
1206 match self.element(name) {
1207 Some(_) => true,
1208 None => false,
1209 }
1210 }
1211
1212 pub fn len(&self) -> usize {
1213 self.elements.len()
1214 }
1215
1216 fn parse_element<LB>(&mut self, token: Token, lexer: &mut LB) -> Result<Token, Error>
1217 where
1218 LB: LexerBase,
1219 {
1220 match token.term() {
1221 Lexicon::Keyword(k) => match k {
1230 Keyword::Config => parse_config::<Ast, LB, ConfigElement>(self, lexer),
1231 Keyword::Menuconfig => parse_config::<Ast, LB, MenuConfigElement>(self, lexer),
1232 Keyword::Menu => {
1233 let next_token = parse_menu::<Ast, LB>(self, lexer)?;
1239 match next_token.term() {
1241 Lexicon::Keyword(k) => match k {
1242 Keyword::Endmenu => Ok(lexer.next_token()),
1243 _ => Err(Error::new(next_token.clone(), "Keyword not expected, expected 'endmenu'"))
1244 },
1245 _ => Err(Error::new(next_token.clone(), "Expected keyword"))
1246 }
1247 }
1248 Keyword::If => {
1249 let next_token = parse_if::<Ast, LB>(self, lexer)?;
1255 match next_token.term() {
1257 Lexicon::Keyword(k) => match k {
1258 Keyword::Endif => Ok(lexer.next_token()),
1259 _ => Err(Error::new(next_token.clone(), "Keyword not expected, expected 'endif'"))
1260 },
1261 _ => Err(Error::new(next_token.clone(), "Expected keyword"))
1262 }
1263 }
1264 Keyword::Comment => parse_comment(self, lexer),
1265 _ => Err(Error::new(token.clone(), "Keyword not expected, expected 'config', 'menuconfig', 'choice', 'comment', 'menu', 'if', 'source'"))
1266 },
1267 Lexicon::Error(e) => Err(Error::new(token.clone(), &format!("Erroneous element: {}", e))),
1268 _ => Err(Error::new(token.clone(), "Expected keyword"))
1269 }
1270 }
1271
1272 fn read_actual<LB>(&mut self, lexer: &mut LB) -> Result<(), Error>
1273 where
1274 LB: LexerBase,
1275 {
1276 let mut next_token = self.read_main_menu(lexer)?;
1280
1281 while !next_token.eot() {
1282 next_token = self.parse_element(next_token, lexer)?;
1283 }
1284
1285 Ok(())
1286 }
1287
1288 fn new() -> Self {
1290 Self {
1291 main_menu: None,
1292 elements: Vec::new(),
1293 comment: String::new(),
1294 conditions: Vec::new(),
1295 }
1296 }
1297
1298 pub fn parse<LB>(input: &mut LB) -> Result<Self, Error>
1300 where
1301 LB: LexerBase,
1302 {
1303 let mut ast = Ast::new();
1304 ast.read_actual(input)?;
1305 Ok(ast)
1306 }
1307
1308 pub fn main_menu(&self) -> Option<&String> {
1309 return self.main_menu.as_ref();
1310 }
1311}
1312
1313#[cfg(test)]
1314mod tests {
1315 use super::super::super::lex::lexer::Lexer;
1316 use super::*;
1317
1318 fn ast_from(s: &str) -> Result<Ast, Error> {
1319 let mut lexer = Lexer::create(s.as_bytes());
1320 Ok(Ast::parse(&mut lexer)?)
1321 }
1322
1323 fn elements_vec_to_hashmap(v: Vec<(String, Element)>) -> HashMap<String, Element> {
1324 v.iter().map(|tuple| tuple.clone()).collect()
1325 }
1326
1327 #[test]
1328 fn test_mainmenu() -> Result<(), Error> {
1329 let ast = ast_from(&"mainmenu \"Hello World\"")?;
1330 assert_eq!(ast.main_menu(), Some(&"Hello World".to_string()));
1331 Ok(())
1332 }
1333
1334 #[test]
1335 fn test_parse_config() -> Result<(), Error> {
1336 let ast = ast_from(&"config MODVERSIONS")?;
1337
1338 assert_eq!(ast.len(), 1);
1339 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1340 let elt = ast.element("MODVERSIONS").unwrap();
1341 assert_eq!(elt.elt_type(), ElementType::Config);
1342 Ok(())
1343 }
1344
1345 #[test]
1346 fn test_parse_menuconfig() -> Result<(), Error> {
1347 let ast = ast_from(&"menuconfig MODVERSIONS")?;
1348
1349 assert_eq!(ast.len(), 1);
1350 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1351 let elt = ast.element("MODVERSIONS").unwrap();
1352 assert_eq!(elt.elt_type(), ElementType::MenuConfig);
1353 Ok(())
1354 }
1355
1356 #[test]
1357 fn test_parse_config_dependencies() -> Result<(), Error> {
1358 let ast = ast_from(&"config MODVERSIONS depends on MODULES")?;
1359
1360 assert_eq!(ast.len(), 1);
1361 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1362 let elt = ast.element("MODVERSIONS").unwrap();
1363 let deps = elt.dependencies();
1364 assert_eq!(deps.len(), 1);
1365 let expected_dep = Dependency::new(&Expr::Sym("MODULES".to_string()));
1366 assert_eq!(deps.contains(&expected_dep), true);
1367 Ok(())
1368 }
1369
1370 #[test]
1371 fn test_parse_config_multiple_dependencies() -> Result<(), Error> {
1372 let ast = ast_from(&"config MODVERSIONS depends on FOO && BAR")?;
1373
1374 assert_eq!(ast.len(), 1);
1375 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1376 let elt = ast.element("MODVERSIONS").unwrap();
1377 let deps = elt.dependencies();
1378 assert_eq!(deps.len(), 1);
1379 let foo_subexpr = Expr::Sym("FOO".to_string());
1380 let bar_subexpr = Expr::Sym("BAR".to_string());
1381 for dep in deps {
1382 assert_eq!(dep.expr().is_and(), true);
1383 assert_eq!(dep.len(), 2);
1384 assert_eq!(dep.contains(&foo_subexpr), true);
1385 assert_eq!(dep.contains(&bar_subexpr), true);
1386 }
1387 Ok(())
1388 }
1389
1390 #[test]
1391 fn test_parse_config_prompt() -> Result<(), Error> {
1392 let ast = ast_from(&"config MODVERSIONS prompt \"Hello World\"")?;
1393
1394 assert_eq!(ast.len(), 1);
1395 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1396 let elt = ast.element("MODVERSIONS").unwrap();
1397 assert_ne!(elt.prompt(), None);
1398 let prompt = elt.prompt().unwrap();
1399 assert_eq!(prompt, "Hello World".to_string());
1400 Ok(())
1401 }
1402
1403 #[test]
1404 fn test_parse_bool() -> Result<(), Error> {
1405 let ast = ast_from(&"config MODVERSIONS \n prompt \"Hello World\" \nbool")?;
1406
1407 assert_eq!(ast.len(), 1);
1408 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1409 let elt = ast.element("MODVERSIONS").unwrap();
1410 assert_ne!(elt.prompt(), None);
1411 let prompt = elt.prompt().unwrap();
1412 assert_eq!(prompt, "Hello World".to_string());
1413 assert_eq!(elt.types().unwrap().get(&ConfigType::Bool).unwrap(), &None);
1414 Ok(())
1415 }
1416
1417 #[test]
1418 fn test_parse_bool_with_prompt() -> Result<(), Error> {
1419 let ast = ast_from(&"config MODVERSIONS \nbool \"Hello World\"")?;
1420
1421 assert_eq!(ast.len(), 1);
1422 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1423 let elt = ast.element("MODVERSIONS").unwrap();
1424 assert_ne!(elt.prompt(), None);
1425 let prompt = elt.prompt().unwrap();
1426 assert_eq!(prompt, "Hello World".to_string());
1427 assert_eq!(elt.types().unwrap().get(&ConfigType::Bool).unwrap(), &None);
1428 Ok(())
1429 }
1430
1431 #[test]
1432 fn test_parse_bool_with_if_dependency() -> Result<(), Error> {
1433 let ast = ast_from(&"config MODVERSIONS \nbool if FOO")?;
1434
1435 assert_eq!(ast.len(), 1);
1436 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1437 let elt = ast.element("MODVERSIONS").unwrap();
1438 assert_eq!(elt.prompt(), None);
1439 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1440 assert_eq!(
1441 elt.types().unwrap().get(&ConfigType::Bool).unwrap(),
1442 &Some(expected_dep)
1443 );
1444 Ok(())
1445 }
1446
1447 #[test]
1448 fn test_parse_bool_with_prompt_and_if_dependency() -> Result<(), Error> {
1449 let ast = ast_from(&"config MODVERSIONS \ntristate \"Hello World\" if FOO")?;
1450
1451 assert_eq!(ast.len(), 1);
1452 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1453 let elt = ast.element("MODVERSIONS").unwrap();
1454 assert_ne!(elt.prompt(), None);
1455 let prompt = elt.prompt().unwrap();
1456 assert_eq!(prompt, "Hello World".to_string());
1457 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1458 assert_eq!(
1459 elt.types().unwrap().get(&ConfigType::Tristate).unwrap(),
1460 &Some(expected_dep)
1461 );
1462 Ok(())
1463 }
1464
1465 #[test]
1466 fn test_parse_tristate() -> Result<(), Error> {
1467 let ast = ast_from(&"config MODVERSIONS \n prompt \"Hello World\" \ntristate")?;
1468
1469 assert_eq!(ast.len(), 1);
1470 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1471 let elt = ast.element("MODVERSIONS").unwrap();
1472 assert_ne!(elt.prompt(), None);
1473 let prompt = elt.prompt().unwrap();
1474 assert_eq!(prompt, "Hello World".to_string());
1475 assert_eq!(
1476 elt.types().unwrap().get(&ConfigType::Tristate).unwrap(),
1477 &None
1478 );
1479 Ok(())
1480 }
1481
1482 #[test]
1483 fn test_parse_tristate_with_prompt() -> Result<(), Error> {
1484 let ast = ast_from(&"config MODVERSIONS \ntristate \"Hello World\"")?;
1485
1486 assert_eq!(ast.len(), 1);
1487 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1488 let elt = ast.element("MODVERSIONS").unwrap();
1489 assert_ne!(elt.prompt(), None);
1490 let prompt = elt.prompt().unwrap();
1491 assert_eq!(prompt, "Hello World".to_string());
1492 assert_eq!(
1493 elt.types().unwrap().get(&ConfigType::Tristate).unwrap(),
1494 &None
1495 );
1496 Ok(())
1497 }
1498
1499 #[test]
1500 fn test_parse_tristate_with_if_dependency() -> Result<(), Error> {
1501 let ast = ast_from(&"config MODVERSIONS \ntristate if FOO")?;
1502
1503 assert_eq!(ast.len(), 1);
1504 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1505 let elt = ast.element("MODVERSIONS").unwrap();
1506 assert_eq!(elt.prompt(), None);
1507 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1508 assert_eq!(
1509 elt.types().unwrap().get(&ConfigType::Tristate).unwrap(),
1510 &Some(expected_dep)
1511 );
1512 Ok(())
1513 }
1514
1515 #[test]
1516 fn test_parse_tristate_with_prompt_and_if_dependency() -> Result<(), Error> {
1517 let ast = ast_from(&"config MODVERSIONS \ntristate \"Hello World\" if FOO")?;
1518
1519 assert_eq!(ast.len(), 1);
1520 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1521 let elt = ast.element("MODVERSIONS").unwrap();
1522 assert_ne!(elt.prompt(), None);
1523 let prompt = elt.prompt().unwrap();
1524 assert_eq!(prompt, "Hello World".to_string());
1525 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1526 assert_eq!(
1527 elt.types().unwrap().get(&ConfigType::Tristate).unwrap(),
1528 &Some(expected_dep)
1529 );
1530 Ok(())
1531 }
1532
1533 #[test]
1534 fn test_parse_string() -> Result<(), Error> {
1535 let ast = ast_from(&"config MODVERSIONS \n prompt \"Hello World\" \nstring")?;
1536
1537 assert_eq!(ast.len(), 1);
1538 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1539 let elt = ast.element("MODVERSIONS").unwrap();
1540 assert_ne!(elt.prompt(), None);
1541 let prompt = elt.prompt().unwrap();
1542 assert_eq!(prompt, "Hello World".to_string());
1543 assert_eq!(
1544 elt.types().unwrap().get(&ConfigType::String).unwrap(),
1545 &None
1546 );
1547 Ok(())
1548 }
1549
1550 #[test]
1551 fn test_parse_string_with_prompt() -> Result<(), Error> {
1552 let ast = ast_from(&"config MODVERSIONS \nstring \"Hello World\"")?;
1553
1554 assert_eq!(ast.len(), 1);
1555 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1556 let elt = ast.element("MODVERSIONS").unwrap();
1557 assert_ne!(elt.prompt(), None);
1558 let prompt = elt.prompt().unwrap();
1559 assert_eq!(prompt, "Hello World".to_string());
1560 assert_eq!(
1561 elt.types().unwrap().get(&ConfigType::String).unwrap(),
1562 &None
1563 );
1564 Ok(())
1565 }
1566
1567 #[test]
1568 fn test_parse_string_with_if_dependency() -> Result<(), Error> {
1569 let ast = ast_from(&"config MODVERSIONS \nstring if FOO")?;
1570
1571 assert_eq!(ast.len(), 1);
1572 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1573 let elt = ast.element("MODVERSIONS").unwrap();
1574 assert_eq!(elt.prompt(), None);
1575 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1576 assert_eq!(
1577 elt.types().unwrap().get(&ConfigType::String).unwrap(),
1578 &Some(expected_dep)
1579 );
1580 Ok(())
1581 }
1582
1583 #[test]
1584 fn test_parse_string_with_prompt_and_if_dependency() -> Result<(), Error> {
1585 let ast = ast_from(&"config MODVERSIONS \nstring \"Hello World\" if FOO")?;
1586
1587 assert_eq!(ast.len(), 1);
1588 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1589 let elt = ast.element("MODVERSIONS").unwrap();
1590 assert_ne!(elt.prompt(), None);
1591 let prompt = elt.prompt().unwrap();
1592 assert_eq!(prompt, "Hello World".to_string());
1593 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1594 assert_eq!(
1595 elt.types().unwrap().get(&ConfigType::String).unwrap(),
1596 &Some(expected_dep)
1597 );
1598 Ok(())
1599 }
1600
1601 #[test]
1602 fn test_parse_int() -> Result<(), Error> {
1603 let ast = ast_from(&"config MODVERSIONS \n prompt \"Hello World\" \nint")?;
1604
1605 assert_eq!(ast.len(), 1);
1606 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1607 let elt = ast.element("MODVERSIONS").unwrap();
1608 assert_ne!(elt.prompt(), None);
1609 let prompt = elt.prompt().unwrap();
1610 assert_eq!(prompt, "Hello World".to_string());
1611 assert_eq!(elt.types().unwrap().get(&ConfigType::Int).unwrap(), &None);
1612 Ok(())
1613 }
1614
1615 #[test]
1616 fn test_parse_int_with_prompt() -> Result<(), Error> {
1617 let ast = ast_from(&"config MODVERSIONS \nint \"Hello World\"")?;
1618
1619 assert_eq!(ast.len(), 1);
1620 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1621 let elt = ast.element("MODVERSIONS").unwrap();
1622 assert_ne!(elt.prompt(), None);
1623 let prompt = elt.prompt().unwrap();
1624 assert_eq!(prompt, "Hello World".to_string());
1625 assert_eq!(elt.types().unwrap().get(&ConfigType::Int).unwrap(), &None);
1626 Ok(())
1627 }
1628
1629 #[test]
1630 fn test_parse_int_with_if_dependency() -> Result<(), Error> {
1631 let ast = ast_from(&"config MODVERSIONS \nint if FOO")?;
1632
1633 assert_eq!(ast.len(), 1);
1634 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1635 let elt = ast.element("MODVERSIONS").unwrap();
1636 assert_eq!(elt.prompt(), None);
1637 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1638 assert_eq!(
1639 elt.types().unwrap().get(&ConfigType::Int).unwrap(),
1640 &Some(expected_dep)
1641 );
1642 Ok(())
1643 }
1644
1645 #[test]
1646 fn test_parse_int_with_prompt_and_if_dependency() -> Result<(), Error> {
1647 let ast = ast_from(&"config MODVERSIONS \nint \"Hello World\" if FOO")?;
1648
1649 assert_eq!(ast.len(), 1);
1650 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1651 let elt = ast.element("MODVERSIONS").unwrap();
1652 assert_ne!(elt.prompt(), None);
1653 let prompt = elt.prompt().unwrap();
1654 assert_eq!(prompt, "Hello World".to_string());
1655 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1656 assert_eq!(
1657 elt.types().unwrap().get(&ConfigType::Int).unwrap(),
1658 &Some(expected_dep)
1659 );
1660 Ok(())
1661 }
1662
1663 #[test]
1664 fn test_parse_hex() -> Result<(), Error> {
1665 let ast = ast_from(&"config MODVERSIONS \n prompt \"Hello World\" \nhex")?;
1666
1667 assert_eq!(ast.len(), 1);
1668 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1669 let elt = ast.element("MODVERSIONS").unwrap();
1670 assert_ne!(elt.prompt(), None);
1671 let prompt = elt.prompt().unwrap();
1672 assert_eq!(prompt, "Hello World".to_string());
1673 assert_eq!(elt.types().unwrap().get(&ConfigType::Hex).unwrap(), &None);
1674 Ok(())
1675 }
1676
1677 #[test]
1678 fn test_parse_hex_with_prompt() -> Result<(), Error> {
1679 let ast = ast_from(&"config MODVERSIONS \nhex \"Hello World\"")?;
1680
1681 assert_eq!(ast.len(), 1);
1682 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1683 let elt = ast.element("MODVERSIONS").unwrap();
1684 assert_ne!(elt.prompt(), None);
1685 let prompt = elt.prompt().unwrap();
1686 assert_eq!(prompt, "Hello World".to_string());
1687 assert_eq!(elt.types().unwrap().get(&ConfigType::Hex).unwrap(), &None);
1688 Ok(())
1689 }
1690
1691 #[test]
1692 fn test_parse_hex_with_if_dependency() -> Result<(), Error> {
1693 let ast = ast_from(&"config MODVERSIONS \nhex if FOO")?;
1694
1695 assert_eq!(ast.len(), 1);
1696 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1697 let elt = ast.element("MODVERSIONS").unwrap();
1698 assert_eq!(elt.prompt(), None);
1699 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1700 assert_eq!(
1701 elt.types().unwrap().get(&ConfigType::Hex).unwrap(),
1702 &Some(expected_dep)
1703 );
1704 Ok(())
1705 }
1706
1707 #[test]
1708 fn test_parse_hex_with_prompt_and_if_dependency() -> Result<(), Error> {
1709 let ast = ast_from(&"config MODVERSIONS \nhex \"Hello World\" if FOO")?;
1710
1711 assert_eq!(ast.len(), 1);
1712 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1713 let elt = ast.element("MODVERSIONS").unwrap();
1714 assert_ne!(elt.prompt(), None);
1715 let prompt = elt.prompt().unwrap();
1716 assert_eq!(prompt, "Hello World".to_string());
1717 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1718 assert_eq!(
1719 elt.types().unwrap().get(&ConfigType::Hex).unwrap(),
1720 &Some(expected_dep)
1721 );
1722 Ok(())
1723 }
1724
1725 #[test]
1726 fn test_parse_default() -> Result<(), Error> {
1727 let ast = ast_from(&"config MODVERSIONS \n default y")?;
1728
1729 assert_eq!(ast.len(), 1);
1730 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1731 let elt = ast.element("MODVERSIONS").unwrap();
1732 assert_eq!(
1733 elt.defaults()
1734 .unwrap()
1735 .get(&Expr::Sym("y".to_string()))
1736 .unwrap(),
1737 &None
1738 );
1739 Ok(())
1740 }
1741
1742 #[test]
1743 fn test_parse_default_string() -> Result<(), Error> {
1744 let ast = ast_from(&"config MODVERSIONS \n default \"y\"")?;
1745
1746 assert_eq!(ast.len(), 1);
1747 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1748 let elt = ast.element("MODVERSIONS").unwrap();
1749 assert_eq!(
1750 elt.defaults()
1751 .unwrap()
1752 .get(&Expr::Sym("y".to_string()))
1753 .unwrap(),
1754 &None
1755 );
1756 Ok(())
1757 }
1758
1759 #[test]
1760 fn test_parse_default_with_if_dependency() -> Result<(), Error> {
1761 let ast = ast_from(&"config MODVERSIONS \nbool default y if FOO")?;
1762
1763 assert_eq!(ast.len(), 1);
1764 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1765 let elt = ast.element("MODVERSIONS").unwrap();
1766 let key = Expr::Sym("y".to_string());
1767 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1768 assert_eq!(
1769 elt.defaults().unwrap().get(&key).unwrap(),
1770 &Some(expected_dep)
1771 );
1772 Ok(())
1773 }
1774
1775 #[test]
1776 fn test_parse_def_bool() -> Result<(), Error> {
1777 let ast = ast_from(&"config MODVERSIONS \n def_bool y")?;
1778
1779 assert_eq!(ast.len(), 1);
1780 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1781 let elt = ast.element("MODVERSIONS").unwrap();
1782 assert_eq!(elt.types().unwrap().get(&ConfigType::Bool).unwrap(), &None);
1783 assert_eq!(
1784 elt.defaults()
1785 .unwrap()
1786 .get(&Expr::Sym("y".to_string()))
1787 .unwrap(),
1788 &None
1789 );
1790 Ok(())
1791 }
1792
1793 #[test]
1794 fn test_parse_def_bool_with_dependency() -> Result<(), Error> {
1795 let ast = ast_from(&"config MODVERSIONS \ndef_bool y if FOO")?;
1796
1797 assert_eq!(ast.len(), 1);
1798 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1799 let elt = ast.element("MODVERSIONS").unwrap();
1800 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1801 assert_eq!(
1802 elt.types().unwrap().get(&ConfigType::Bool).unwrap(),
1803 &Some(expected_dep.clone())
1804 );
1805 let key = Expr::Sym("y".to_string());
1806 assert_eq!(
1807 elt.defaults().unwrap().get(&key).unwrap(),
1808 &Some(expected_dep)
1809 );
1810 Ok(())
1811 }
1812
1813 #[test]
1814 fn test_parse_def_tristate() -> Result<(), Error> {
1815 let ast = ast_from(&"config MODVERSIONS \n def_tristate y")?;
1816
1817 assert_eq!(ast.len(), 1);
1818 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1819 let elt = ast.element("MODVERSIONS").unwrap();
1820 assert_eq!(
1821 elt.types().unwrap().get(&ConfigType::Tristate).unwrap(),
1822 &None
1823 );
1824 assert_eq!(
1825 elt.defaults()
1826 .unwrap()
1827 .get(&Expr::Sym("y".to_string()))
1828 .unwrap(),
1829 &None
1830 );
1831 Ok(())
1832 }
1833
1834 #[test]
1835 fn test_parse_def_tristate_with_dependency() -> Result<(), Error> {
1836 let ast = ast_from(&"config MODVERSIONS \ndef_tristate y if FOO")?;
1837
1838 assert_eq!(ast.len(), 1);
1839 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1840 let elt = ast.element("MODVERSIONS").unwrap();
1841 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1842 assert_eq!(
1843 elt.types().unwrap().get(&ConfigType::Tristate).unwrap(),
1844 &Some(expected_dep.clone())
1845 );
1846 let key = Expr::Sym("y".to_string());
1847 assert_eq!(
1848 elt.defaults().unwrap().get(&key).unwrap(),
1849 &Some(expected_dep)
1850 );
1851 Ok(())
1852 }
1853
1854 #[test]
1855 fn test_parse_select() -> Result<(), Error> {
1856 let ast = ast_from(&"config MODVERSIONS \n select y")?;
1857
1858 assert_eq!(ast.len(), 1);
1859 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1860 let elt = ast.element("MODVERSIONS").unwrap();
1861 assert_eq!(
1862 elt.reverse_dependencies()
1863 .unwrap()
1864 .get(&"y".to_string())
1865 .unwrap(),
1866 &None
1867 );
1868 Ok(())
1869 }
1870
1871 #[test]
1872 fn test_parse_select_with_dependency() -> Result<(), Error> {
1873 let ast = ast_from(&"config MODVERSIONS \nselect y if FOO")?;
1874
1875 assert_eq!(ast.len(), 1);
1876 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1877 let elt = ast.element("MODVERSIONS").unwrap();
1878 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1879 assert_eq!(
1880 elt.reverse_dependencies()
1881 .unwrap()
1882 .get(&"y".to_string())
1883 .unwrap(),
1884 &Some(expected_dep)
1885 );
1886 Ok(())
1887 }
1888
1889 #[test]
1890 fn test_parse_imply() -> Result<(), Error> {
1891 let ast = ast_from(&"config MODVERSIONS \n imply y")?;
1892
1893 assert_eq!(ast.len(), 1);
1894 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1895 let elt = ast.element("MODVERSIONS").unwrap();
1896 assert_eq!(
1897 elt.weak_dependencies()
1898 .unwrap()
1899 .get(&"y".to_string())
1900 .unwrap(),
1901 &None
1902 );
1903 Ok(())
1904 }
1905
1906 #[test]
1907 fn test_parse_imply_with_dependency() -> Result<(), Error> {
1908 let ast = ast_from(&"config MODVERSIONS \nimply y if FOO")?;
1909
1910 assert_eq!(ast.len(), 1);
1911 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1912 let elt = ast.element("MODVERSIONS").unwrap();
1913 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1914 assert_eq!(
1915 elt.weak_dependencies()
1916 .unwrap()
1917 .get(&"y".to_string())
1918 .unwrap(),
1919 &Some(expected_dep)
1920 );
1921 Ok(())
1922 }
1923
1924 #[test]
1925 fn test_parse_range() -> Result<(), Error> {
1926 let ast = ast_from(&"config MODVERSIONS \n range 1 2")?;
1927
1928 assert_eq!(ast.len(), 1);
1929 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1930 let elt = ast.element("MODVERSIONS").unwrap();
1931 assert_eq!(elt.range().unwrap().lhs(), 1);
1932 assert_eq!(elt.range().unwrap().rhs(), 2);
1933 assert_eq!(elt.range().unwrap().dependency(), &None);
1934 Ok(())
1935 }
1936
1937 #[test]
1938 fn test_negative_to_positive_range() -> Result<(), Error> {
1939 let ast = ast_from(&"config MODVERSIONS \n range -1 1")?;
1940
1941 assert_eq!(ast.len(), 1);
1942 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1943 let elt = ast.element("MODVERSIONS").unwrap();
1944 assert_eq!(elt.range().unwrap().lhs(), -1);
1945 assert_eq!(elt.range().unwrap().rhs(), 1);
1946 assert_eq!(elt.range().unwrap().dependency(), &None);
1947 Ok(())
1948 }
1949
1950 #[test]
1951 fn test_negative_range() -> Result<(), Error> {
1952 let ast = ast_from(&"config MODVERSIONS \n range -2 -1")?;
1953
1954 assert_eq!(ast.len(), 1);
1955 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1956 let elt = ast.element("MODVERSIONS").unwrap();
1957 assert_eq!(elt.range().unwrap().lhs(), -2);
1958 assert_eq!(elt.range().unwrap().rhs(), -1);
1959 assert_eq!(elt.range().unwrap().dependency(), &None);
1960 Ok(())
1961 }
1962
1963 #[test]
1964 fn test_parse_range_with_dependency() -> Result<(), Error> {
1965 let ast = ast_from(&"config MODVERSIONS \nrange 1 2 if FOO")?;
1966
1967 assert_eq!(ast.len(), 1);
1968 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1969 let elt = ast.element("MODVERSIONS").unwrap();
1970 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
1971 assert_eq!(elt.range().unwrap().lhs(), 1);
1972 assert_eq!(elt.range().unwrap().rhs(), 2);
1973 assert_eq!(elt.range().unwrap().dependency(), &Some(expected_dep));
1974 Ok(())
1975 }
1976
1977 #[test]
1978 fn test_parse_help() -> Result<(), Error> {
1979 let ast = ast_from(&"config MODVERSIONS \nhelp\n foo\n bar\n")?;
1980
1981 assert_eq!(ast.len(), 1);
1982 assert_eq!(ast.contains_element("MODVERSIONS"), true);
1983 let elt = ast.element("MODVERSIONS").unwrap();
1984 assert_eq!(
1985 elt.help().into_iter().next().unwrap(),
1986 "foo\nbar".to_string()
1987 );
1988 Ok(())
1989 }
1990
1991 #[test]
1992 fn test_parse_comment() -> Result<(), Error> {
1993 let ast = ast_from(&"comment \"Foo\"")?;
1994
1995 assert_eq!(ast.comment(), "Foo".to_string());
1996 Ok(())
1997 }
1998
1999 #[test]
2000 fn test_parse_simple_if() -> Result<(), Error> {
2001 let ast = ast_from(&"if FOO endif")?;
2002
2003 assert_eq!(ast.len_conditional_blocks(), 1);
2004 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
2005 let mut passes = 0;
2006 for block in ast.conditional_blocks() {
2007 assert_eq!(block.dependency(), expected_dep);
2008 passes += 1;
2009 }
2010 assert_eq!(passes, 1);
2011 Ok(())
2012 }
2013
2014 #[test]
2015 fn test_simple_menu() -> Result<(), Error> {
2016 let ast = ast_from(&"menu \"Menu\"\nendmenu")?;
2017
2018 assert_eq!(ast.len(), 1);
2019 assert_eq!(ast.contains_element("Menu"), true);
2020 let elt = ast.element("Menu").unwrap();
2021 assert_eq!(elt.elt_type(), ElementType::Menu);
2022 Ok(())
2023 }
2024
2025 #[test]
2026 fn test_menu_depends_on() -> Result<(), Error> {
2027 let ast = ast_from(&"menu \"Menu\" depends on MODULES \nendmenu")?;
2028
2029 assert_eq!(ast.len(), 1);
2030 assert_eq!(ast.contains_element("Menu"), true);
2031 let elt = ast.element("Menu").unwrap();
2032 let deps = elt.dependencies();
2033 assert_eq!(deps.len(), 1);
2034 let expected_dep = Dependency::new(&Expr::Sym("MODULES".to_string()));
2035 assert_eq!(deps.contains(&expected_dep), true);
2036 Ok(())
2037 }
2038
2039 #[test]
2040 fn test_menu_visible_if() -> Result<(), Error> {
2041 let ast = ast_from(&"menu \"Menu\" visible if MODULES \nendmenu")?;
2042
2043 assert_eq!(ast.len(), 1);
2044 assert_eq!(ast.contains_element("Menu"), true);
2045 let elt = ast.element("Menu").unwrap();
2046 let visible_deps = elt.visible_if();
2047 assert_eq!(visible_deps.len(), 1);
2048 let expected_dep = Dependency::new(&Expr::Sym("MODULES".to_string()));
2049 assert_eq!(visible_deps.contains(&expected_dep), true);
2050 Ok(())
2051 }
2052
2053 #[test]
2054 fn test_menu_with_config() -> Result<(), Error> {
2055 let ast = ast_from(&"menu \"Menu\" config FOO \nendmenu")?;
2056
2057 assert_eq!(ast.len(), 1);
2058 assert_eq!(ast.contains_element("Menu"), true);
2059 let elt = ast.element("Menu").unwrap();
2060 let sub_elements = elements_vec_to_hashmap(elt.sub_elements());
2061 assert_eq!(sub_elements.len(), 1);
2062 assert_eq!(sub_elements.contains_key("FOO"), true);
2063 let sub_elt = sub_elements.get("FOO").unwrap();
2064 assert_eq!(sub_elt.elt_type(), ElementType::Config);
2065 assert_eq!(sub_elt.name(), "FOO".to_string());
2066 Ok(())
2067 }
2068
2069 #[test]
2070 fn test_menu_with_menuconfig() -> Result<(), Error> {
2071 let ast = ast_from(&"menu \"Menu\" menuconfig FOO \nendmenu")?;
2072
2073 assert_eq!(ast.len(), 1);
2074 assert_eq!(ast.contains_element("Menu"), true);
2075 let elt = ast.element("Menu").unwrap();
2076 let sub_elements = elements_vec_to_hashmap(elt.sub_elements());
2077 assert_eq!(sub_elements.len(), 1);
2078 assert_eq!(sub_elements.contains_key("FOO"), true);
2079 let sub_elt = sub_elements.get("FOO").unwrap();
2080 assert_eq!(sub_elt.elt_type(), ElementType::MenuConfig);
2081 assert_eq!(sub_elt.name(), "FOO".to_string());
2082 Ok(())
2083 }
2084
2085 #[test]
2086 fn test_menu_with_submenu() -> Result<(), Error> {
2087 let ast = ast_from(&"menu \"Menu\"\nmenu \"Submenu\" endmenu \nendmenu")?;
2088
2089 assert_eq!(ast.len(), 1);
2090 assert_eq!(ast.contains_element("Menu"), true);
2091 let elt = ast.element("Menu").unwrap();
2092 let sub_elements = elements_vec_to_hashmap(elt.sub_elements());
2093 assert_eq!(sub_elements.len(), 1);
2094 assert_eq!(sub_elements.contains_key("Submenu"), true);
2095 let sub_elt = sub_elements.get("Submenu").unwrap();
2096 assert_eq!(sub_elt.elt_type(), ElementType::Menu);
2097 assert_eq!(sub_elt.name(), "Submenu".to_string());
2098 Ok(())
2099 }
2100
2101 #[test]
2102 fn test_menu_comment() -> Result<(), Error> {
2103 let ast = ast_from(&"menu \"Menu\" comment \"Foo\" endmenu")?;
2104
2105 let elt = ast.element("Menu").unwrap();
2106 assert_eq!(elt.elt_type(), ElementType::Menu);
2107 if let Element::Menu(menu) = elt {
2108 assert_eq!(menu.comment(), "Foo".to_string());
2109 }
2110 Ok(())
2111 }
2112
2113 #[test]
2114 fn test_menu_simple_if() -> Result<(), Error> {
2115 let ast = ast_from(&"menu \"Menu\" if FOO endif endmenu")?;
2116
2117 assert_eq!(ast.contains_element("Menu"), true);
2118 let elt = ast.element("Menu").unwrap();
2119 assert_eq!(elt.len_conditional_blocks(), 1);
2120 let expected_dep = Dependency::new(&Expr::Sym("FOO".to_string()));
2121 let mut passes = 0;
2122 for block in elt.conditional_blocks() {
2123 assert_eq!(block.dependency(), expected_dep);
2124 passes += 1;
2125 }
2126 assert_eq!(passes, 1);
2127 Ok(())
2128 }
2129
2130 #[test]
2131 fn test_if_with_config() -> Result<(), Error> {
2132 let ast = ast_from(&"if CONDITION \n config FOO \n endif")?;
2133
2134 assert_eq!(ast.len_conditional_blocks(), 1);
2135 let expected_dep = Dependency::new(&Expr::Sym("CONDITION".to_string()));
2136 let mut passes = 0;
2137 for block in ast.conditional_blocks() {
2138 assert_eq!(block.dependency(), expected_dep);
2139 let sub_elements = elements_vec_to_hashmap(block.elements());
2140 assert_eq!(sub_elements.len(), 1);
2141 assert_eq!(sub_elements.contains_key("FOO"), true);
2142 let sub_elt = sub_elements.get("FOO").unwrap();
2143 assert_eq!(sub_elt.elt_type(), ElementType::Config);
2144 assert_eq!(sub_elt.name(), "FOO".to_string());
2145 passes += 1;
2146 }
2147 assert_eq!(passes, 1);
2148 Ok(())
2149 }
2150
2151 #[test]
2152 fn test_if_with_menuconfig() -> Result<(), Error> {
2153 let ast = ast_from(&"if CONDITION\n menuconfig FOO \n endif")?;
2154
2155 assert_eq!(ast.len_conditional_blocks(), 1);
2156 let expected_dep = Dependency::new(&Expr::Sym("CONDITION".to_string()));
2157 let mut passes = 0;
2158 for block in ast.conditional_blocks() {
2159 assert_eq!(block.dependency(), expected_dep);
2160 let sub_elements = elements_vec_to_hashmap(block.elements());
2161 assert_eq!(sub_elements.len(), 1);
2162 assert_eq!(sub_elements.contains_key("FOO"), true);
2163 let sub_elt = sub_elements.get("FOO").unwrap();
2164 assert_eq!(sub_elt.elt_type(), ElementType::MenuConfig);
2165 assert_eq!(sub_elt.name(), "FOO".to_string());
2166 passes += 1;
2167 }
2168 assert_eq!(passes, 1);
2169 Ok(())
2170 }
2171
2172 #[test]
2173 fn test_if_with_subif() -> Result<(), Error> {
2174 let ast = ast_from(&"if CONDITION if CONDITION2 endif endif")?;
2175
2176 assert_eq!(ast.len_conditional_blocks(), 1);
2177 let mut passes = 0;
2178 for block in ast.conditional_blocks() {
2179 assert_eq!(block.len_conditional_blocks(), 1);
2180 passes += 1;
2181 }
2182 assert_eq!(passes, 1);
2183 Ok(())
2184 }
2185
2186 #[test]
2187 fn test_nameless_mainmenu() -> Result<(), Error> {
2188 let ast = ast_from(&"")?;
2189 assert_eq!(ast.main_menu(), None);
2190 Ok(())
2191 }
2192}