Add files via upload
This commit is contained in:
parent
c11f19c640
commit
2714d19d9e
@ -8,15 +8,13 @@
|
|||||||
"\n",
|
"\n",
|
||||||
"# BASIC Interpreter\n",
|
"# BASIC Interpreter\n",
|
||||||
"\n",
|
"\n",
|
||||||
"[Years ago](http://norvig.com/lispy.html), I showed how to write an Interpreter for a dialect of Lisp. Some readers appreciated it, and some asked about an interpreter for a language that isn't just a bunch of parentheses. In 2014 I saw a [celebration](http://time.com/69316/basic/) of the 50th anniversary of the 1964 [Dartmouth BASIC](http://web.archive.org/web/20120716185629/http://www.bitsavers.org/pdf/dartmouth/BASIC_Oct64.pdf) interpreter, and thought that I could show how to implement such an interpreter. I never quite finished in 2014, but in 2017 I rediscovered my unfinished file and completed it. For those of you unfamiliar with BASIC, here is a sample program:"
|
"[Years ago](http://norvig.com/lispy.html), I showed how to write an Interpreter for a dialect of Lisp. Some readers appreciated it, and some asked about an interpreter for a language that isn't just a bunch of parentheses. In 2014 I saw a [celebration](http://time.com/69316/basic/) of the 50th anniversary of the 1964 [Dartmouth BASIC](http://web.archive.org/web/20120716185629/http://www.bitsavers.org/pdf/dartmouth/BASIC_Oct64.pdf) interpreter, and thought that I could show how to implement such an interpreter. I never quite finished in 2014, but now it is 2017, I rediscovered this unfinished file, and completed it. For those of you unfamiliar with BASIC, here is a sample program:"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 1,
|
"execution_count": 1,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"program = '''\n",
|
"program = '''\n",
|
||||||
@ -47,8 +45,9 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"Of course I don't have to build everything from scratch in assembly language, and I don't have to worry about every byte of storage, like [Kemeny](http://www.dartmouth.edu/basicfifty/basic.html), [Gates](http://www.pagetable.com/?p=774), and [Woz](http://www.retrothing.com/2008/07/restoring-wozs.html) did, so my job is much easier. The interpreter consists of three phases: \n",
|
"Of course I don't have to build everything from scratch in assembly language, and I don't have to worry about every byte of storage, like [Kemeny](http://www.dartmouth.edu/basicfifty/basic.html), [Gates](http://www.pagetable.com/?p=774), and [Woz](http://www.retrothing.com/2008/07/restoring-wozs.html) did, so my job is much easier. The interpreter consists of three phases: \n",
|
||||||
"* **Tokenization**: breaking a text into a list of tokens, for example: `\"10 READ N\"` becomes `['10', 'READ', 'N']`.\n",
|
"* **Tokenization**: breaking a text into a list of tokens, for example: `\"10 READ N\"` becomes `['10', 'READ', 'N']`.\n",
|
||||||
"* **Parsing**: building an executable representation from the tokens, so this statement becomes: `Stmt(num=10, typ='READ', args=['N'])`.\n",
|
"* **Parsing**: building a representation from the tokens: `Stmt(num=10, typ='READ', args=['N'])`.\n",
|
||||||
"* **Execution**: follow the flow of the program and do what each statement says; in this case an assignment: `variables['N'] = data.popleft()`.\n",
|
"* **Execution**: follow the flow of the program and do what each statement says; in this case the `READ` statement\n",
|
||||||
|
"has the effect of an assignment: `variables['N'] = data.popleft()`.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
@ -60,9 +59,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 2,
|
"execution_count": 2,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"import re \n",
|
"import re \n",
|
||||||
@ -73,7 +70,7 @@
|
|||||||
" LET|READ|DATA|PRINT|GOTO|IF|FOR|NEXT|END|STOP | # keywords\n",
|
" LET|READ|DATA|PRINT|GOTO|IF|FOR|NEXT|END|STOP | # keywords\n",
|
||||||
" DEF|GOSUB|RETURN|DIM|REM|TO|THEN|STEP | # more keywords\n",
|
" DEF|GOSUB|RETURN|DIM|REM|TO|THEN|STEP | # more keywords\n",
|
||||||
" [A-Z]\\d? | # variable names (letter optionally followed by a digit)\n",
|
" [A-Z]\\d? | # variable names (letter optionally followed by a digit)\n",
|
||||||
" \" .*? \" | # labels (strings in double quotes)\n",
|
" \".*? \" | # labels (strings in double quotes)\n",
|
||||||
" <>|>=|<= | # multi-character relational operators\n",
|
" <>|>=|<= | # multi-character relational operators\n",
|
||||||
" \\S # any non-space single character ''', \n",
|
" \\S # any non-space single character ''', \n",
|
||||||
" re.VERBOSE).findall"
|
" re.VERBOSE).findall"
|
||||||
@ -90,9 +87,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 3,
|
"execution_count": 3,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
@ -112,9 +107,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 4,
|
"execution_count": 4,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
@ -133,9 +126,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"source": [
|
"source": [
|
||||||
"That looks good. Note that my tokens are just strings; it will be the parser's job, not the tokenizer's, to recognize that `'2'` is a number and `'X'` is the name of a variable. (In some interpreters, the tokenizer makes distinctions like these.)\n",
|
"That looks good. Note that my tokens are just strings; it will be the parser's job, not the tokenizer's, to recognize that `'2'` is a number and `'X'` is the name of a variable. (In some interpreters, the tokenizer makes distinctions like these.)\n",
|
||||||
"\n",
|
"\n",
|
||||||
@ -151,9 +142,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 5,
|
"execution_count": 5,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
@ -180,15 +169,13 @@
|
|||||||
"* `peek()`: returns the next token in `tokens` (without changing `tokens`), or `None` if there are no more tokens.\n",
|
"* `peek()`: returns the next token in `tokens` (without changing `tokens`), or `None` if there are no more tokens.\n",
|
||||||
"* `pop()`: removes and returns the next token. \n",
|
"* `pop()`: removes and returns the next token. \n",
|
||||||
"* `pop(`*string*`)`: removes and returns the next token if it is equal to the string; else return `None` and leave `tokens` unchanged.\n",
|
"* `pop(`*string*`)`: removes and returns the next token if it is equal to the string; else return `None` and leave `tokens` unchanged.\n",
|
||||||
"* `pop(`*predicate*`)`: removes and returns the next token if *predicate*(*token*) is true; else return `None` and leave `tokens` unchanged."
|
"* `pop(`*predicate*`)`: remove and return the next token if *predicate*(*token*) is true; else return `None`, leave `tokens` alone."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 6,
|
"execution_count": 6,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"tokens = [] # Global variable to hold a list of tokens\n",
|
"tokens = [] # Global variable to hold a list of tokens\n",
|
||||||
@ -202,9 +189,10 @@
|
|||||||
" return (tokens[0] if tokens else None)\n",
|
" return (tokens[0] if tokens else None)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def pop(constraint=None):\n",
|
"def pop(constraint=None):\n",
|
||||||
" \"\"\"Remove and return the first token in `tokens`, or return None if first token fails a constraint.\n",
|
" \"\"\"Remove and return the first token in `tokens`, or return None if token fails constraint.\n",
|
||||||
" `constraint` can be None, a literal string (e.g. pop('=')), or a predicate (e.g. pop(is_varname)).\"\"\"\n",
|
" constraint can be None, a literal (e.g. pop('=')), or a predicate (e.g. pop(is_varname)).\"\"\"\n",
|
||||||
" if constraint is None or (peek() == constraint) or (callable(constraint) and constraint(peek())):\n",
|
" top = peek()\n",
|
||||||
|
" if constraint is None or (top == constraint) or (callable(constraint) and constraint(top)):\n",
|
||||||
" return tokens.pop(0)\n",
|
" return tokens.pop(0)\n",
|
||||||
" \n",
|
" \n",
|
||||||
"def remove_spaces(line): \n",
|
"def remove_spaces(line): \n",
|
||||||
@ -228,9 +216,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 7,
|
"execution_count": 7,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
@ -255,7 +241,8 @@
|
|||||||
" ['100', 'IF', 'X1', '+', '123.4', '+', 'E1', '-', '12.3E4', '<>', \n",
|
" ['100', 'IF', 'X1', '+', '123.4', '+', 'E1', '-', '12.3E4', '<>', \n",
|
||||||
" '1.2E-34', '*', '-', '12E34', '+', '1', '+', '\"HI\"', 'THEN', '99'])\n",
|
" '1.2E-34', '*', '-', '12E34', '+', '1', '+', '\"HI\"', 'THEN', '99'])\n",
|
||||||
" assert remove_spaces('10 GO TO 99') == '10GOTO99'\n",
|
" assert remove_spaces('10 GO TO 99') == '10GOTO99'\n",
|
||||||
" assert remove_spaces('100 PRINT \"HELLO WORLD\", SIN(X) ^ 2') == '100PRINT\"HELLO WORLD\",SIN(X)^2'\n",
|
" assert (remove_spaces('100 PRINT \"HELLO WORLD\", SIN(X) ^ 2')\n",
|
||||||
|
" == '100PRINT\"HELLO WORLD\",SIN(X)^2')\n",
|
||||||
" assert lines('one line') == ['one line']\n",
|
" assert lines('one line') == ['one line']\n",
|
||||||
" assert lines(program) == [\n",
|
" assert lines(program) == [\n",
|
||||||
" '10 REM POWER TABLE',\n",
|
" '10 REM POWER TABLE',\n",
|
||||||
@ -313,6 +300,43 @@
|
|||||||
"test_tokenizer()"
|
"test_tokenizer()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"['10 REM POWER TABLE',\n",
|
||||||
|
" '11 DATA 8, 4',\n",
|
||||||
|
" '15 READ N0, P0',\n",
|
||||||
|
" '20 PRINT \"N\",',\n",
|
||||||
|
" '25 FOR P = 2 to P0',\n",
|
||||||
|
" '30 PRINT \"N ^\" P,',\n",
|
||||||
|
" '35 NEXT P',\n",
|
||||||
|
" '40 PRINT \"SUM\"',\n",
|
||||||
|
" '45 LET S = 0',\n",
|
||||||
|
" '50 FOR N = 2 TO N0',\n",
|
||||||
|
" '55 PRINT N,',\n",
|
||||||
|
" '60 FOR P = 2 TO P0',\n",
|
||||||
|
" '65 LET S = S + N ^ P',\n",
|
||||||
|
" '70 PRINT N ^ P,',\n",
|
||||||
|
" '75 NEXT P',\n",
|
||||||
|
" '80 PRINT S',\n",
|
||||||
|
" '85 NEXT N',\n",
|
||||||
|
" '99 END']"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 8,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"lines(program)"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
@ -347,10 +371,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 8,
|
"execution_count": 9,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def Grammar(): \n",
|
"def Grammar(): \n",
|
||||||
@ -408,7 +430,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 9,
|
"execution_count": 10,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
@ -419,11 +441,11 @@
|
|||||||
" num = linenumber()\n",
|
" num = linenumber()\n",
|
||||||
" typ = pop(is_stmt_type) or fail('unknown statement type')\n",
|
" typ = pop(is_stmt_type) or fail('unknown statement type')\n",
|
||||||
" args = []\n",
|
" args = []\n",
|
||||||
" for c in grammar[typ]: # For each constituent of rule, call if callable or match if literal string\n",
|
" for p in grammar[typ]: # For each part of rule, call if callable or match if literal string\n",
|
||||||
" if callable(c):\n",
|
" if callable(p):\n",
|
||||||
" args.append(c())\n",
|
" args.append(p())\n",
|
||||||
" else:\n",
|
" else:\n",
|
||||||
" pop(c) or fail('expected ' + repr(c))\n",
|
" pop(p) or fail('expected ' + repr(p))\n",
|
||||||
" return Stmt(num, typ, args)"
|
" return Stmt(num, typ, args)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -436,19 +458,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 10,
|
"execution_count": 11,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def linenumber(): return (int(pop()) if peek().isnumeric() else fail('missing line number'))\n",
|
"def linenumber(): return (int(pop()) if peek().isnumeric() else fail('missing line number'))\n",
|
||||||
"def number(): return (-1 if pop('-') else +1) * float(pop()) # Optional minus sign before number\n",
|
"def number(): return (-1 if pop('-') else +1) * float(pop()) # Optional minus sign\n",
|
||||||
"def step(): return (expression() if pop('STEP') else 1) # 1 is the default step\n",
|
"def step(): return (expression() if pop('STEP') else 1) # 1 is the default step\n",
|
||||||
"def relational(): return pop(is_relational) or fail('expected a relational operator')\n",
|
"def relational(): return pop(is_relational) or fail('expected a relational operator')\n",
|
||||||
"def varname(): return pop(is_varname) or fail('expected a variable name')\n",
|
"def varname(): return pop(is_varname) or fail('expected a variable name')\n",
|
||||||
"def funcname(): return pop(is_funcname) or fail('expected a function name')\n",
|
"def funcname(): return pop(is_funcname) or fail('expected a function name')\n",
|
||||||
"def anycharacters(): tokens.clear() # The tokens in a REM statement don't matter, so just clear them"
|
"def anycharacters(): tokens.clear() # Ignore tokens in a REM statement"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -460,18 +480,20 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 11,
|
"execution_count": 12,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def is_stmt_type(x): return isinstance(x, str) and x in grammar # LET, READ, ...\n",
|
"def is_stmt_type(x): return is_str(x) and x in grammar # LET, READ, ...\n",
|
||||||
"def is_funcname(x): return isinstance(x, str) and len(x) == 3 and x.isalpha() # SIN, COS, FNA, FNB, ...\n",
|
"def is_funcname(x): return is_str(x) and len(x) == 3 and x.isalpha() # SIN, COS, FNA, FNB, ...\n",
|
||||||
"def is_varname(x): return isinstance(x, str) and len(x) in (1, 2) and x[0].isalpha() # A, A1, A2, B, ...\n",
|
"def is_varname(x): return is_str(x) and len(x) in (1, 2) and x[0].isalpha() # A, A1, A2, B, ...\n",
|
||||||
"def is_label(x): return isinstance(x, str) and x.startswith('\"') # \"HELLO WORLD\", ...\n",
|
"def is_label(x): return is_str(x) and x.startswith('\"') # \"HELLO WORLD\", ...\n",
|
||||||
"def is_relational(x): return isinstance(x, str) and x in ('<', '=', '>', '<=', '<>', '>=')\n",
|
"def is_relational(x): return is_str(x) and x in ('<', '=', '>', '<=', '<>', '>=')\n",
|
||||||
"def is_number(x): return isinstance(x, str) and x and x[0] in '.0123456789' # '3', '.14', ..."
|
"def is_number(x): return is_str(x) and x and x[0] in '.0123456789' # '3', '.14', ...\n",
|
||||||
|
"\n",
|
||||||
|
"def is_str(x): return isinstance(x, str)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -483,10 +505,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 12,
|
"execution_count": 13,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def variable(): \n",
|
"def variable(): \n",
|
||||||
@ -509,7 +529,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": 14,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
@ -536,7 +556,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 14,
|
"execution_count": 15,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
@ -556,10 +576,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 15,
|
"execution_count": 16,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": true
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def parse_line(line):\n",
|
"def parse_line(line):\n",
|
||||||
@ -572,7 +590,7 @@
|
|||||||
" return stmt\n",
|
" return stmt\n",
|
||||||
" except SyntaxError as err:\n",
|
" except SyntaxError as err:\n",
|
||||||
" print(\"Error in line '{}' at '{}': {}\".format(line, ' '.join(tokens), err))\n",
|
" print(\"Error in line '{}' at '{}': {}\".format(line, ' '.join(tokens), err))\n",
|
||||||
" return Stmt(0, 'REM', []) # Have to return something: a dummy statement\n",
|
" return Stmt(0, 'REM', []) # Return dummy statement\n",
|
||||||
" \n",
|
" \n",
|
||||||
"def fail(message): raise SyntaxError(message)"
|
"def fail(message): raise SyntaxError(message)"
|
||||||
]
|
]
|
||||||
@ -588,7 +606,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 16,
|
"execution_count": 17,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
@ -596,14 +614,14 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"from collections import namedtuple, defaultdict, deque\n",
|
"from collections import namedtuple, defaultdict, deque\n",
|
||||||
"\n",
|
"\n",
|
||||||
"Stmt = namedtuple('Stmt', 'num, typ, args') # Statement: '20 GOTO 99' => Stmt(20, 'GOTO', 99)\n",
|
"Stmt = namedtuple('Stmt', 'num, typ, args') # '1 GOTO 9' => Stmt(1, 'GOTO', 9)\n",
|
||||||
"Subscript = namedtuple('Subscript', 'var, indexes') # Subscripted reference: 'A(I)' => Subscript('A', ['I'])\n",
|
"Subscript = namedtuple('Subscript', 'var, indexes') # 'A(I)' => Subscript('A', ['I'])\n",
|
||||||
"Funcall = namedtuple('Funcall', 'f, x') # Function call: 'SQR(X)' => Funcall('SQR', 'X')\n",
|
"Funcall = namedtuple('Funcall', 'f, x') # 'SQR(X)' => Funcall('SQR', 'X')\n",
|
||||||
"Opcall = namedtuple('Opcall', 'x, op, y') # Infix operation: 'X + 1' => Opcall('X', '+', 1)\n",
|
"Opcall = namedtuple('Opcall', 'x, op, y') # 'X + 1' => Opcall('X', '+', 1)\n",
|
||||||
"ForState = namedtuple('ForState', 'continu, end, step') # Data used to control a FOR loop variable\n",
|
"ForState = namedtuple('ForState', 'continu, end, step') # Data for FOR loop \n",
|
||||||
"\n",
|
"\n",
|
||||||
"class Function(namedtuple('_', 'parm, body')):\n",
|
"class Function(namedtuple('_', 'parm, body')):\n",
|
||||||
" \"User-defined callable function; 'DEF FNC(X) = X ^ 3' => functions['FNC'] = Function('X', Opcall('X', '^', 3))\"\n",
|
" \"User-defined function; 'DEF FNC(X) = X ^ 3' => Function('X', Opcall('X', '^', 3))\"\n",
|
||||||
" def __call__(self, value): \n",
|
" def __call__(self, value): \n",
|
||||||
" variables[self.parm] = value # Global assignment to the parameter\n",
|
" variables[self.parm] = value # Global assignment to the parameter\n",
|
||||||
" return evalu(self.body)"
|
" return evalu(self.body)"
|
||||||
@ -651,7 +669,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 17,
|
"execution_count": 18,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
@ -692,10 +710,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 18,
|
"execution_count": 19,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def expression(prec=1): \n",
|
"def expression(prec=1): \n",
|
||||||
@ -724,9 +740,11 @@
|
|||||||
" else:\n",
|
" else:\n",
|
||||||
" return fail('unknown expression')\n",
|
" return fail('unknown expression')\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def precedence(op): return (3 if op == '^' else 2 if op in ('*', '/') else 1 if op in ('+', '-') else 0)\n",
|
"def precedence(op): \n",
|
||||||
|
" return (3 if op == '^' else 2 if op in ('*', '/') else 1 if op in ('+', '-') else 0)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def associativity(op): return (0 if op == '^' else 1)"
|
"def associativity(op): \n",
|
||||||
|
" return (0 if op == '^' else 1)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -740,10 +758,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 19,
|
"execution_count": 20,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
@ -768,7 +784,7 @@
|
|||||||
" Stmt(num=99, typ='END', args=[])]"
|
" Stmt(num=99, typ='END', args=[])]"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 19,
|
"execution_count": 20,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
@ -788,10 +804,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 20,
|
"execution_count": 21,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
@ -799,17 +813,17 @@
|
|||||||
"'ok'"
|
"'ok'"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 20,
|
"execution_count": 21,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"def test_parse(text, result, category=expression):\n",
|
"def test_exp(text, repr):\n",
|
||||||
" \"Test that text can be parsed as a category to yield the semantic result, with no tokens left over.\"\n",
|
" \"Test that text can be parsed as an expression to yield repr, with no tokens left over.\"\n",
|
||||||
" global tokens\n",
|
" global tokens\n",
|
||||||
" tokens = tokenizer(text)\n",
|
" tokens = tokenizer(text)\n",
|
||||||
" return category() == result and not tokens\n",
|
" return (expression() == repr) and not tokens\n",
|
||||||
" \n",
|
" \n",
|
||||||
"def test_parser():\n",
|
"def test_parser():\n",
|
||||||
" assert is_funcname('SIN') and is_funcname('FNZ') # Function names are three letters\n",
|
" assert is_funcname('SIN') and is_funcname('FNZ') # Function names are three letters\n",
|
||||||
@ -818,16 +832,17 @@
|
|||||||
" assert not is_varname('FNZ') and not is_varname('A10') and not is_varname('')\n",
|
" assert not is_varname('FNZ') and not is_varname('A10') and not is_varname('')\n",
|
||||||
" assert is_relational('>') and is_relational('>=') and not is_relational('+')\n",
|
" assert is_relational('>') and is_relational('>=') and not is_relational('+')\n",
|
||||||
" \n",
|
" \n",
|
||||||
" assert test_parse('A + B * X + C', Opcall(Opcall('A', '+', Opcall('B', '*', 'X')), '+', 'C'))\n",
|
" assert test_exp('A + B * X + C', Opcall(Opcall('A', '+', Opcall('B', '*', 'X')), '+', 'C'))\n",
|
||||||
" assert test_parse('A + B + X + C', Opcall(Opcall(Opcall('A', '+', 'B'), '+', 'X'), '+', 'C'))\n",
|
" assert test_exp('A + B + X + C', Opcall(Opcall(Opcall('A', '+', 'B'), '+', 'X'), '+', 'C'))\n",
|
||||||
" assert test_parse('SIN(X)^2', Opcall(Funcall('SIN', 'X'), '^', 2))\n",
|
" assert test_exp('SIN(X)^2', Opcall(Funcall('SIN', 'X'), '^', 2))\n",
|
||||||
" assert test_parse('10 ^ 2 ^ 3', Opcall(10, '^', Opcall(2, '^', 3))) # right associative\n",
|
" assert test_exp('10 ^ 2 ^ 3', Opcall(10, '^', Opcall(2, '^', 3))) # right associative\n",
|
||||||
" assert test_parse('10 - 2 - 3', Opcall(Opcall(10, '-', 2), '-', 3)) # left associative\n",
|
" assert test_exp('10 - 2 - 3', Opcall(Opcall(10, '-', 2), '-', 3)) # left associative\n",
|
||||||
" assert test_parse('A(I)+M(I, J)', Opcall(Subscript(var='A', indexes=['I']), '+', \n",
|
" assert test_exp('A(I)+M(I, J)', Opcall(Subscript(var='A', indexes=['I']), '+', \n",
|
||||||
" Subscript(var='M', indexes=['I', 'J'])))\n",
|
" Subscript(var='M', indexes=['I', 'J'])))\n",
|
||||||
" assert test_parse('X * -1', Opcall('X', '*', Funcall('NEG', 1.0)))\n",
|
" assert test_exp('X * -1', Opcall('X', '*', Funcall('NEG', 1.0)))\n",
|
||||||
" assert test_parse('X--Y--Z', Opcall(Opcall('X', '-', Funcall('NEG', 'Y')), '-', Funcall('NEG', 'Z')))\n",
|
" assert test_exp('X--Y--Z', Opcall(Opcall('X', '-', Funcall('NEG', 'Y')), \n",
|
||||||
" assert test_parse('((((X))))', 'X')\n",
|
" '-', Funcall('NEG', 'Z')))\n",
|
||||||
|
" assert test_exp('((((X))))', 'X')\n",
|
||||||
" return 'ok'\n",
|
" return 'ok'\n",
|
||||||
"\n",
|
"\n",
|
||||||
"test_parser()"
|
"test_parser()"
|
||||||
@ -844,7 +859,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 21,
|
"execution_count": 22,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
@ -881,10 +896,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 22,
|
"execution_count": 23,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def execute(stmts): \n",
|
"def execute(stmts): \n",
|
||||||
@ -944,10 +957,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 23,
|
"execution_count": 24,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"import math\n",
|
"import math\n",
|
||||||
@ -1040,10 +1051,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 24,
|
"execution_count": 25,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def basic_print(items): \n",
|
"def basic_print(items): \n",
|
||||||
@ -1082,10 +1091,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 25,
|
"execution_count": 26,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1120,9 +1127,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 26,
|
"execution_count": 27,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false,
|
|
||||||
"scrolled": true
|
"scrolled": true
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@ -1149,7 +1155,7 @@
|
|||||||
" Stmt(num=99, typ='END', args=[])]"
|
" Stmt(num=99, typ='END', args=[])]"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 26,
|
"execution_count": 27,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
@ -1160,10 +1166,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 27,
|
"execution_count": 28,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1197,10 +1201,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 28,
|
"execution_count": 29,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1237,10 +1239,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 29,
|
"execution_count": 30,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1277,10 +1277,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 30,
|
"execution_count": 31,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1306,10 +1304,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 31,
|
"execution_count": 32,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1369,10 +1365,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 32,
|
"execution_count": 33,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1401,10 +1395,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 33,
|
"execution_count": 34,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1455,39 +1447,37 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 34,
|
"execution_count": 35,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"defaultdict(float,\n",
|
"defaultdict(float,\n",
|
||||||
" {'J': 5.0,\n",
|
" {('P', (1.0,)): 1.25,\n",
|
||||||
" ('S', (1.0, 1.0)): 40.0,\n",
|
|
||||||
" ('S', (2.0, 4.0)): 21.0,\n",
|
|
||||||
" ('P', (1.0,)): 1.25,\n",
|
|
||||||
" ('S', (3.0, 2.0)): 47.0,\n",
|
|
||||||
" ('S', (2.0, 2.0)): 16.0,\n",
|
|
||||||
" ('S', (3.0, 3.0)): 29.0,\n",
|
|
||||||
" ('S', (3.0, 5.0)): 33.0,\n",
|
" ('S', (3.0, 5.0)): 33.0,\n",
|
||||||
" ('S', (1.0, 5.0)): 42.0,\n",
|
|
||||||
" ('S', (3.0, 4.0)): 16.0,\n",
|
" ('S', (3.0, 4.0)): 16.0,\n",
|
||||||
" 'I': 3.0,\n",
|
" ('S', (1.0, 5.0)): 42.0,\n",
|
||||||
|
" ('S', (2.0, 1.0)): 10.0,\n",
|
||||||
" ('P', (3.0,)): 2.5,\n",
|
" ('P', (3.0,)): 2.5,\n",
|
||||||
" ('S', (1.0, 4.0)): 29.0,\n",
|
" ('S', (1.0, 4.0)): 29.0,\n",
|
||||||
" ('S', (2.0, 3.0)): 3.0,\n",
|
|
||||||
" ('S', (1.0, 3.0)): 37.0,\n",
|
|
||||||
" ('S', (2.0, 1.0)): 10.0,\n",
|
|
||||||
" ('S', (1.0, 2.0)): 20.0,\n",
|
" ('S', (1.0, 2.0)): 20.0,\n",
|
||||||
" ('S', (2.0, 5.0)): 8.0,\n",
|
|
||||||
" ('S', (3.0, 1.0)): 35.0,\n",
|
" ('S', (3.0, 1.0)): 35.0,\n",
|
||||||
|
" 'I': 3.0,\n",
|
||||||
|
" ('S', (2.0, 4.0)): 21.0,\n",
|
||||||
|
" ('P', (2.0,)): 4.3,\n",
|
||||||
|
" ('S', (2.0, 5.0)): 8.0,\n",
|
||||||
|
" ('S', (1.0, 1.0)): 40.0,\n",
|
||||||
|
" ('S', (3.0, 3.0)): 29.0,\n",
|
||||||
|
" 'J': 5.0,\n",
|
||||||
|
" ('S', (3.0, 2.0)): 47.0,\n",
|
||||||
" 'S': 169.4,\n",
|
" 'S': 169.4,\n",
|
||||||
" ('P', (2.0,)): 4.3})"
|
" ('S', (2.0, 2.0)): 16.0,\n",
|
||||||
|
" ('S', (2.0, 3.0)): 3.0,\n",
|
||||||
|
" ('S', (1.0, 3.0)): 37.0})"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 34,
|
"execution_count": 35,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
@ -1498,19 +1488,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 35,
|
"execution_count": 36,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"6 3 2 6 9 0 0 3 3 6 9 2 7 9 1 2 1 4 4 1 2 7 3 7 8 \n",
|
"7 2 8 4 9 1 9 8 0 8 3 0 3 4 5 6 4 2 1 6 9 9 9 7 5 \n",
|
||||||
"5 2 5 4 4 9 7 7 0 5 4 9 7 7 5 5 4 9 3 8 6 2 6 4 5 \n",
|
"8 4 1 5 9 9 7 5 5 7 2 0 3 2 1 2 1 8 3 9 9 3 0 0 2 \n",
|
||||||
"8 7 6 0 3 4 1 4 2 2 8 1 1 9 2 4 0 1 0 2 1 3 4 0 2 \n",
|
"2 8 9 7 5 8 9 0 2 7 8 6 7 4 9 9 4 2 5 4 0 9 6 5 3 \n",
|
||||||
"9 0 2 7 4 1 8 4 3 2 8 3 9 3 9 3 2 4 6 8 9 0 9 5 9 \n"
|
"3 3 5 1 7 1 6 1 0 7 3 5 8 1 9 0 4 7 1 7 4 5 1 7 6 \n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -1527,10 +1515,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 36,
|
"execution_count": 37,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1564,10 +1550,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 37,
|
"execution_count": 38,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1602,10 +1586,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 38,
|
"execution_count": 39,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1632,10 +1614,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 39,
|
"execution_count": 40,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1668,10 +1648,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 40,
|
"execution_count": 41,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1730,22 +1708,18 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"source": [
|
"source": [
|
||||||
"# Final Program\n",
|
"# Final Program\n",
|
||||||
"\n",
|
"\n",
|
||||||
"Now for a final, longer example, Conway's Game of [Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life),\n",
|
"Now for a final, longer example, Conway's Game of [Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life),\n",
|
||||||
"which shows that BASIC is capable of handling a non-trivial problem—but I wouldn't want to rely on it for anything much bigger. This should give us some added confidence in the validity of the interpreter, but I would say the interpreter needs more work before I would trust it. I hope you found working through the interpreter informative, and maybe you have ideas for how to improve it, or to develop an interpreter for another language."
|
"which shows that BASIC is capable of handling a non-trivial problem—but I wouldn't want to rely on it for anything much bigger. This should give us some added confidence in the validity of the interpreter, but I would say the interpreter needs more work before I would trust it. I hope you found working through the interpreter infortative, and maybe you have ideas for how to improve it, or to develop an interpreter for another language."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 41,
|
"execution_count": 42,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
@ -1931,6 +1905,15 @@
|
|||||||
"999 END \n",
|
"999 END \n",
|
||||||
"''')"
|
"''')"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
@ -1949,9 +1932,9 @@
|
|||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.5.1"
|
"version": "3.5.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
"nbformat_minor": 0
|
"nbformat_minor": 1
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user