mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
examples: vfmt calculator.v
This commit is contained in:
parent
1c9e02094c
commit
bb60b4227e
@ -1,134 +1,135 @@
|
||||
// Q: What's this?
|
||||
// A: This is a mini "home-made" calculator. You may also regard it as a very elementary version of "interpreter".
|
||||
|
||||
import os
|
||||
|
||||
const (
|
||||
numeric_char = [`0`,`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`,`.`,`e`,`E`]
|
||||
)
|
||||
|
||||
// Convert expression to Reverse Polish Notation.
|
||||
fn expr_to_rev_pol(expr string) ?[]string {
|
||||
if expr == '' {
|
||||
return error('err: empty expression')
|
||||
}
|
||||
mut stack := []string{}
|
||||
mut rev_pol := []string{}
|
||||
mut pos := 0
|
||||
for pos<expr.len {
|
||||
mut end_pos := pos
|
||||
for end_pos<expr.len && expr[end_pos] in numeric_char {
|
||||
end_pos++
|
||||
}
|
||||
if end_pos>pos {
|
||||
stack << expr[pos..end_pos]
|
||||
pos = end_pos
|
||||
}
|
||||
else if end_pos==pos {
|
||||
op := expr[pos].str()
|
||||
match op {
|
||||
'(' {
|
||||
stack << op
|
||||
}
|
||||
'*', '/' {
|
||||
for stack.len>0 && stack.last() !in ['(', '+', '-'] {
|
||||
rev_pol << stack.last()
|
||||
stack.delete(stack.len-1)
|
||||
}
|
||||
stack << op
|
||||
}
|
||||
'+', '-' {
|
||||
for stack.len>0 && stack.last() != '(' {
|
||||
rev_pol << stack.last()
|
||||
stack.delete(stack.len-1)
|
||||
}
|
||||
stack << op
|
||||
}
|
||||
')' {
|
||||
for stack.len>0 && stack.last() != '(' {
|
||||
rev_pol << stack.last()
|
||||
stack.delete(stack.len-1)
|
||||
}
|
||||
stack.delete(stack.len-1)
|
||||
}
|
||||
else {
|
||||
return error('err: invalid character `${op}`')
|
||||
}
|
||||
}
|
||||
pos++
|
||||
}
|
||||
}
|
||||
for stack.len>0 {
|
||||
top := stack.last()
|
||||
rev_pol << top
|
||||
stack.delete(stack.len-1)
|
||||
}
|
||||
return rev_pol
|
||||
}
|
||||
|
||||
// Evaluate the result of Reverse Polish Notation.
|
||||
fn eval_rev_pol(rev_pol []string) ?f64 {
|
||||
mut stack := []f64{}
|
||||
for item in rev_pol {
|
||||
if is_num_string(item) {
|
||||
stack << item.f64()
|
||||
}
|
||||
else {
|
||||
if stack.len>=2 {
|
||||
oprand_r := stack.last()
|
||||
stack.delete(stack.len-1)
|
||||
oprand_l := stack.last()
|
||||
stack.delete(stack.len-1)
|
||||
match item {
|
||||
'+' { stack << oprand_l+oprand_r }
|
||||
'-' { stack << oprand_l-oprand_r }
|
||||
'*' { stack << oprand_l*oprand_r }
|
||||
'/' {
|
||||
if oprand_r == 0 {
|
||||
return error('err: divide by zero')
|
||||
}
|
||||
stack << oprand_l/oprand_r
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return error('err: invalid expression')
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack[0]
|
||||
}
|
||||
|
||||
fn is_num_string(str string) bool {
|
||||
for c in str {
|
||||
if c !in numeric_char {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
println('Please enter the expression you want to calculate, e.g. 1e2+(3-2.5)*6/1.5 .')
|
||||
println('Enter \'exit\' or \'EXIT\' to quit.')
|
||||
mut expr_count := 0
|
||||
for {
|
||||
expr_count++
|
||||
print('[$expr_count] ')
|
||||
expr := os.get_line().trim_space()
|
||||
if expr in ['exit', 'EXIT'] {
|
||||
break
|
||||
}
|
||||
rev_pol := expr_to_rev_pol(expr) or {
|
||||
eprintln(err)
|
||||
continue
|
||||
}
|
||||
res := eval_rev_pol(rev_pol) or {
|
||||
eprintln(err)
|
||||
continue
|
||||
}
|
||||
println(res)
|
||||
}
|
||||
}
|
||||
// Q: What's this?
|
||||
// A: This is a mini "home-made" calculator. You may also regard it as a very elementary version of "interpreter".
|
||||
import os
|
||||
|
||||
const (
|
||||
numeric_char = [`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `.`, `e`, `E`]
|
||||
)
|
||||
|
||||
// Convert expression to Reverse Polish Notation.
|
||||
fn expr_to_rev_pol(expr string) ?[]string {
|
||||
if expr == '' {
|
||||
return error('err: empty expression')
|
||||
}
|
||||
mut stack := []string{}
|
||||
mut rev_pol := []string{}
|
||||
mut pos := 0
|
||||
for pos < expr.len {
|
||||
mut end_pos := pos
|
||||
for end_pos < expr.len && expr[end_pos] in numeric_char {
|
||||
end_pos++
|
||||
}
|
||||
if end_pos > pos {
|
||||
stack << expr[pos..end_pos]
|
||||
pos = end_pos
|
||||
} else if end_pos == pos {
|
||||
op := expr[pos].str()
|
||||
match op {
|
||||
'(' {
|
||||
stack << op
|
||||
}
|
||||
'*', '/' {
|
||||
for stack.len > 0 && stack.last() !in ['(', '+', '-'] {
|
||||
rev_pol << stack.last()
|
||||
stack.delete(stack.len - 1)
|
||||
}
|
||||
stack << op
|
||||
}
|
||||
'+', '-' {
|
||||
for stack.len > 0 && stack.last() != '(' {
|
||||
rev_pol << stack.last()
|
||||
stack.delete(stack.len - 1)
|
||||
}
|
||||
stack << op
|
||||
}
|
||||
')' {
|
||||
for stack.len > 0 && stack.last() != '(' {
|
||||
rev_pol << stack.last()
|
||||
stack.delete(stack.len - 1)
|
||||
}
|
||||
stack.delete(stack.len - 1)
|
||||
}
|
||||
else {
|
||||
return error('err: invalid character `$op`')
|
||||
}
|
||||
}
|
||||
pos++
|
||||
}
|
||||
}
|
||||
for stack.len > 0 {
|
||||
top := stack.last()
|
||||
rev_pol << top
|
||||
stack.delete(stack.len - 1)
|
||||
}
|
||||
return rev_pol
|
||||
}
|
||||
|
||||
// Evaluate the result of Reverse Polish Notation.
|
||||
fn eval_rev_pol(rev_pol []string) ?f64 {
|
||||
mut stack := []f64{}
|
||||
for item in rev_pol {
|
||||
if is_num_string(item) {
|
||||
stack << item.f64()
|
||||
} else {
|
||||
if stack.len >= 2 {
|
||||
oprand_r := stack.last()
|
||||
stack.delete(stack.len - 1)
|
||||
oprand_l := stack.last()
|
||||
stack.delete(stack.len - 1)
|
||||
match item {
|
||||
'+' {
|
||||
stack << oprand_l + oprand_r
|
||||
}
|
||||
'-' {
|
||||
stack << oprand_l - oprand_r
|
||||
}
|
||||
'*' {
|
||||
stack << oprand_l * oprand_r
|
||||
}
|
||||
'/' {
|
||||
if oprand_r == 0 {
|
||||
return error('err: divide by zero')
|
||||
}
|
||||
stack << oprand_l / oprand_r
|
||||
}
|
||||
else {}
|
||||
}
|
||||
} else {
|
||||
return error('err: invalid expression')
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack[0]
|
||||
}
|
||||
|
||||
fn is_num_string(str string) bool {
|
||||
for c in str {
|
||||
if c !in numeric_char {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('Please enter the expression you want to calculate, e.g. 1e2+(3-2.5)*6/1.5 .')
|
||||
println("Enter \'exit\' or \'EXIT\' to quit.")
|
||||
mut expr_count := 0
|
||||
for {
|
||||
expr_count++
|
||||
print('[$expr_count] ')
|
||||
expr := os.get_line().trim_space()
|
||||
if expr in ['exit', 'EXIT'] {
|
||||
break
|
||||
}
|
||||
rev_pol := expr_to_rev_pol(expr) or {
|
||||
eprintln(err)
|
||||
continue
|
||||
}
|
||||
res := eval_rev_pol(rev_pol) or {
|
||||
eprintln(err)
|
||||
continue
|
||||
}
|
||||
println(res)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user