add: integer_node_parser
This commit is contained in:
parent
58e1e9c62c
commit
e51d02dd6f
|
@ -1 +1,2 @@
|
||||||
pub mod tokenizer;
|
pub mod tokenizer;
|
||||||
|
pub mod parser;
|
3
src/parser.rs
Normal file
3
src/parser.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
mod syntax_tree;
|
||||||
|
mod grammar_parser;
|
||||||
|
|
32
src/parser/grammar_parser.rs
Normal file
32
src/parser/grammar_parser.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
use crate::parser::syntax_tree::SyntaxNode;
|
||||||
|
use crate::tokenizer::{LexicalTokenSpan, LexicalTokenType};
|
||||||
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::combinator::map;
|
||||||
|
use nom::{IResult};
|
||||||
|
|
||||||
|
fn integer_node_parser(input: LexicalTokenSpan) -> IResult<LexicalTokenSpan, SyntaxNode> {
|
||||||
|
map(tag(LexicalTokenType::ConstInteger(0)),
|
||||||
|
|t: LexicalTokenSpan| {
|
||||||
|
if let LexicalTokenType::ConstInteger(number) = t.span[0].token_type {
|
||||||
|
SyntaxNode::const_integer(number, t)
|
||||||
|
} else {
|
||||||
|
panic!("Illegal integer constant: {}", t.as_str())
|
||||||
|
}
|
||||||
|
})(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::parser::syntax_tree::SyntaxNodeType;
|
||||||
|
use crate::tokenizer::lexical_parser;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn number_parser_test() {
|
||||||
|
let (_, input) = lexical_parser("123").unwrap();
|
||||||
|
dbg!(&input);
|
||||||
|
let (_, node) = integer_node_parser((&input).into()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(SyntaxNodeType::ConstIntegerNode(123), node.node_type);
|
||||||
|
}
|
||||||
|
}
|
22
src/parser/syntax_tree.rs
Normal file
22
src/parser/syntax_tree.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use crate::tokenizer::LexicalTokenSpan;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
pub enum SyntaxNodeType {
|
||||||
|
ConstIntegerNode(u32),
|
||||||
|
ConstFloatNode(f32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
pub struct SyntaxNode<'a> {
|
||||||
|
pub node_type: SyntaxNodeType,
|
||||||
|
pub lexical_tokens: LexicalTokenSpan<'a>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SyntaxNode<'a> {
|
||||||
|
pub fn const_integer(number: u32, span: LexicalTokenSpan<'a>) -> Self {
|
||||||
|
SyntaxNode {
|
||||||
|
node_type: SyntaxNodeType::ConstIntegerNode(number),
|
||||||
|
lexical_tokens: span
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
use crate::tokenizer::parser::{combine_parser, junk_parser};
|
use crate::tokenizer::lexical_parser::{combine_parser, junk_parser};
|
||||||
|
|
||||||
mod parser;
|
mod lexical_parser;
|
||||||
|
mod lexical_token;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum LexicalTokenType {
|
pub enum LexicalTokenType {
|
||||||
Identifier,
|
Identifier,
|
||||||
ConstInteger(u32),
|
ConstInteger(u32),
|
||||||
|
@ -19,6 +20,11 @@ pub struct LexicalToken<'a> {
|
||||||
pub literal_value: &'a str,
|
pub literal_value: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
pub struct LexicalTokenSpan<'a> {
|
||||||
|
pub span: &'a [LexicalToken<'a>]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn lexical_parser(mut input: &str) -> IResult<&str, Vec<LexicalToken>> {
|
pub fn lexical_parser(mut input: &str) -> IResult<&str, Vec<LexicalToken>> {
|
||||||
let mut array = vec![];
|
let mut array = vec![];
|
||||||
|
|
||||||
|
|
143
src/tokenizer/lexical_token.rs
Normal file
143
src/tokenizer/lexical_token.rs
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
use crate::tokenizer::{LexicalToken, LexicalTokenSpan, LexicalTokenType};
|
||||||
|
use nom::{Compare, CompareResult, InputLength, InputTake};
|
||||||
|
|
||||||
|
impl<'a> LexicalTokenSpan<'a> {
|
||||||
|
pub fn new(span: &'a [LexicalToken]) -> Self {
|
||||||
|
Self {
|
||||||
|
span
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a [LexicalToken<'a>]> for LexicalTokenSpan<'a> {
|
||||||
|
fn from(value: &'a [LexicalToken<'a>]) -> Self {
|
||||||
|
LexicalTokenSpan::new(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Vec<LexicalToken<'a>>> for LexicalTokenSpan<'a> {
|
||||||
|
fn from(value: &'a Vec<LexicalToken<'a>>) -> Self {
|
||||||
|
LexicalTokenSpan::new(value.as_slice())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LexicalTokenSpan<'_> {
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
self.span[0].literal_value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for LexicalTokenType {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
match self {
|
||||||
|
LexicalTokenType::ConstInteger(_) => {
|
||||||
|
match other {
|
||||||
|
LexicalTokenType::ConstInteger(_) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LexicalTokenType::ConstFloat(_) => {
|
||||||
|
match other {
|
||||||
|
LexicalTokenType::ConstFloat(_) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LexicalTokenType::Keyword => {
|
||||||
|
match other {
|
||||||
|
LexicalTokenType::Keyword => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LexicalTokenType::Identifier => {
|
||||||
|
match other {
|
||||||
|
LexicalTokenType::Identifier => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LexicalTokenType::Delimiter => {
|
||||||
|
match other {
|
||||||
|
LexicalTokenType::Delimiter => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LexicalTokenType::Operator => {
|
||||||
|
match other {
|
||||||
|
LexicalTokenType::Operator => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputLength for LexicalTokenType {
|
||||||
|
fn input_len(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputLength for LexicalToken<'_> {
|
||||||
|
fn input_len(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Compare<LexicalTokenType> for LexicalTokenSpan<'_> {
|
||||||
|
fn compare(&self, t: LexicalTokenType) -> CompareResult {
|
||||||
|
if self.span.is_empty() {
|
||||||
|
CompareResult::Incomplete
|
||||||
|
} else if self.span[0].token_type == t {
|
||||||
|
CompareResult::Ok
|
||||||
|
} else {
|
||||||
|
CompareResult::Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_no_case(&self, t: LexicalTokenType) -> CompareResult {
|
||||||
|
self.compare(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Compare<LexicalToken<'a>> for LexicalTokenSpan<'a> {
|
||||||
|
fn compare(&self, t: LexicalToken) -> CompareResult {
|
||||||
|
if self.span.is_empty() {
|
||||||
|
CompareResult::Incomplete
|
||||||
|
} else if self.span[0] == t {
|
||||||
|
CompareResult::Ok
|
||||||
|
} else {
|
||||||
|
CompareResult::Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_no_case(&self, t: LexicalToken) -> CompareResult {
|
||||||
|
self.compare(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputTake for LexicalTokenSpan<'_> {
|
||||||
|
fn take(&self, count: usize) -> Self {
|
||||||
|
LexicalTokenSpan::new(&self.span[..count])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_split(&self, count: usize) -> (Self, Self) {
|
||||||
|
let (prefix, suffix) = self.span.split_at(count);
|
||||||
|
// 先返回suffix,再返回prefix
|
||||||
|
// 这TM谁能第一次写对
|
||||||
|
(LexicalTokenSpan::new(suffix), LexicalTokenSpan::new(prefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lexical_token_type_test() {
|
||||||
|
assert_eq!(LexicalTokenType::Identifier, LexicalTokenType::Identifier);
|
||||||
|
assert_eq!(LexicalTokenType::ConstInteger(1), LexicalTokenType::ConstInteger(2));
|
||||||
|
assert_eq!(LexicalTokenType::ConstFloat(3.0), LexicalTokenType::ConstFloat(3.0));
|
||||||
|
|
||||||
|
assert_ne!(LexicalTokenType::Identifier, LexicalTokenType::Keyword);
|
||||||
|
assert_ne!(LexicalTokenType::ConstInteger(1), LexicalTokenType::Operator);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,10 +14,12 @@ fn validate_tokens(input: &'static str, tokens: Vec<LexicalTokenType>) {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn main_test() {
|
fn main_test() {
|
||||||
validate_tokens("int main { return 0; }", vec![
|
validate_tokens("int main() { return 0; }", vec![
|
||||||
Keyword,
|
Keyword,
|
||||||
Identifier,
|
Identifier,
|
||||||
Delimiter,
|
Delimiter,
|
||||||
|
Delimiter,
|
||||||
|
Delimiter,
|
||||||
Keyword,
|
Keyword,
|
||||||
ConstInteger(0),
|
ConstInteger(0),
|
||||||
Delimiter,
|
Delimiter,
|
||||||
|
@ -25,6 +27,13 @@ fn main_test() {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn number_test() {
|
||||||
|
validate_tokens("123", vec![
|
||||||
|
ConstInteger(123)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hexadecimal_test() {
|
fn hexadecimal_test() {
|
||||||
validate_tokens("// test hexadecimal define
|
validate_tokens("// test hexadecimal define
|
||||||
|
|
Loading…
Reference in New Issue
Block a user