examples: vfmt calculator.v

pull/6199/head
Charadon 2020-08-23 14:18:37 +00:00 committed by GitHub
parent 1c9e02094c
commit bb60b4227e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 135 additions and 134 deletions

View File

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