Skip to content

Commit

Permalink
Merge pull request #6 from kbkpbot/master
Browse files Browse the repository at this point in the history
byte is deprecated, use u8 instead
  • Loading branch information
svelterust authored May 9, 2024
2 parents 195dac6 + 1d51741 commit f044714
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 50 deletions.
39 changes: 20 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,39 @@ It is written in V, hence the name.
[Hexadecimal color](https://developer.mozilla.org/en-US/docs/Web/CSS/color) parser:

```v
import strconv
module main
import vom { is_hex_digit, tag, take_while_m_n, tuple }
struct Color {
red byte
green byte
blue byte
red u8
green u8
blue u8
}
fn from_hex(input string) ?byte {
return byte(strconv.parse_uint(input, 16, 8) ?)
fn from_hex(input string) u8 {
return '0x${input}'.u8()
}
fn hex_primary(input string) ?(string, string) {
parser := take_while_m_n(2, 2, is_hex_digit)
return parser(input)
fn hex_primary(input string) !(string, string, int) {
parser := take_while_m_n(2, 2, is_hex_digit)
return parser(input)
}
fn hex_color(input string) ?(string, Color) {
discard := tag('#')
hex_part, _ := discard(input) ?
parser := tuple([hex_primary, hex_primary, hex_primary])
rest, output := parser(hex_part) ?
red, green, blue := from_hex(output[0]) ?, from_hex(output[1]) ?, from_hex(output[2]) ?
return rest, Color{red, green, blue}
fn hex_color(input string) !(string, Color) {
discard := tag('#')
hex_part, _, _ := discard(input)!
parser := tuple([hex_primary, hex_primary, hex_primary])
rest, output, _ := parser(hex_part)!
red, green, blue := from_hex(output[0]), from_hex(output[1]), from_hex(output[2])
return rest, Color{red, green, blue}
}
fn main() {
_, color := hex_color('#2F14DF') ?
assert color == Color{47, 20, 223}
_, color := hex_color('#2F14DF')!
assert color == Color{47, 20, 223}
println(color)
}
```

## When will it reach 1.0?
Expand Down
10 changes: 5 additions & 5 deletions bytes.v
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub fn take(n int) Fn {
}

// Returns the longest input slice (if any) till a predicate `condition` is met.
pub fn take_till(condition fn (byte) bool) Fn {
pub fn take_till(condition fn (u8) bool) Fn {
return fn [condition] (input string) !(string, string, int) {
for i, c in input.bytes() {
if condition(c) {
Expand All @@ -98,7 +98,7 @@ pub fn take_till(condition fn (byte) bool) Fn {
}

// Returns the longest (at least 1) input slice till a predicate `condition` is met.
pub fn take_till1(condition fn (byte) bool) Fn {
pub fn take_till1(condition fn (u8) bool) Fn {
return fn [condition] (input string) !(string, string, int) {
for i, c in input.bytes() {
if condition(c) && i > 0 {
Expand Down Expand Up @@ -134,7 +134,7 @@ pub fn take_until1(pattern string) Fn {
}

// Returns the longest input slice (if any) that matches the predicate `condition`.
pub fn take_while(condition fn (byte) bool) Fn {
pub fn take_while(condition fn (u8) bool) Fn {
return fn [condition] (input string) !(string, string, int) {
for i, c in input.bytes() {
if !condition(c) {
Expand All @@ -146,7 +146,7 @@ pub fn take_while(condition fn (byte) bool) Fn {
}

// Returns the longest (at least 1) input slice that matches the predicate `condition`.
pub fn take_while1(condition fn (byte) bool) Fn {
pub fn take_while1(condition fn (u8) bool) Fn {
return fn [condition] (input string) !(string, string, int) {
for i, c in input.bytes() {
if !condition(c) {
Expand All @@ -161,7 +161,7 @@ pub fn take_while1(condition fn (byte) bool) Fn {
}

// Returns the longest (m <= len <= n) input slice that matches the predicate `condition`.
pub fn take_while_m_n(m int, n int, condition fn (byte) bool) Fn {
pub fn take_while_m_n(m int, n int, condition fn (u8) bool) Fn {
return fn [m, n, condition] (input string) !(string, string, int) {
mut longest := -1
for i, c in input.bytes() {
Expand Down
4 changes: 2 additions & 2 deletions bytes_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn test_take() ! {
}

fn test_take_till() ! {
parser := take_till(fn (b byte) bool {
parser := take_till(fn (b u8) bool {
return b == `:`
})
rest, output, len := parser('latin:123')!
Expand All @@ -110,7 +110,7 @@ fn test_take_till() ! {
}

fn test_take_till1() ! {
parser := take_till1(fn (b byte) bool {
parser := take_till1(fn (b u8) bool {
return b == `:`
})
rest, output, len := parser(':latin:123')!
Expand Down
36 changes: 18 additions & 18 deletions character.v
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,38 @@ module vom

// Based on https://docs.rs/nom/7.1.3/nom/character/index.html

// Tests if byte is ASCII alphabetic: A-Z, a-z.
pub fn is_alphabetic(b byte) bool {
// Tests if u8 is ASCII alphabetic: A-Z, a-z.
pub fn is_alphabetic(b u8) bool {
return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.bytes().any(it == b)
}

// Tests if byte is ASCII alphanumeric: A-Z, a-z, 0-9.
pub fn is_alphanumeric(b byte) bool {
// Tests if u8 is ASCII alphanumeric: A-Z, a-z, 0-9.
pub fn is_alphanumeric(b u8) bool {
return is_alphabetic(b) || is_digit(b)
}

// Tests if byte is ASCII digit: 0-9.
pub fn is_digit(b byte) bool {
// Tests if u8 is ASCII digit: 0-9.
pub fn is_digit(b u8) bool {
return '0123456789'.bytes().any(it == b)
}

// Tests if byte is ASCII hex digit: 0-9, A-F, a-f.
pub fn is_hex_digit(b byte) bool {
// Tests if u8 is ASCII hex digit: 0-9, A-F, a-f.
pub fn is_hex_digit(b u8) bool {
return is_digit(b) || 'ABCDEF'.bytes().any(it == b) || 'abcdef'.bytes().any(it == b)
}

// Tests if byte is ASCII newline: \n.
pub fn is_newline(b byte) bool {
// Tests if u8 is ASCII newline: \n.
pub fn is_newline(b u8) bool {
return b == `\n`
}

// Tests if byte is ASCII octal digit: 0-7.
pub fn is_oct_digit(b byte) bool {
// Tests if u8 is ASCII octal digit: 0-7.
pub fn is_oct_digit(b u8) bool {
return '01234567'.bytes().any(it == b)
}

// Tests if byte is ASCII space or tab.
pub fn is_space(b byte) bool {
// Tests if u8 is ASCII space or tab.
pub fn is_space(b u8) bool {
return ' \t'.bytes().any(it == b)
}

Expand Down Expand Up @@ -107,15 +107,15 @@ pub fn line_ending(input string) !(string, string, int) {

// Recognizes zero or more spaces, tabs, carriage returns and line feeds.
pub fn multispace0(input string) !(string, string, int) {
parser := take_while(fn (b byte) bool {
parser := take_while(fn (b u8) bool {
return ' \t\n\r'.bytes().any(it == b)
})
return parser(input)
}

// Recognizes one or more spaces, tabs, carriage returns and line feeds.
pub fn multispace1(input string) !(string, string, int) {
parser := take_while1(fn (b byte) bool {
parser := take_while1(fn (b u8) bool {
return ' \t\n\r'.bytes().any(it == b)
})
return parser(input)
Expand Down Expand Up @@ -143,7 +143,7 @@ pub fn none_of(pattern string) Fn {

// Recognizes a string of any char except '\r\n' or '\n'.
pub fn not_line_ending(input string) !(string, string, int) {
parser := take_while(fn (b byte) bool {
parser := take_while(fn (b u8) bool {
return '\r\n'.bytes().all(it != b)
})
return parser(input)
Expand Down Expand Up @@ -176,7 +176,7 @@ pub fn one_of(pattern string) Fn {
}

// Recognizes one character and checks that it satisfies a predicate
pub fn satisfy(condition fn (byte) bool) Fn {
pub fn satisfy(condition fn (u8) bool) Fn {
return fn [condition] (input string) !(string, string, int) {
if input.len == 0 {
return error('`satisfy` failed because input is empty')
Expand Down
2 changes: 1 addition & 1 deletion character_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ fn test_one_of() ! {
}

fn test_satisfy() ! {
parser := satisfy(fn (b byte) bool {
parser := satisfy(fn (b u8) bool {
return b == `a` || b == `b`
})
rest, output, len := parser('abc')!
Expand Down
8 changes: 4 additions & 4 deletions examples/hexadecimal/hexadecimal.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ module main
import vom { is_hex_digit, tag, take_while_m_n, tuple }

struct Color {
red byte
green byte
blue byte
red u8
green u8
blue u8
}

fn from_hex(input string) byte {
fn from_hex(input string) u8 {
return '0x${input}'.u8()
}

Expand Down
2 changes: 1 addition & 1 deletion examples/lua/lua.v
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn keyword(input string, location Location) !(string, Token) {
}

fn identifier(input string, location Location) !(string, Token) {
rest, output := alphanumeric1(input)!
rest, output, _ := alphanumeric1(input)!
if is_digit(output[0]) {
return error('${output} starts with digit')
} else {
Expand Down
85 changes: 85 additions & 0 deletions regex.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module vom

// https://www.cnblogs.com/baiyuxuan/p/15430458.html
// 从字符串生成Regex

pub struct Regex {
expr string
mut: ind int
}

fn (r Regex) peek() char {
return expr[ind]
}

fn (r Regex) next() char {
c := expr[ind]
ind ++
return c
}

fn (r Regex) read(c char) ! {
if c != next() {
return error('expected: ${c}')
}
}

fn (r Regex) end() bool {
return ind == expr.len
}

fn (r Regex) parse() ! {
ind = 0
return parse_expr()
}

// elem = char | (expr)
fn (r Regex) parse_elem() ! {
if peek() == `(` {
next()
rr := parse_expr()
read(`)`)
return rr
} else if peek() == `.` {
next()
return any()
} else {
return ch(next())
}
}

// factor = elem* | elem+ | elem
fn (r Regex) parse_factor() ! {
mut r := parse_elem()
if !end() && peek() == `*` {
r = r.zeroOrMore()
next()
} else if !end() && peek() == `+` {
r = r.oneOrMore()
next()
}
return r
}

// term = factor factor ... factor
fn (r Regex) parse_term() ! {
mut r := parse_factor()
for !end() && peek() != ')' && peek() != '|' {
r = r.concat(parseFactor())
}
return r
}

// expr = term|term|...|term
fn (r Regex) parse_expr() ! {
mut r := parse_term()

for !end() && peek() == '|' {
next()
r = r.or(parse_term())
}
return r
}



10 changes: 10 additions & 0 deletions regex_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module vom

fn test_regex() ! {
parser := Regex{expr:'((a|b)c*)+'}
rest, output, len := parser('acc')
assert rest == ''
assert output == 'acc'
assert len == 3
}

0 comments on commit f044714

Please sign in to comment.