forked from UnBCIC-TP2/r-python
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathparser_common.rs
More file actions
121 lines (103 loc) · 3.82 KB
/
parser_common.rs
File metadata and controls
121 lines (103 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{alpha1, multispace0},
combinator::{not, peek, recognize},
multi::many0,
sequence::{delimited, terminated},
IResult,
};
use crate::parser::keywords::KEYWORDS;
// Type name constants
pub const INT_TYPE: &str = "Int";
pub const REAL_TYPE: &str = "Real";
pub const BOOLEAN_TYPE: &str = "Boolean";
pub const STRING_TYPE: &str = "String";
pub const UNIT_TYPE: &str = "Unit";
pub const ANY_TYPE: &str = "Any";
// Special type constructor constants
pub const MAYBE_TYPE: &str = "Maybe";
pub const RESULT_TYPE: &str = "Result";
// Keyword constants
pub const DATA_KEYWORD: &str = "data";
pub const END_KEYWORD: &str = "end";
// Statement keyword constants
pub const IF_KEYWORD: &str = "if";
pub const ELIF_KEYWORD: &str = "elif";
pub const ELSE_KEYWORD: &str = "else";
pub const WHILE_KEYWORD: &str = "while";
pub const FOR_KEYWORD: &str = "for";
pub const IN_KEYWORD: &str = "in";
pub const ASSERT_KEYWORD: &str = "assert";
pub const ASSERTEQ_KEYWORD: &str = "asserteq";
pub const ASSERTNEQ_KEYWORD: &str = "assertneq";
pub const ASSERTTRUE_KEYWORD: &str = "asserttrue";
pub const ASSERTFALSE_KEYWORD: &str = "assertfalse";
pub const VAR_KEYWORD: &str = "var";
pub const VAL_KEYWORD: &str = "val";
pub const DEF_KEYWORD: &str = "def";
pub const TEST_KEYWORD: &str = "test";
// Operator and symbol constants
pub const FUNCTION_ARROW: &str = "->";
pub const PIPE_SYMBOL: &str = "|";
pub const COLON_SYMBOL: &str = ":";
pub const COMMA_SYMBOL: &str = ",";
pub const SEMICOLON_SYMBOL: &str = ";";
// Bracket and parentheses constants
pub const LEFT_BRACKET: char = '[';
pub const RIGHT_BRACKET: char = ']';
pub const LEFT_PAREN: char = '(';
pub const RIGHT_PAREN: char = ')';
// Other character constants
pub const COMMA_CHAR: char = ',';
pub const COLON_CHAR: char = ':';
pub const PIPE_CHAR: char = '|';
pub const SEMICOLON_CHAR: char = ';';
pub const EQUALS_CHAR: char = '=';
/// Accepts any character except '"' and control characters (like \n, \t)
pub fn is_string_char(c: char) -> bool {
c != '"' && !c.is_control()
}
pub fn separator<'a>(sep: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str> {
delimited(multispace0, tag(sep), multispace0)
}
/// Parses a reserved keyword (e.g., "if") surrounded by optional spaces
/// A implementação da função keyword foi alterada para que seja garantida que a keyword seja uma palavra completa e seja separada por um espaço
pub fn keyword<'a>(kw: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str> {
delimited(
multispace0,
terminated(
tag(kw),
// Ensure the keyword is not followed by an identifier character (letter, digit, or underscore)
peek(not(identifier_start_or_continue)),
),
multispace0,
)
}
/// Parsers for identifiers.
pub fn identifier(input: &str) -> IResult<&str, &str> {
let (input, _) = multispace0(input)?;
let (input, first_char) = identifier_start(input)?;
let (input, rest) = identifier_continue(input)?;
let ident = format!("{}{}", first_char, rest);
if KEYWORDS.contains(&ident.as_str()) {
Err(nom::Err::Error(nom::error::Error::new(
input,
nom::error::ErrorKind::Tag,
)))
} else {
Ok((input, Box::leak(ident.into_boxed_str())))
}
}
/// First character of an identifier: [a-zA-Z_]
fn identifier_start(input: &str) -> IResult<&str, &str> {
alt((alpha1, tag("_")))(input)
}
/// Remaining characters: [a-zA-Z0-9_]*
fn identifier_continue(input: &str) -> IResult<&str, &str> {
recognize(many0(identifier_start_or_continue))(input)
}
/// A single identifier character: alphanumeric or underscore
fn identifier_start_or_continue(input: &str) -> IResult<&str, &str> {
recognize(alt((alpha1, tag("_"), nom::character::complete::digit1)))(input)
}