packcr 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/packcr/generated/context.rb +8 -13
- data/lib/packcr/generated/node/action_node.rb +4 -6
- data/lib/packcr/generated/node/alternate_node.rb +11 -17
- data/lib/packcr/generated/node/capture_node.rb +1 -1
- data/lib/packcr/generated/node/charclass_node.rb +8 -8
- data/lib/packcr/generated/node/eof_node.rb +1 -1
- data/lib/packcr/generated/node/error_node.rb +1 -1
- data/lib/packcr/generated/node/expand_node.rb +1 -1
- data/lib/packcr/generated/node/predicate_node.rb +9 -7
- data/lib/packcr/generated/node/quantity_node.rb +16 -16
- data/lib/packcr/generated/node/reference_node.rb +3 -8
- data/lib/packcr/generated/node/rule_node.rb +6 -6
- data/lib/packcr/generated/node/sequence_node.rb +1 -1
- data/lib/packcr/generated/node/string_node.rb +28 -4
- data/lib/packcr/generator.rb +4 -3
- data/lib/packcr/node/action_node.rb +2 -2
- data/lib/packcr/node/alternate_node.rb +2 -2
- data/lib/packcr/node/capture_node.rb +2 -2
- data/lib/packcr/node/charclass_node.rb +15 -15
- data/lib/packcr/node/eof_node.rb +2 -2
- data/lib/packcr/node/error_node.rb +2 -2
- data/lib/packcr/node/expand_node.rb +2 -2
- data/lib/packcr/node/predicate_node.rb +3 -3
- data/lib/packcr/node/quantity_node.rb +4 -4
- data/lib/packcr/node/reference_node.rb +4 -4
- data/lib/packcr/node/rule_node.rb +2 -2
- data/lib/packcr/node/sequence_node.rb +2 -2
- data/lib/packcr/node/string_node.rb +17 -3
- data/lib/packcr/parser.rb +1 -1
- data/lib/packcr/templates/context/source.rs.erb +93 -91
- data/lib/packcr/templates/node/action.rs.erb +5 -5
- data/lib/packcr/templates/node/alternate.rs.erb +28 -29
- data/lib/packcr/templates/node/charclass_utf8.rs.erb +3 -3
- data/lib/packcr/templates/node/predicate_neg.rs.erb +6 -6
- data/lib/packcr/templates/node/quantity_many.rs.erb +55 -28
- data/lib/packcr/templates/node/reference.rs.erb +2 -2
- data/lib/packcr/templates/node/rule.rs.erb +20 -11
- data/lib/packcr/templates/node/string_many.rs.erb +4 -4
- data/lib/packcr/templates/node/string_many_reverse.rs.erb +7 -0
- data/lib/packcr/templates/node/string_one.rs.erb +3 -3
- data/lib/packcr/templates/node/string_one_reverse.rs.erb +6 -0
- data/lib/packcr/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec849cdb4d638eb308cdefaf4a2e743ec49e71b46b7343265f8f8b78f5508c5a
|
4
|
+
data.tar.gz: d9c7e0db4c53e247edfb28ca9a6266364e0647152a202c92ca94bdf60ed0e5e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7b5ec64eb5ea1a407efb518ee0a169f7d0a24294e9d0924fbd7c9bf7a95fd20de13f0ccda290e8deea34b4745d08e07022576fa120dc58f2d81cb4c0e12ee4e
|
7
|
+
data.tar.gz: aa881736505df4e86e9a511b48941781e89a3618445e71a88034097624750e902edaa986ea0d875e537933034c4e0e12b5e8a971206732f2084f0b06d2db2b90
|
data/README.md
CHANGED
@@ -486,7 +486,7 @@ class Packcr
|
|
486
486
|
erbout
|
487
487
|
when :rs
|
488
488
|
erbout = +""
|
489
|
-
erbout << "/* A packrat parser generated by PackCR #{Packcr::VERSION} */\n\nuse std::cell::RefCell;\nuse std::collections::{HashMap, HashSet};\nuse std::io::Read;\nuse std::rc::Rc;\n
|
489
|
+
erbout << "/* A packrat parser generated by PackCR #{Packcr::VERSION} */\n\nuse std::cell::RefCell;\nuse std::collections::{HashMap, HashSet};\nuse std::io::Read;\nuse std::rc::Rc;\n".freeze
|
490
490
|
|
491
491
|
if !code(:esource).empty?
|
492
492
|
erbout << "\n".freeze
|
@@ -496,32 +496,27 @@ class Packcr
|
|
496
496
|
end
|
497
497
|
end
|
498
498
|
use_value = @root.rules.map { |r| r.vars.size }.max > 0
|
499
|
-
erbout << "\nstruct LrMemoTable {\n memos: HashMap<usize, LrMemoMap>,\n}\nimpl LrMemoTable {\n fn new() -> Self {\n Self {\n memos: HashMap::new(),\n }\n }\n\n fn clear(&mut self) {\n self.memos.clear();\n }\n\n fn set(&mut self, index: usize, rule: Rule, memo: LrMemo) {\n let memo_map = self.memos.entry(index).or_default();\n memo_map.insert(rule, memo);\n }\n\n fn get(&mut self, index: usize, rule: Rule) -> &mut LrMemo {\n self.memos.get_mut(&index).unwrap().get_mut(&rule).unwrap()\n }\n fn has(&
|
499
|
+
erbout << "\nstruct LrMemoTable {\n memos: HashMap<usize, LrMemoMap>,\n}\nimpl LrMemoTable {\n fn new() -> Self {\n Self {\n memos: HashMap::new(),\n }\n }\n\n fn clear(&mut self) {\n self.memos.clear();\n }\n\n fn set(&mut self, index: usize, rule: Rule, memo: LrMemo) {\n let memo_map = self.memos.entry(index).or_default();\n memo_map.insert(rule, memo);\n }\n\n fn get(&mut self, index: usize, rule: Rule) -> &mut LrMemo {\n self.memos.get_mut(&index).unwrap().get_mut(&rule).unwrap()\n }\n fn has(&self, index: usize, rule: Rule) -> bool {\n self.memos\n .get(&index)\n .is_some_and(|memo_map| memo_map.contains_key(&rule))\n }\n}\n\nstruct LrMemo {\n offset: usize,\n answer: Option<Rc<RefCell<ThunkChunk>>>,\n grow: bool,\n}\n\nimpl LrMemo {\n fn new(offset: usize) -> Self {\n Self {\n offset,\n answer: None,\n grow: false,\n }\n }\n\n fn start_grow(&mut self) -> bool {\n if !self.grow && self.answer.is_none() {\n self.grow = true;\n true\n } else {\n false\n }\n }\n\n fn update(&mut self, answer: Option<ThunkChunk>, offset: usize) {\n self.answer = answer.map(|c| Rc::new(RefCell::new(c)));\n self.offset = offset;\n }\n\n fn clone_answer(&mut self) -> Option<Rc<RefCell<ThunkChunk>>> {\n self.answer.as_ref().map(Rc::clone)\n }\n}\n\nstruct ThunkChunk {\n thunks: Rc<RefCell<Vec<Thunk>>>,\n capts: CaptureTable,\n pos: usize,\n values: ValueTable,\n}\n\nimpl ThunkChunk {\n fn new(pos: usize) -> Self {\n Self {\n values: ValueTable::new(),\n capts: CaptureTable::new(),\n thunks: Rc::new(RefCell::new(Vec::new())),\n pos,\n }\n }\n\n fn push_leaf(\n &self,\n action: Action,\n end: usize,\n value_indices: &[usize],\n capt_indices: &[usize],\n ) {\n {\n let start = self.pos;\n let mut value_refs = HashMap::new();\n for &index in value_indices {\n value_refs.insert(index, ValueRef::new(index, self.values.clone()));\n }\n let mut capts = HashMap::new();\n for &index in capt_indices {\n capts.insert(index, self.capts[index].clone());\n }\n let leaf = Thunk::Leaf(ThunkLeaf::new(action, start, end, value_refs, capts));\n self.thunks.borrow_mut().push(leaf);\n }\n }\n\n fn value_ref(&self, index: usize) -> ValueRef {\n ValueRef::new(index, self.values.clone())\n }\n}\n\nenum Thunk {\n Leaf(ThunkLeaf),\n Node(ThunkNode),\n}\nimpl Thunk {\n fn do_action(&self, processor: &ThunkProcessor, value: ValueRef) -> Value {\n match self {\n Thunk::Leaf(leaf) => leaf.do_action(processor, value),\n Thunk::Node(node) => node.do_action(processor),\n }\n }\n}\n\n#[allow(dead_code)]\nstruct ThunkLeaf {\n value_refs: HashMap<usize, ValueRef>,\n capts: HashMap<usize, Capture>,\n capt0: Capture,\n action: Action,\n}\nimpl ThunkLeaf {\n fn new(\n action: Action,\n start: usize,\n end: usize,\n value_refs: HashMap<usize, ValueRef>,\n capts: HashMap<usize, Capture>,\n ) -> Self {\n Self {\n value_refs,\n capts,\n capt0: Capture { start, end },\n action,\n }\n }\n\n fn do_action(&self, processor: &ThunkProcessor, mut value: ValueRef) -> Value {\n value.with_mut(|v| {\n processor.call_action(self.action, self, v);\n });\n value.get()\n }\n".freeze
|
500
500
|
|
501
501
|
if use_value
|
502
502
|
erbout << "\n fn values(&self) -> HashMap<usize, Value> {\n self.value_refs.iter().map(|(k, v)| (*k, v.get())).collect()\n }\n".freeze
|
503
503
|
end
|
504
|
-
erbout << "}\n\nstruct ThunkNode {\n thunks: Rc<RefCell<Vec<Thunk>>>,\n value: ValueRef,\n}\nimpl ThunkNode {\n fn do_action(&self, processor: &ThunkProcessor) {\n for thunk in self.thunks.
|
504
|
+
erbout << "}\n\nstruct ThunkNode {\n thunks: Rc<RefCell<Vec<Thunk>>>,\n value: ValueRef,\n}\nimpl ThunkNode {\n fn do_action(&self, processor: &ThunkProcessor) -> Value {\n let mut v = 0;\n for thunk in self.thunks.borrow_mut().iter_mut() {\n v = thunk.do_action(processor, self.value.clone());\n }\n v\n }\n}\n\n#[derive(Clone)]\nstruct Capture {\n start: usize,\n end: usize,\n}\n\ntype Value = i32;\n\nstruct ValueTable {\n table: Rc<RefCell<HashMap<usize, Value>>>,\n}\nimpl ValueTable {\n fn new() -> Self {\n Self {\n table: Rc::new(RefCell::new(HashMap::new())),\n }\n }\n".freeze
|
505
505
|
|
506
506
|
if use_value
|
507
507
|
erbout << "\n fn clear(&mut self) {\n self.table.borrow_mut().clear();\n }\n".freeze
|
508
508
|
end
|
509
|
-
erbout << "\n fn with_mut<F>(&mut self, index: usize, f: F)\n where\n F: FnOnce(&mut Value),\n {\n let mut table = self.table.borrow_mut();\n let value = table.entry(index).or_insert(0);\n f(value);\n }\n}\nimpl Clone for ValueTable {\n fn clone(&self) -> Self {\n Self {\n table: self.table.clone(),\n }\n }\n}\n\nstruct ValueRef {\n values: ValueTable,\n index: usize,\n}\nimpl ValueRef {\n fn new(index: usize, values: ValueTable) -> Self {\n Self { index, values }\n }\n\n fn with_mut<F>(&mut self, f: F)\n where\n F: FnOnce(&mut i32),\n {\n self.values.with_mut(self.index, f);\n }\n\n".freeze
|
510
|
-
|
511
|
-
if use_value
|
512
|
-
erbout << " fn get(&self) -> i32 {\n *self.values.table.borrow().get(&self.index).unwrap_or(&0)\n }\n".freeze
|
513
|
-
end
|
514
|
-
erbout << "}\nimpl Clone for ValueRef {\n fn clone(&self) -> Self {\n Self {\n index: self.index,\n values: self.values.clone(),\n }\n }\n}\n\nstruct CaptureTable {\n table: HashMap<usize, Capture>,\n len: usize,\n}\n\ntype RuleSet = HashSet<Rule>;\n\ntype LrMemoMap = HashMap<Rule, LrMemo>;\n\nimpl CaptureTable {\n fn new() -> Self {\n Self {\n table: HashMap::new(),\n len: 0,\n }\n }\n\n fn resize(&mut self, len: usize) {\n let current_len = self.len;\n if len > current_len {\n for i in current_len..len {\n self.table.insert(i, Capture { start: 0, end: 0 });\n }\n } else if len < current_len {\n for i in len..current_len {\n self.table.remove(&i);\n }\n }\n self.len = len;\n }\n}\nimpl std::ops::Index<usize> for CaptureTable {\n type Output = Capture;\n\n fn index(&self, index: usize) -> &Self::Output {\n &self.table[&index]\n }\n}\nimpl std::ops::IndexMut<usize> for CaptureTable {\n fn index_mut(&mut self, index: usize) -> &mut Self::Output {\n if self.len <= index {\n self.resize(index + 1);\n }\n self.table.get_mut(&index).unwrap()\n }\n}\n\nstruct Input {\n input: Box<dyn std::io::Read>,\n start_position: usize,\n position_offset: usize,\n buffer: String,\n}\n\nimpl Input {\n fn new(input: impl std::io::Read + 'static) -> Self {\n Self {\n input: Box::new(input),\n start_position: 0,\n position_offset: 0,\n buffer: String::new(),\n }\n }\n\n fn refill_buffer(&mut self, num: usize) -> usize {\n let mut len = self.buffer.len();\n if len >= self.position_offset + num {\n return len - self.position_offset;\n }\n\n let mut input_buffer = [0u8; 1024];\n\n while len < self.position_offset + num {\n match self.input.read(&mut input_buffer) {\n Ok(0) => break,\n Ok(bytes_read) => {\n let s = std::string::String::from_utf8_lossy(&input_buffer[..bytes_read]);\n self.buffer.push_str(&s);\n }\n Err(_) => break,\n }\n len = self.buffer.len();\n }\n\n len - self.position_offset\n }\n\n fn commit_buffer(&mut self) {\n let position_offset = self.position_offset;\n\n self.buffer.drain(..position_offset);\n\n self.start_position += position_offset;\n self.position_offset = 0;\n }\n\n #[allow(dead_code)]\n fn get_char_as_utf32(&mut self) -> (i32, usize) {\n if self.refill_buffer(1) < 1 {\n return (0, 0);\n }\n\n let current_position = self.position_offset;\n let remaining_chars: &str = &self.buffer[current_position..];\n\n if let Some(ch) = remaining_chars.chars().next() {\n let bytes_used = ch.len_utf8();\n\n if self.refill_buffer(bytes_used) < bytes_used {\n return (0, 0);\n }\n\n let utf32_value = ch as u32 as i32;\n\n return (utf32_value, bytes_used);\n }\n\n (0, 0)\n }\n\n fn back_to(&mut self, memo: &mut LrMemo) -> Option<Rc<RefCell<ThunkChunk>>> {\n self.position_offset = memo.offset;\n memo.answer_as_deref_mut()\n }\n}\n\nstruct #{class_name} {\n level: usize,\n memos: LrMemoTable,\n input: Input,\n}\n\nimpl #{class_name} {\n fn new(input: impl std::io::Read + 'static) -> Self {\n Self {\n level: 0,\n memos: LrMemoTable::new(),\n input: Input::new(input),\n }\n }\n\n fn error(&self) -> ! {\n eprintln!(\"Syntax error\");\n std::process::exit(1);\n }\n\n fn refill_buffer(&mut self, num: usize) -> usize {\n self.input.refill_buffer(num)\n }\n\n fn commit_buffer(&mut self) {\n self.input.commit_buffer();\n self.memos.clear();\n }\n\n fn parse(&mut self) -> bool {\n let mut answer = ThunkChunk::new(0);\n let pos = self.input.start_position;\n\n".freeze
|
509
|
+
erbout << "\n fn with_mut<F>(&mut self, index: usize, f: F)\n where\n F: FnOnce(&mut Value),\n {\n let mut table = self.table.borrow_mut();\n let value = table.entry(index).or_insert(0);\n f(value);\n }\n}\nimpl Clone for ValueTable {\n fn clone(&self) -> Self {\n Self {\n table: self.table.clone(),\n }\n }\n}\n\nstruct ValueRef {\n values: ValueTable,\n index: usize,\n}\nimpl ValueRef {\n fn new(index: usize, values: ValueTable) -> Self {\n Self { index, values }\n }\n\n fn with_mut<F>(&mut self, f: F)\n where\n F: FnOnce(&mut i32),\n {\n self.values.with_mut(self.index, f);\n }\n\n fn get(&self) -> i32 {\n *self.values.table.borrow().get(&self.index).unwrap_or(&0)\n }\n}\nimpl Clone for ValueRef {\n fn clone(&self) -> Self {\n Self {\n index: self.index,\n values: self.values.clone(),\n }\n }\n}\n\nstruct CaptureTable {\n table: HashMap<usize, Capture>,\n len: usize,\n}\n\ntype RuleSet = HashSet<Rule>;\ntype RuleLimit = Option<RuleSet>;\n\ntype LrMemoMap = HashMap<Rule, LrMemo>;\n\nimpl CaptureTable {\n fn new() -> Self {\n Self {\n table: HashMap::new(),\n len: 0,\n }\n }\n\n fn resize(&mut self, len: usize) {\n let current_len = self.len;\n if len > current_len {\n for i in current_len..len {\n self.table.insert(i, Capture { start: 0, end: 0 });\n }\n } else if len < current_len {\n for i in len..current_len {\n self.table.remove(&i);\n }\n }\n self.len = len;\n }\n}\nimpl std::ops::Index<usize> for CaptureTable {\n type Output = Capture;\n\n fn index(&self, index: usize) -> &Self::Output {\n &self.table[&index]\n }\n}\nimpl std::ops::IndexMut<usize> for CaptureTable {\n fn index_mut(&mut self, index: usize) -> &mut Self::Output {\n if self.len <= index {\n self.resize(index + 1);\n }\n self.table.get_mut(&index).unwrap()\n }\n}\n\nstruct Input {\n input: Box<dyn std::io::Read>,\n start_position: usize,\n position_offset: usize,\n buffer: String,\n closed: bool,\n}\n\nimpl Input {\n fn new(input: impl std::io::Read + 'static) -> Self {\n Self {\n input: Box::new(input),\n start_position: 0,\n position_offset: 0,\n buffer: String::new(),\n closed: false,\n }\n }\n\n fn refill_buffer(&mut self, num: usize) -> usize {\n let mut len = self.buffer.len();\n if len >= self.position_offset + num {\n return len - self.position_offset;\n }\n\n let mut input_buffer = [0u8; 1024];\n\n while len < self.position_offset + num {\n match self.input.read(&mut input_buffer) {\n Ok(0) => break,\n Ok(bytes_read) => {\n let s = std::string::String::from_utf8_lossy(&input_buffer[..bytes_read]);\n self.buffer.push_str(&s);\n }\n Err(_) => break,\n }\n len = self.buffer.len();\n }\n\n len - self.position_offset\n }\n\n fn commit_buffer(&mut self) {\n let position_offset = self.position_offset;\n\n self.buffer.drain(..position_offset);\n\n self.start_position += position_offset;\n self.position_offset = 0;\n }\n\n #[allow(dead_code)]\n fn get_char_as_utf32(&mut self) -> (i32, usize) {\n if self.refill_buffer(1) < 1 {\n return (0, 0);\n }\n\n let current_position = self.position_offset;\n let remaining_chars: &str = &self.buffer[current_position..];\n\n if let Some(ch) = remaining_chars.chars().next() {\n let bytes_used = ch.len_utf8();\n\n if self.refill_buffer(bytes_used) < bytes_used {\n return (0, 0);\n }\n\n let utf32_value = ch as u32 as i32;\n\n return (utf32_value, bytes_used);\n }\n\n (0, 0)\n }\n\n fn back_to(&mut self, memo: &mut LrMemo) -> Option<Rc<RefCell<ThunkChunk>>> {\n self.position_offset = memo.offset;\n memo.clone_answer()\n }\n}\n\nconst NOP: Result<usize, usize> = Ok(0);\nconst fn throw(label: usize) -> Result<usize, usize> {\n Err(label)\n}\n\nfn catch(label: usize, f: impl FnOnce() -> Result<usize, usize>) -> Result<usize, usize> {\n match f() {\n Ok(_) => NOP,\n Err(e) if e == label => NOP,\n Err(e) => throw(e),\n }\n}\n\nstruct #{class_name} {\n level: usize,\n memos: LrMemoTable,\n input: Input,\n}\n\nimpl #{class_name} {\n fn new(input: impl std::io::Read + 'static) -> Self {\n Self {\n level: 0,\n memos: LrMemoTable::new(),\n input: Input::new(input),\n }\n }\n\n fn parse(&mut self) -> Option<Value> {\n if self.input.closed {\n return None;\n }\n\n let mut answer = ThunkChunk::new(0);\n let pos = self.input.start_position;\n".freeze
|
515
510
|
|
516
511
|
if !@root.rules.empty?
|
517
|
-
erbout << " let
|
512
|
+
erbout << "\n let value = {\n let node = self.rule_thunk_node(\n Rule::#{Packcr.camelize(@root.rules[0].name)},\n &mut answer,\n 0,\n self.input.position_offset,\n &None,\n );\n self.memos.clear();\n node.map(|node| node.do_action(&ThunkProcessor::new(&self.input.buffer)))\n };\n self.input.commit_buffer();\n if pos == self.input.start_position || self.input.refill_buffer(1) < 1 {\n self.input.closed = true;\n }\n value\n".freeze
|
518
513
|
end
|
519
|
-
erbout << "
|
514
|
+
erbout << " }\n\n fn grow_lr(&mut self, rule: Rule, offset: usize) {\n loop {\n let old_offset = self.input.position_offset;\n self.input.position_offset = offset;\n\n let answer = self.call_rule(rule, offset, Some(RuleSet::new()));\n match answer {\n Some(answer) if self.input.position_offset > old_offset => {\n let memo = self.memos.get(offset, rule);\n memo.update(Some(answer), self.input.position_offset);\n }\n _ => {\n return;\n }\n }\n }\n }\n\n fn rule_answer_without_limits(&mut self, rule: Rule) -> Option<Rc<RefCell<ThunkChunk>>> {\n let offset = self.input.position_offset;\n if !self.memos.has(offset, rule) {\n let memo = LrMemo::new(offset);\n self.memos.set(offset, rule, memo);\n let answer = self.call_rule(rule, offset, None);\n\n let memo = self.memos.get(offset, rule);\n memo.update(answer, self.input.position_offset);\n if !memo.grow {\n return self.input.back_to(memo);\n }\n self.grow_lr(rule, offset);\n\n let memo = self.memos.get(offset, rule);\n memo.grow = false;\n return self.input.back_to(memo);\n }\n\n let memo = self.memos.get(offset, rule);\n if memo.start_grow() {\n return None;\n }\n self.input.back_to(memo)\n }\n\n fn rule_answer_with_limits(\n &mut self,\n rule: Rule,\n limits: RuleSet,\n ) -> Option<Rc<RefCell<ThunkChunk>>> {\n let offset = self.input.position_offset;\n let answer = self.call_rule(rule, offset, Some(limits));\n if !self.memos.has(offset, rule) {\n return answer.map(|answer| Rc::new(RefCell::new(answer)));\n }\n\n let memo = self.memos.get(offset, rule);\n if self.input.position_offset > memo.offset {\n memo.update(answer, self.input.position_offset);\n }\n self.input.back_to(memo)\n }\n\n fn apply_rule(\n &mut self,\n rule: Rule,\n parent: &mut ThunkChunk,\n value_index: usize,\n offset: usize,\n limits: &RuleLimit,\n ) -> bool {\n let node = self.rule_thunk_node(rule, parent, value_index, offset, limits);\n node.is_some_and(|node| {\n parent.thunks.borrow_mut().push(Thunk::Node(node));\n true\n })\n }\n\n fn rule_thunk_node(\n &mut self,\n rule: Rule,\n parent: &ThunkChunk,\n value_index: usize,\n offset: usize,\n limits: &RuleLimit,\n ) -> Option<ThunkNode> {\n match limits {\n Some(limit_set)\n if self.input.position_offset == offset && !limit_set.contains(&rule) =>\n {\n self.rule_answer_with_limits(rule, limits.clone().unwrap())\n }\n _ => self.rule_answer_without_limits(rule),\n }\n .map(|answer| ThunkNode {\n thunks: answer.borrow().thunks.clone(),\n value: parent.value_ref(value_index),\n })\n }\n\n fn call_rule(\n &mut self,\n rule: Rule,\n offset: usize,\n mut limits: RuleLimit,\n ) -> Option<ThunkChunk> {\n if let Some(ref mut limits) = limits {\n limits.insert(rule);\n }\n match rule {\n".freeze
|
520
515
|
|
521
516
|
@root.rules.each do |rule|
|
522
517
|
erbout << " Rule::#{Packcr.camelize(rule.name)} => self.evaluate_rule_#{rule.name}(offset, limits),\n".freeze
|
523
518
|
end
|
524
|
-
erbout << " }\n }\n
|
519
|
+
erbout << " }\n }\n".freeze
|
525
520
|
|
526
521
|
@root.rules.each do |rule|
|
527
522
|
erbout << "\n".freeze
|
@@ -541,7 +536,7 @@ class Packcr
|
|
541
536
|
|
542
537
|
@root.rules.each do |rule|
|
543
538
|
rule.codes.each do |code|
|
544
|
-
erbout << "\n #[allow(unused_variables,non_snake_case)]\n fn action_#{rule.name}_#{code.index}(&self, leaf: &ThunkLeaf, out: &mut i32) {\n".freeze
|
539
|
+
erbout << "\n #[allow(unused_variables, non_snake_case)]\n fn action_#{rule.name}_#{code.index}(&self, leaf: &ThunkLeaf, out: &mut i32) {\n".freeze
|
545
540
|
|
546
541
|
code.vars.each_with_index do |ref, i|
|
547
542
|
if i == 0
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class ActionNode
|
4
|
-
def get_code(gen, onfail, indent,
|
4
|
+
def get_code(gen, onfail, indent, unwrap, oncut)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -55,17 +55,15 @@ class Packcr
|
|
55
55
|
erbout
|
56
56
|
when :rs
|
57
57
|
erbout = +""
|
58
|
-
erbout << "answer.push_leaf(
|
59
|
-
|
58
|
+
erbout << "answer.push_leaf(Action::#{Packcr.camelize(gen.rule.name)}#{index}, self.input.position_offset, &[".freeze
|
60
59
|
vars.each_with_index do |var, i|
|
61
60
|
erbout << "#{", " if i > 0}#{var.index}".freeze
|
62
61
|
end
|
63
|
-
erbout << "]
|
64
|
-
|
62
|
+
erbout << "], &[".freeze
|
65
63
|
capts.each_with_index do |capt, i|
|
66
64
|
erbout << "#{", " if i > 0}#{capt.index}".freeze
|
67
65
|
end
|
68
|
-
erbout << "]
|
66
|
+
erbout << "]);\n".freeze
|
69
67
|
|
70
68
|
erbout
|
71
69
|
else
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class AlternateNode
|
4
|
-
def get_code(gen, onfail, indent,
|
4
|
+
def get_code(gen, onfail, indent, unwrap, oncut)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -92,47 +92,41 @@ class Packcr
|
|
92
92
|
when :rs
|
93
93
|
erbout = +""
|
94
94
|
m = gen.next_label
|
95
|
-
erbout << "
|
95
|
+
erbout << "catch(#{m}, || {\n let p = self.input.position_offset;\n".freeze
|
96
96
|
|
97
97
|
if gen.location
|
98
98
|
erbout << " TODO\n".freeze
|
99
99
|
end
|
100
100
|
nodes.each_with_index do |expr, i|
|
101
|
-
erbout << " {\n".freeze
|
102
|
-
|
103
101
|
c = i + 1 < nodes.length
|
104
102
|
if expr.reversible?(gen)
|
105
103
|
|
106
|
-
erbout << "#{gen.generate_code(expr, m,
|
104
|
+
erbout << "#{gen.generate_code(expr, m, 4, false, reverse: true, oncut: onfail)}".freeze
|
107
105
|
else
|
108
106
|
l = gen.next_label
|
109
|
-
erbout << " 'L#{format("%04d", l)}: {\n".freeze
|
110
|
-
|
111
107
|
r = expr.reachability
|
112
|
-
|
113
|
-
erbout << "#{gen.generate_code(expr, l, 12, false, oncut: onfail)}".freeze
|
114
108
|
if r == Packcr::CODE_REACH__ALWAYS_SUCCEED
|
109
|
+
erbout << " catch(#{l}, || {\n#{gen.generate_code(expr, l, 8, false, oncut: onfail)}".freeze
|
115
110
|
if c
|
116
|
-
erbout << "
|
111
|
+
erbout << " // unreachable codes omitted\n".freeze
|
117
112
|
end
|
118
|
-
erbout << "
|
113
|
+
erbout << " NOP\n })?\n".freeze
|
119
114
|
|
120
115
|
break
|
121
|
-
|
122
|
-
erbout << "
|
116
|
+
else
|
117
|
+
erbout << " catch(#{l}, || {\n#{gen.generate_code(expr, l, 8, false, oncut: onfail)} throw(#{m})\n })?;\n".freeze
|
123
118
|
end
|
124
|
-
erbout << " }\n".freeze
|
125
119
|
end
|
126
|
-
erbout << "
|
120
|
+
erbout << " self.input.position_offset = p;\n".freeze
|
127
121
|
|
128
122
|
if gen.location
|
129
123
|
erbout << " TODO\n".freeze
|
130
124
|
end
|
131
125
|
next if c
|
132
126
|
|
133
|
-
erbout << "
|
127
|
+
erbout << " throw(#{onfail})\n".freeze
|
134
128
|
end
|
135
|
-
erbout << "}
|
129
|
+
erbout << "})?;\n".freeze
|
136
130
|
|
137
131
|
erbout
|
138
132
|
else
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class CharclassNode
|
4
|
-
def get_code(gen, onfail, indent,
|
4
|
+
def get_code(gen, onfail, indent, unwrap, charclass, n, a)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -97,7 +97,7 @@ class Packcr
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
def get_any_code(gen, onfail, indent,
|
100
|
+
def get_any_code(gen, onfail, indent, unwrap, charclass)
|
101
101
|
case gen.lang
|
102
102
|
when :c
|
103
103
|
erbout = +""
|
@@ -124,7 +124,7 @@ class Packcr
|
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
def get_fail_code(gen, onfail, indent,
|
127
|
+
def get_fail_code(gen, onfail, indent, unwrap)
|
128
128
|
case gen.lang
|
129
129
|
when :c
|
130
130
|
erbout = +""
|
@@ -141,7 +141,7 @@ class Packcr
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
-
def get_one_code(gen, onfail, indent,
|
144
|
+
def get_one_code(gen, onfail, indent, unwrap, charclass, n, a)
|
145
145
|
case gen.lang
|
146
146
|
when :c
|
147
147
|
erbout = +""
|
@@ -176,7 +176,7 @@ class Packcr
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
-
def get_utf8_code(gen, onfail, indent,
|
179
|
+
def get_utf8_code(gen, onfail, indent, unwrap, charclass, n)
|
180
180
|
case gen.lang
|
181
181
|
when :c
|
182
182
|
erbout = +""
|
@@ -308,7 +308,7 @@ class Packcr
|
|
308
308
|
a = charclass && charclass[0] == "^"
|
309
309
|
i = a ? 1 : 0
|
310
310
|
any_code = !charclass || (a && n == 1)
|
311
|
-
erbout << "let (#{any_code ? "_" : ""}u, n) = self.get_char_as_utf32();\nif n == 0 {\n
|
311
|
+
erbout << "let (#{any_code ? "_" : ""}u, n) = self.input.get_char_as_utf32();\nif n == 0 {\n return throw(#{onfail});\n}\n".freeze
|
312
312
|
|
313
313
|
unless any_code
|
314
314
|
erbout << "if ".freeze
|
@@ -353,7 +353,7 @@ class Packcr
|
|
353
353
|
erbout << ") ".freeze
|
354
354
|
end
|
355
355
|
|
356
|
-
erbout << "{\n
|
356
|
+
erbout << "{\n return throw(#{onfail});\n}\n".freeze
|
357
357
|
end
|
358
358
|
erbout << "self.input.position_offset += n;\n".freeze
|
359
359
|
|
@@ -363,7 +363,7 @@ class Packcr
|
|
363
363
|
end
|
364
364
|
end
|
365
365
|
|
366
|
-
def get_utf8_reverse_code(gen, onsuccess, indent,
|
366
|
+
def get_utf8_reverse_code(gen, onsuccess, indent, unwrap, charclass, n)
|
367
367
|
case gen.lang
|
368
368
|
when :rb
|
369
369
|
erbout = +""
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class PredicateNode
|
4
|
-
def get_code(gen, onfail, indent,
|
4
|
+
def get_code(gen, onfail, indent, unwrap, oncut)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -77,7 +77,7 @@ class Packcr
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
def get_neg_code(gen, onfail, indent,
|
80
|
+
def get_neg_code(gen, onfail, indent, unwrap, oncut)
|
81
81
|
case gen.lang
|
82
82
|
when :c
|
83
83
|
erbout = +""
|
@@ -144,17 +144,19 @@ class Packcr
|
|
144
144
|
if gen.location
|
145
145
|
erbout << "TODO\n".freeze
|
146
146
|
end
|
147
|
-
erbout << "
|
148
|
-
|
149
|
-
|
147
|
+
erbout << "catch(#{l}, || {\n#{gen.generate_code(expr, l, 4, false)}".freeze
|
148
|
+
if r == Packcr::CODE_REACH__ALWAYS_FAIL
|
149
|
+
erbout << " NOP\n".freeze
|
150
|
+
else
|
150
151
|
erbout << " self.input.position_offset = p;\n".freeze
|
151
152
|
|
152
153
|
if gen.location
|
153
154
|
erbout << " TODO\n".freeze
|
154
155
|
end
|
155
|
-
erbout << "
|
156
|
+
erbout << " throw(#{onfail})\n".freeze
|
157
|
+
|
156
158
|
end
|
157
|
-
erbout << "}
|
159
|
+
erbout << "})?;\n".freeze
|
158
160
|
|
159
161
|
if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
|
160
162
|
erbout << "self.input.position_offset = p;\n".freeze
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class QuantityNode
|
4
|
-
def get_many_code(gen, onfail, indent,
|
4
|
+
def get_many_code(gen, onfail, indent, unwrap, oncut)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -120,32 +120,32 @@ class Packcr
|
|
120
120
|
erbout << "let mut i = -1;\n".freeze
|
121
121
|
end
|
122
122
|
m = gen.next_label
|
123
|
-
erbout << "
|
123
|
+
erbout << "catch(#{m}, || {\n loop {\n".freeze
|
124
124
|
|
125
125
|
if use_count
|
126
|
-
erbout << "
|
126
|
+
erbout << " i += 1;\n".freeze
|
127
127
|
end
|
128
128
|
if max >= 0
|
129
|
-
erbout << "
|
129
|
+
erbout << " if i >= #{max} {\n return NOP;\n }\n".freeze
|
130
130
|
end
|
131
|
-
erbout << "
|
131
|
+
erbout << " let p = self.input.position_offset;\n".freeze
|
132
132
|
|
133
133
|
if (r != Packcr::CODE_REACH__ALWAYS_SUCCEED) && gen.location
|
134
|
-
erbout << "
|
134
|
+
erbout << " TODO\n".freeze
|
135
135
|
end
|
136
136
|
l = gen.next_label
|
137
137
|
r = expr.reachability
|
138
|
-
|
138
|
+
if r == Packcr::CODE_REACH__ALWAYS_SUCCEED
|
139
|
+
erbout << " TODO\n match (|| {\n#{gen.generate_code(expr, l, 12, false)} if self.input.position_offset == p {\n return throw(#{m});\n }\n })() {\n NOP => continue,\n Err(label) if label != #{l} => return throw(label),\n _ => {\n self.input.position_offset = p;\n".freeze
|
139
140
|
|
140
|
-
|
141
|
-
erbout << "
|
141
|
+
else
|
142
|
+
erbout << " match (|| {\n#{gen.generate_code(expr, l, 12, false)} if self.input.position_offset == p {\n return throw(#{m});\n }\n NOP\n })() {\n NOP => continue,\n Err(label) if label != #{l} => return throw(label),\n _ => {\n self.input.position_offset = p;\n".freeze
|
142
143
|
|
143
|
-
if gen.location
|
144
|
-
erbout << " TODO\n".freeze
|
145
|
-
end
|
146
|
-
erbout << " break 'L#{format("%04d", m)};\n".freeze
|
147
144
|
end
|
148
|
-
|
145
|
+
if gen.location
|
146
|
+
erbout << " TODO\n".freeze
|
147
|
+
end
|
148
|
+
erbout << " return throw(#{m});\n }\n }\n }\n})?;\n".freeze
|
149
149
|
|
150
150
|
if min > 0
|
151
151
|
erbout << "if i < #{min} {\n self.input.position_offset = p0;\n".freeze
|
@@ -153,7 +153,7 @@ class Packcr
|
|
153
153
|
if gen.location
|
154
154
|
erbout << " TODO\n".freeze
|
155
155
|
end
|
156
|
-
erbout << "
|
156
|
+
erbout << " return throw(#{onfail});\n}\n".freeze
|
157
157
|
end
|
158
158
|
erbout
|
159
159
|
else
|
@@ -161,7 +161,7 @@ class Packcr
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
-
def get_one_code(gen, onfail, indent,
|
164
|
+
def get_one_code(gen, onfail, indent, unwrap, oncut)
|
165
165
|
case gen.lang
|
166
166
|
when :c
|
167
167
|
erbout = +""
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class ReferenceNode
|
4
|
-
def get_code(gen, onfail, indent,
|
4
|
+
def get_code(gen, onfail, indent, unwrap, oncut)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -39,7 +39,7 @@ class Packcr
|
|
39
39
|
erbout
|
40
40
|
when :rs
|
41
41
|
erbout = +""
|
42
|
-
erbout << "if !self.apply_rule(Rule::#{Packcr.camelize(name)}, &mut answer, #{index || 0}, offset, limits
|
42
|
+
erbout << "if !self.apply_rule(Rule::#{Packcr.camelize(name)}, &mut answer, #{index || 0}, offset, &limits) {\n return throw(#{onfail});\n}\n".freeze
|
43
43
|
|
44
44
|
erbout
|
45
45
|
else
|
@@ -47,7 +47,7 @@ class Packcr
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def get_reverse_code(gen, onsuccess, indent,
|
50
|
+
def get_reverse_code(gen, onsuccess, indent, unwrap, oncut)
|
51
51
|
case gen.lang
|
52
52
|
when :rb
|
53
53
|
erbout = +""
|
@@ -69,11 +69,6 @@ class Packcr
|
|
69
69
|
erbout << ", offset_loc".freeze
|
70
70
|
end
|
71
71
|
erbout << ")\n throw(#{onsuccess})\n end\nend\n".freeze
|
72
|
-
erbout
|
73
|
-
when :rs
|
74
|
-
erbout = +""
|
75
|
-
erbout << "/* lib/packcr/templates/node/reference_reverse.rs.erb */\n\n".freeze
|
76
|
-
|
77
72
|
erbout
|
78
73
|
else
|
79
74
|
raise "unknown lang #{gen.lang}"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class RuleNode
|
4
|
-
def get_code(gen, onfail, indent,
|
4
|
+
def get_code(gen, onfail, indent, unwrap, oncut)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -59,12 +59,13 @@ class Packcr
|
|
59
59
|
when :rs
|
60
60
|
erbout = +""
|
61
61
|
for_ref = has_ref ? "" : "_"
|
62
|
-
erbout << "#[allow(non_snake_case)]\nfn evaluate_rule_#{name}(
|
62
|
+
erbout << "#[allow(non_snake_case)]\nfn evaluate_rule_#{name}(&mut self, #{for_ref}offset: usize, ".freeze
|
63
63
|
|
64
64
|
if gen.location
|
65
65
|
erbout << " TODO\n".freeze
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
|
+
erbout << "#{for_ref}limits: RuleLimit) -> Option<ThunkChunk> {\n let mut answer = ThunkChunk::new(self.input.position_offset);\n".freeze
|
68
69
|
|
69
70
|
if gen.location
|
70
71
|
erbout << " TODO\n".freeze
|
@@ -76,11 +77,10 @@ class Packcr
|
|
76
77
|
end
|
77
78
|
r = expr.reachability
|
78
79
|
if r == Packcr::CODE_REACH__ALWAYS_SUCCEED
|
79
|
-
|
80
|
-
erbout << "#{gen.generate_code(expr, 0, 4, false)} self.level -= 1;\n return Some(answer);\n".freeze
|
80
|
+
erbout << " let _ = (|| {\n#{gen.generate_code(expr, 0, 8, false)} NOP\n })();\n self.level -= 1;\n Some(answer)\n".freeze
|
81
81
|
|
82
82
|
else
|
83
|
-
erbout << "
|
83
|
+
erbout << " match (|| {\n#{gen.generate_code(expr, 0, 8, false)} NOP\n })() {\n NOP => {\n self.level -= 1;\n Some(answer)\n }\n _ => {\n self.level -= 1;\n None\n }\n }\n".freeze
|
84
84
|
end
|
85
85
|
erbout << "}\n".freeze
|
86
86
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Packcr
|
2
2
|
class Node
|
3
3
|
class StringNode
|
4
|
-
def get_many_code(gen, onfail, indent,
|
4
|
+
def get_many_code(gen, onfail, indent, unwrap, oncut, n)
|
5
5
|
case gen.lang
|
6
6
|
when :c
|
7
7
|
erbout = +""
|
@@ -30,7 +30,7 @@ class Packcr
|
|
30
30
|
erbout
|
31
31
|
when :rs
|
32
32
|
erbout = +""
|
33
|
-
erbout << "if self.refill_buffer(#{n}) < #{n}\n
|
33
|
+
erbout << "if self.input.refill_buffer(#{n}) < #{n}\n || !self.input.buffer[self.input.position_offset..] .starts_with(\"#{value[0, n].each_char.map { |c| "#{Packcr.escape_character(c)}" }.join}\")\n{\n return throw(#{onfail});\n}\n".freeze
|
34
34
|
|
35
35
|
if gen.location
|
36
36
|
erbout << "TODO\n".freeze
|
@@ -43,7 +43,19 @@ class Packcr
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
46
|
+
def get_many_reverse_code(gen, onsuccess, indent, unwrap, oncut, n)
|
47
|
+
case gen.lang
|
48
|
+
when :rs
|
49
|
+
erbout = +""
|
50
|
+
erbout << "if self.input.refill_buffer(#{n}) >= #{n}\n && self.input.buffer[self.input.position_offset..].starts_with(\"#{value[0, n].each_char.map { |c| "#{Packcr.escape_character(c)}" }.join}\")\n{\n self.input.position_offset += #{n};\n return throw(#{onsuccess});\n}\n".freeze
|
51
|
+
|
52
|
+
erbout
|
53
|
+
else
|
54
|
+
raise "unknown lang #{gen.lang}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_one_code(gen, onfail, indent, unwrap, oncut, n)
|
47
59
|
case gen.lang
|
48
60
|
when :c
|
49
61
|
erbout = +""
|
@@ -67,7 +79,7 @@ class Packcr
|
|
67
79
|
erbout
|
68
80
|
when :rs
|
69
81
|
erbout = +""
|
70
|
-
erbout << "if self.refill_buffer(1) < 1\n || self.input.buffer
|
82
|
+
erbout << "if self.input.refill_buffer(1) < 1\n || !self.input.buffer[self.input.position_offset..].starts_with(\"#{Packcr.escape_character(value[0])}\")\n{\n return throw(#{onfail});\n}\n".freeze
|
71
83
|
|
72
84
|
if gen.location
|
73
85
|
erbout << "TODO\n".freeze
|
@@ -79,6 +91,18 @@ class Packcr
|
|
79
91
|
raise "unknown lang #{gen.lang}"
|
80
92
|
end
|
81
93
|
end
|
94
|
+
|
95
|
+
def get_one_reverse_code(gen, onsuccess, indent, unwrap, oncut, n)
|
96
|
+
case gen.lang
|
97
|
+
when :rs
|
98
|
+
erbout = +""
|
99
|
+
erbout << "if self.input.refill_buffer(1) >= 1\n && self.input.buffer[self.input.position_offset..].starts_with(\"#{Packcr.escape_character(value[0])}\")\n{\n self.input.position_offset += 1;\n return throw(#{onsuccess});\n}\n".freeze
|
100
|
+
|
101
|
+
erbout
|
102
|
+
else
|
103
|
+
raise "unknown lang #{gen.lang}"
|
104
|
+
end
|
105
|
+
end
|
82
106
|
end
|
83
107
|
end
|
84
108
|
end
|
data/lib/packcr/generator.rb
CHANGED
@@ -15,16 +15,17 @@ class Packcr
|
|
15
15
|
@label += 1
|
16
16
|
end
|
17
17
|
|
18
|
-
def generate_code(node, onescape, indent,
|
18
|
+
def generate_code(node, onescape, indent, unwrap, reverse: false, oncut: nil)
|
19
19
|
stream = @stream
|
20
20
|
@stream = +""
|
21
21
|
@level += 1
|
22
22
|
begin
|
23
23
|
if reverse
|
24
|
-
node.generate_reverse_code(self, onescape, indent,
|
24
|
+
code = node.generate_reverse_code(self, onescape, indent, unwrap, oncut: oncut)
|
25
25
|
else
|
26
|
-
node.generate_code(self, onescape, indent,
|
26
|
+
code = node.generate_code(self, onescape, indent, unwrap, oncut: oncut)
|
27
27
|
end
|
28
|
+
write Packcr.format_code(code, indent: indent, unwrap: unwrap)
|
28
29
|
@stream
|
29
30
|
ensure
|
30
31
|
@level -= 1
|