實現乙個計算器

2021-09-07 09:47:24 字數 2400 閱讀 6417

(1)一直以來,我都想寫一門語言,但無從下手。

(2)我找到了很多編譯原理的教程,但始終覺得內容晦澀,理解不了,所以先嘗試寫乙個簡單的,比如:計算器。

(3)網上有很多關於計算器的實現,但大多需要有編譯原理的基礎,對於我這種小白實在難以理解。

(4)我決定採用暴力模擬的方式,需要用正規表示式,但我不想自己實現,所以用js。

計算器接受一串字元,處理後返回結果。

我們來看一下要做什麼:

首先需要知道有哪些「元素」,比如「12+34×56"的元素有整數12,加號,整數34,乘號,整數56,這個過程稱為詞法分析

然後根據符號的優先順序進行組合,其過程相當於加括號,12+(34*56),這個過程稱為語法分析

借用正規表示式,可以簡單暴力的實現詞法分析。

正規表示式的概念,和編譯原理一樣,都要費好大功夫來理解,當初也是各種查資料。

盡量簡單的講一講吧。

定義:正規表示式是一種生成器,可以生成大量相同模式的字串。

字串的概念大家都懂,來看一下正規表示式是怎麼生成字串的。

例子:正規表示式 ab* 可以生成'a' , 'ab' , 'abb' , 'abbb' ...

正規表示式有三種規則(並,或,閉包),其他規則都是由這三個規則組合而成。

並,直接連在一起,表示相連,例如:abc 生成』abc'

或,以符號|分隔,表示或,例如:a|b生成'a','b'

閉包,加符號*,表示重複任意次,例如:a* 生成 '','a', 'aa', 'aaa'...

一些常用的規則:

,例如:[abcd]等價於a|b|c|d

+,例如:a+等價於aa*

?,例如:a?等價於 a|空

\d,等價於[0123456789],還可以用[0-9]

\w,等價於[a-za-z0-9]

\w,非\w

\b,表示\w與\w的交界處

計算器用到的正規表示式:

number:\b\d+\b

注意:規則中有的字元要轉義,如:+

不斷用正則來匹配輸入的字串,就可以。

使用js來實現:

1 function get_words(buf)

26 }

27 }

28 return words;

29 }

對於'12+34 * (78-56)',會得到:

number,12

+,nan

number,34

*,nan

(,nan

number,78

-,nan

number,56

),nan

至此,詞法分析完成。

我們採用類似於正則的方式來描述語法分析的過程,可稱其為文法

分析一波。

括號優先順序最高,所以遇見括號就要計算,文法為:

=> ( '(' ')' )  | 'number'

引號的稱終結符,尖括號的稱非終結符

非終結符表示可以繼續推導,終結符表示推導終點。

其中表示整個算式

乘除優先順序比加法高,所以遇見乘除就要計算,文法為:

然後是加減:

這些都可以用正則來理解。

其中每個非終結符都做成乙個函式,翻譯過來就成。

1 function parse(words) 

11 function match(sym)

15 console.log('\nerror\n');

16 }

17 function expr() else

27 }

28 return value;

29 }

30 function term() else

40 }

41 return value;

42 }

43 function factor() else if (type() == 'number')

51 return value;

52 }

53

54 return expr();

55 }

寫完了,哈哈。

用node.js可以簡單的跑起來:

摺起來吧,效果在前面。

實現乙個計算器

一直以來,我都想寫一門語言,但無從下手。我找到了很多編譯原理的教程,但始終覺得內容晦澀,理解不了,所以先嘗試寫乙個簡單的,比如 計算器。網上有很多關於計算器的實現,但大多需要有編譯原理的基礎,對於我這種小白實在難以理解。我決定採用暴力模擬的方式,需要用正規表示式,但我不想自己實現,所以用js。計算器...

Pythons實現乙個計算器

coding utf 8 from tkinter import def calculate result eval equ.get equ.set equ.get n str result def show buttonstring content equ.get if content 0 con...

堆疊實現乙個整型計算器

計算器特性 支援整型運算 能夠處理運算子和運算元間的空格,支援括號 實現思路 利用乙個運算元堆疊dgt和乙個運算子堆疊ops實現 1 從左至右掃瞄運算表示式輸入,若為運算元則直接壓入dgt堆疊 2 若為運算子則判斷ops中是否已經存在運算子,不存在則直接壓入,存在則與棧頂運算子比較優先順序,優先順序...