Skip to content
This repository has been archived by the owner on Apr 21, 2023. It is now read-only.

AST & Parser #5

Draft
wants to merge 40 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
10d819b
dep: make parser depend on AST
JarvisCraft Aug 13, 2020
3c3a8e5
feat(parser): implement parsing of integral types
JarvisCraft Aug 14, 2020
ec1c70d
test(parser): cover `int_number` rule
JarvisCraft Aug 14, 2020
c673ea6
refactor(parser): move similar number sub-rules to separate rules
JarvisCraft Aug 15, 2020
ba5c974
refactor(parser): remove redundant imports
JarvisCraft Aug 15, 2020
4ed2753
refactor(parser): make numeric parsing a bit more flexible
JarvisCraft Aug 15, 2020
d796ac8
refactor(parser): parse numbers to Option's
JarvisCraft Aug 15, 2020
db8c6a9
fix(parser): allow upper-case integer prefixes
JarvisCraft Aug 15, 2020
b164c0e
feat(parser): implement rule for double numbers
JarvisCraft Aug 17, 2020
ac217eb
feat(parser): implement rule for float numbers
JarvisCraft Aug 17, 2020
561b96c
fix(parser): long number parsing
JarvisCraft Aug 17, 2020
2a7f5d9
fix(parser): floating-point number parsing
JarvisCraft Aug 17, 2020
0889df6
refactor(parser): move similar floating point number sub-rules to sep…
JarvisCraft Aug 17, 2020
459c270
chore(CI): add Travis config
JarvisCraft Aug 17, 2020
86a3e9b
Merge branch 'development' into ast-parsing
JarvisCraft Aug 18, 2020
3bb9a8d
feat(AST): add basic AST entries and type definitions
JarvisCraft Aug 18, 2020
c378385
style(AST): add blank line to end of ast.rs
JarvisCraft Aug 18, 2020
c074cce
feat(AST): add missing literal types
JarvisCraft Aug 18, 2020
3f96a9b
fix(AST): set correct Rust type for Java's `long`
JarvisCraft Aug 18, 2020
0bfc5a2
fix(AST): make Java type definitions public
JarvisCraft Aug 18, 2020
f061ef3
feat(parser): add rules for parsing literals
JarvisCraft Aug 18, 2020
8d10be1
feat(parser): implement rules for `char`s
JarvisCraft Aug 18, 2020
6a81fd0
style(parser): resolve rustfmt issue with method chaining in parser.rs
JarvisCraft Aug 18, 2020
7187c72
Merge branch 'development' into ast-parsing
JarvisCraft Oct 8, 2020
819c5ac
feat(parser): move ParseError into a separate module reworking floats…
JarvisCraft Oct 26, 2020
3d922c0
feat(ast): derive `Debug` and `PartialEq` for Literal
JarvisCraft Oct 26, 2020
d4290bb
feat(ast): add `Identifier` Expression and `Keyword`
JarvisCraft Oct 26, 2020
8f8ba57
feat(ast): derive `Debug` and `PartialEq` for Expression
JarvisCraft Oct 26, 2020
f83b6fd
feat(parser): support identifiers and keywords
JarvisCraft Oct 26, 2020
a564b3f
feat(ast): utilize `Keyword` as a type of `Expression`
JarvisCraft Oct 26, 2020
4978d37
feat(parser): make pub rules return `Expression`s also refactoring re…
JarvisCraft Oct 26, 2020
716983f
Merge branch 'development' into ast-parsing
JarvisCraft Oct 26, 2020
6c342df
feat(ast): add `Comment` Expression
JarvisCraft Oct 26, 2020
d4f975b
feat(parser): support comments
JarvisCraft Oct 26, 2020
3fc0411
build(deps): add num-traits to `parser`
JarvisCraft Oct 27, 2020
751ffa5
chore(parser): rework error handling to omit nesting of Results
JarvisCraft Oct 27, 2020
1efdb21
chore(parser): cleanup pub's in java grammar
JarvisCraft Oct 27, 2020
5dbde62
style(parser): cleanup whitespaces of `java::keyword`
JarvisCraft Oct 27, 2020
d79ef8a
refactor(parser): split `parser.rs` into multiple files
JarvisCraft Oct 27, 2020
f50c36b
feat(parser): implement string literal parsing
JarvisCraft Dec 21, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

173 changes: 173 additions & 0 deletions javac-rs-ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/// Java `boolean` type
pub type Boolean = bool;
/// Java `byte` type
pub type Byte = i8;
/// Java `short` type
pub type Short = i16;
/// Java `char` type
pub type Char = u16;
/// Java `int` type
pub type Int = i32;
/// Java `long` type
pub type Long = i64;
/// Java `float` type
pub type Float = f32;
/// Java `double` type
pub type Double = f64;

/// Type used for storing raw identifiers
pub type IdentifierName = String;

/// Type used for storing raw comment body
pub type CommentBody = String;

/// Type used for storing raw string literal body
pub type StringLiteralValue = String;

/// Java [literal](https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10)
#[derive(Debug, PartialEq)]
pub enum Literal {
/// Literal of `int` type
Int(Int),
/// Literal of `long` type
Long(Long),
/// Literal of `float` type
Float(Float),
/// Literal of `double` type
Double(Double),
/// Literal of `boolean` type
Boolean(Boolean),
/// Literal of `char` type
Char(Char),
/// Literal of `java.lang.String` type
String(StringLiteralValue),
/// `null` literal
Null,
}

#[derive(Debug, PartialEq)]
pub enum Keyword {
//<editor-fold desc="List of keywords" defaultstate="collapsed">
Abstract,
Assert,
Boolean,
Break,
Byte,
Case,
Catch,
Char,
Class,
Const,
Continue,
Default,
Do,
Double,
Else,
Enum,
Extends,
Final,
Finally,
Float,
For,
Goto,
If,
Implements,
Import,
Instanceof,
Int,
Interface,
Long,
Native,
New,
Package,
Private,
Protected,
Public,
Return,
Short,
Static,
Strictfp,
Super,
Switch,
Synchronized,
This,
Throw,
Throws,
Transient,
Try,
Void,
Volatile,
While,
//</editor-fold>
}

impl Keyword {
/// Checks if this keyword represents a (primitive) type.
///
/// # Examples
///
/// ```
/// use javac_rs_ast::ast::Keyword;
///
/// assert!(Keyword::Byte.is_type());
/// assert!(!Keyword::Private.is_type());
/// assert!(!Keyword::Synchronized.is_type());
/// ```
pub fn is_type(&self) -> bool {
matches!(
self,
Self::Boolean
| Self::Byte
| Self::Char
| Self::Double
| Self::Float
| Self::Int
| Self::Long
| Self::Short
)
}

/// Checks if this keyword represents an access modifier.
///
/// # Examples
///
/// ```
/// use javac_rs_ast::ast::Keyword;
///
/// assert!(Keyword::Public.is_access_modifier());
/// assert!(!Keyword::Package.is_access_modifier());
/// assert!(!Keyword::Continue.is_access_modifier());
/// ```
pub fn is_access_modifier(&self) -> bool {
matches!(self, Self::Private | Self::Protected | Self::Public)
}

/// Checks if this keyword represents an unused keyword.
///
/// # Examples
///
/// ```
/// use javac_rs_ast::ast::Keyword;
///
/// assert!(Keyword::Const.is_unused());
/// assert!(Keyword::Goto.is_unused());
/// assert!(!Keyword::Abstract.is_unused());
/// assert!(!Keyword::Case.is_unused());
/// ```
pub fn is_unused(&self) -> bool {
matches!(self, Self::Const | Self::Goto)
}
}

/// A Java expression in source code AST
#[derive(Debug, PartialEq)]
pub enum Expression {
/// Keyword expression
Keyword(Keyword),
/// Literal expression
Literal(Literal),
/// Identifier expression
Identifier(IdentifierName),
/// Comment expression
Comment(CommentBody),
}
9 changes: 1 addition & 8 deletions javac-rs-ast/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//! Elements of Java language AST (Abstract Syntax Tree)

#[allow(clippy::panic)]
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
pub mod ast;
2 changes: 2 additions & 0 deletions javac-rs-parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ authors = ["progrm_jarvis <[email protected]>"]
edition = "2018"

[dependencies]
javac-rs-ast = { path = "../javac-rs-ast" }
peg = "0.6.3"
num-traits = "0.2.12"
11 changes: 3 additions & 8 deletions javac-rs-parser/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
//! Utilities for parsing Java language AST (Abstract Syntax Tree)

#[allow(clippy::panic)]
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
mod parser;

pub use parser::*;
90 changes: 90 additions & 0 deletions javac-rs-parser/src/parser/literals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use num_traits::Num;
use std::num::{ParseFloatError, ParseIntError};
use std::str::FromStr;

pub trait PrimitiveFrom<T> {
fn from(source: T) -> Self;
}

impl PrimitiveFrom<u32> for i32 {
fn from(source: u32) -> Self {
source as Self
}
}

impl PrimitiveFrom<u64> for i64 {
fn from(source: u64) -> Self {
source as Self
}
}

pub trait IntoStaticStr {
fn into_static_str(self) -> &'static str;
}

impl IntoStaticStr for ParseIntError {
fn into_static_str(self) -> &'static str {
"integer literal cannot be parsed"
}
}

impl IntoStaticStr for ParseFloatError {
fn into_static_str(self) -> &'static str {
"floating point literal cannot be parsed"
}
}

pub fn parse_integer_number<F: Num, T: Num + PrimitiveFrom<F>>(
digits: &str,
radix: u32,
) -> Result<T, &'static str>
where
<F as Num>::FromStrRadixErr: IntoStaticStr,
{
F::from_str_radix(digits.replace('_', "").as_str(), radix)
.map(|value| T::from(value))
.map_err(|error| error.into_static_str())
}

pub fn parse_number_i32(digits: &str, radix: u32) -> Result<i32, &'static str> {
parse_integer_number::<u32, i32>(digits, radix)
}

pub fn parse_number_i64(digits: &str, radix: u32) -> Result<i64, &'static str> {
parse_integer_number::<u64, i64>(digits, radix)
}

pub fn parse_floating_point_number<T: FromStr>(digits: &str) -> Result<T, &'static str>
where
T::Err: IntoStaticStr,
{
digits
.replace('_', "")
.parse::<T>()
.map_err(|error| error.into_static_str())
}

pub fn parse_from_parts<T: FromStr>(
integer_digits: Option<&str>,
decimal_digits: Option<&str>,
exponent_digits: Option<&str>,
radix: u32,
) -> Result<T, &'static str>
where
T::Err: IntoStaticStr,
{
format!(
"{}.{}e{}",
integer_digits
.map_or(Ok(0), |digits| i64::from_str_radix(digits, radix))
.map_err(|error| error.into_static_str())?,
decimal_digits
.map_or(Ok(0), |digits| i64::from_str_radix(digits, radix))
.map_err(|error| error.into_static_str())?,
exponent_digits
.map_or(Ok(0), |digits| i64::from_str_radix(digits, radix))
.map_err(|error| error.into_static_str())?
)
.parse::<T>()
.map_err(|error| error.into_static_str())
}
Loading