Skip to content
GitLab
Explore
Projects
Groups
Snippets
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Memri
parsers
Commits
7c3181ab
Commit
7c3181ab
authored
4 years ago
by
Ruben Daniels
Browse files
Options
Download
Email Patches
Plain Diff
First attempt at something of an interpreter
parent
5e550973
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
main.swift
+28
-0
main.swift
memri-parser.xcodeproj/project.pbxproj
+4
-0
memri-parser.xcodeproj/project.pbxproj
memri-parser/expression-parser/Compiler.swift
+143
-0
memri-parser/expression-parser/Compiler.swift
memri-parser/expression-parser/Lexer.swift
+2
-2
memri-parser/expression-parser/Lexer.swift
memri-parser/expression-parser/Nodes.swift
+3
-3
memri-parser/expression-parser/Nodes.swift
memri-parser/expression-parser/Parser.swift
+1
-0
memri-parser/expression-parser/Parser.swift
memri-parser/expression-parser/main.swift
+12
-1
memri-parser/expression-parser/main.swift
with
193 additions
and
6 deletions
+193
-6
main.swift
0 → 100644
+
28
-
0
View file @
7c3181ab
//
// main.swift
// Kaleidoscope
//
// Created by Matthew Cheok on 15/11/15.
// Copyright © 2015 Matthew Cheok. All rights reserved.
//
import
Foundation
let
source
=
multiline
(
"def foo(x, y)"
,
" x + y * 2 + (4 + 5) / 3"
,
""
,
"foo(3, 4)"
)
let
lexer
=
Lexer
(
input
:
source
)
let
tokens
=
lexer
.
tokenize
()
print
(
tokens
)
let
parser
=
Parser
(
tokens
:
tokens
)
do
{
print
(
try
parser
.
parse
())
}
catch
{
print
(
error
)
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
memri-parser.xcodeproj/project.pbxproj
+
4
-
0
View file @
7c3181ab
...
...
@@ -11,6 +11,7 @@
86CDB71E246D100D007EAE67
/* Parser.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
86CDB71A246D100D007EAE67
/* Parser.swift */
;
};
86CDB71F246D100D007EAE67
/* Lexer.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
86CDB71B246D100D007EAE67
/* Lexer.swift */
;
};
86CDB720246D100D007EAE67
/* main.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
86CDB71C246D100D007EAE67
/* main.swift */
;
};
86CDB722246D1402007EAE67
/* Compiler.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
86CDB721246D1402007EAE67
/* Compiler.swift */
;
};
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
...
...
@@ -31,6 +32,7 @@
86CDB71A246D100D007EAE67
/* Parser.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Parser.swift
;
sourceTree
=
"<group>"
;
};
86CDB71B246D100D007EAE67
/* Lexer.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Lexer.swift
;
sourceTree
=
"<group>"
;
};
86CDB71C246D100D007EAE67
/* main.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
main.swift
;
sourceTree
=
"<group>"
;
};
86CDB721246D1402007EAE67
/* Compiler.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Compiler.swift
;
sourceTree
=
"<group>"
;
};
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
...
...
@@ -75,6 +77,7 @@
86CDB71C246D100D007EAE67
/* main.swift */
,
86CDB719246D100D007EAE67
/* Nodes.swift */
,
86CDB71A246D100D007EAE67
/* Parser.swift */
,
86CDB721246D1402007EAE67
/* Compiler.swift */
,
);
path
=
"expression-parser"
;
sourceTree
=
"<group>"
;
...
...
@@ -140,6 +143,7 @@
files
=
(
86CDB71E246D100D007EAE67
/* Parser.swift in Sources */
,
86CDB71F246D100D007EAE67
/* Lexer.swift in Sources */
,
86CDB722246D1402007EAE67
/* Compiler.swift in Sources */
,
86CDB720246D100D007EAE67
/* main.swift in Sources */
,
86CDB71D246D100D007EAE67
/* Nodes.swift in Sources */
,
);
...
...
This diff is collapsed.
Click to expand it.
memri-parser/expression-parser/Compiler.swift
0 → 100644
+
143
-
0
View file @
7c3181ab
//
// Compiler.swift
// memri-parser
//
// Created by Ruben Daniels on 5/14/20.
// Copyright © 2020 Memri. All rights reserved.
//
import
Foundation
class
Interpreter
{
let
ast
:
ExprNode
let
lookup
:
(
LookupNode
)
->
Any
let
execFunc
:
(
LookupNode
,
[
Any
?])
->
Any
var
stack
:
[
Any
]
=
[]
enum
Signals
{
case
execElse
}
init
(
_
ast
:
ExprNode
,
_
lookup
:
@escaping
(
LookupNode
)
->
Any
,
_
execFunc
:
@escaping
(
LookupNode
,
[
Any
?])
->
Any
)
{
self
.
ast
=
ast
self
.
lookup
=
lookup
self
.
execFunc
=
execFunc
}
func
push
(
_
x
:
Any
)
{
print
(
"POP:
\(
x
)
\(
stack
.
count
)
"
);
stack
.
append
(
x
)
}
func
pop
()
->
Any
?
{
stack
.
popLast
()
}
func
execute
()
->
Any
?
{
execSingle
(
ast
)
return
pop
()
}
func
evaluateBoolean
(
_
x
:
Any
?)
->
Bool
{
if
let
x
=
x
as?
Bool
{
return
x
}
else
if
let
x
=
x
as?
Int
{
return
x
!=
0
}
else
if
let
x
=
x
as?
Double
{
return
x
!=
0
}
else
if
let
x
=
x
as?
String
{
return
x
!=
""
}
else
if
x
==
nil
{
return
false
}
else
{
return
true
}
}
func
evaluateNumber
(
_
x
:
Any
?)
->
Double
{
if
let
x
=
x
as?
Bool
{
return
x
?
1
:
0
}
else
if
let
x
=
x
as?
Int
{
return
Double
(
x
)
}
else
if
let
x
=
x
as?
Double
{
return
x
}
else
if
let
x
=
x
as?
String
{
return
(
x
as
NSString
)
.
doubleValue
}
else
if
x
==
nil
{
return
.
nan
}
else
{
return
.
nan
}
}
func
compare
(
_
a
:
Any
?,
_
b
:
Any
?)
->
Bool
{
if
let
a
=
a
as?
Bool
{
return
a
==
evaluateBoolean
(
b
)
}
else
if
let
a
=
a
as?
Int
{
return
Double
(
a
)
==
evaluateNumber
(
b
)
}
else
if
let
a
=
a
as?
Double
{
return
a
==
evaluateNumber
(
b
)
}
else
if
let
a
=
a
as?
String
{
return
a
==
"
\(
b
??
""
)
"
}
else
if
a
==
nil
{
return
b
==
nil
}
else
{
return
false
}
}
func
execSingle
(
_
expr
:
ExprNode
)
{
if
let
expr
=
expr
as?
BinaryOpNode
{
execSingle
(
expr
.
lhs
)
let
result
=
pop
()
switch
expr
.
op
{
case
.
ConditionStart
:
if
evaluateBoolean
(
result
)
{
execSingle
(
expr
.
rhs
)
}
else
{
push
(
Signals
.
execElse
)
}
case
.
ConditionElse
:
if
result
as?
Signals
==
Signals
.
execElse
{
execSingle
(
expr
.
rhs
)
}
else
{
// Done
}
case
.
ConditionEquals
:
execSingle
(
expr
.
rhs
)
let
otherResult
=
pop
()
push
(
compare
(
result
,
otherResult
))
case
.
ConditionAND
:
let
boolLHS
=
evaluateBoolean
(
result
)
if
boolLHS
{
push
(
true
)
}
else
{
execSingle
(
expr
.
rhs
)
let
otherResult
=
pop
()
push
(
boolLHS
&&
evaluateBoolean
(
otherResult
))
}
case
.
ConditionOR
:
let
boolLHS
=
evaluateBoolean
(
result
)
if
boolLHS
{
push
(
true
)
}
else
{
execSingle
(
expr
.
rhs
)
let
otherResult
=
pop
()
push
(
boolLHS
||
evaluateBoolean
(
otherResult
))
}
case
.
Division
:
execSingle
(
expr
.
rhs
)
let
otherResult
=
pop
()
push
(
evaluateNumber
(
result
)
/
evaluateNumber
(
otherResult
))
case
.
Minus
:
execSingle
(
expr
.
rhs
)
let
otherResult
=
pop
()
push
(
evaluateNumber
(
result
)
-
evaluateNumber
(
otherResult
))
case
.
Multiplication
:
execSingle
(
expr
.
rhs
)
let
otherResult
=
pop
()
push
(
evaluateNumber
(
result
)
*
evaluateNumber
(
otherResult
))
case
.
Plus
:
execSingle
(
expr
.
rhs
)
let
otherResult
=
pop
()
push
(
evaluateNumber
(
result
)
+
evaluateNumber
(
otherResult
))
}
}
else
if
let
expr
=
expr
as?
NegationNode
{
execSingle
(
expr
.
exp
)
let
result
=
pop
()
push
(
!
evaluateBoolean
(
result
))
}
else
if
let
expr
=
expr
as?
NumberNode
{
push
(
expr
.
value
)
}
else
if
let
expr
=
expr
as?
StringNode
{
push
(
expr
.
value
)
}
else
if
let
expr
=
expr
as?
BoolNode
{
push
(
expr
.
value
)
}
else
if
let
expr
=
expr
as?
NumberExpressionNode
{
execSingle
(
expr
.
exp
)
let
result
=
pop
()
push
(
evaluateNumber
(
result
))
}
// else if let expr = expr as? VariableNode { push(expr.value) }
else
if
let
expr
=
expr
as?
LookupNode
{
push
(
lookup
(
expr
))
}
else
if
let
expr
=
expr
as?
CallNode
{
let
args
:[
Any
?]
=
expr
.
arguments
.
map
{
execSingle
(
$0
);
return
pop
()
}
push
(
execFunc
(
expr
.
lookup
,
args
))
}
}
}
This diff is collapsed.
Click to expand it.
memri-parser/expression-parser/Lexer.swift
+
2
-
2
View file @
7c3181ab
...
...
@@ -10,7 +10,7 @@ public enum Token {
case
Operator
(
Operator
,
Int
)
case
Bool
(
Bool
,
Int
)
case
Identifier
(
String
,
Int
)
case
Number
(
Float
,
Int
)
case
Number
(
Double
,
Int
)
case
Negation
(
Int
)
case
Comma
(
Int
)
case
ParensOpen
(
Int
)
...
...
@@ -86,7 +86,7 @@ public class Lexer {
func
addToken
(
_
token
:
Token
?
=
nil
){
if
isMode
==
.
number
{
tokens
.
append
(
.
Number
((
keyword
.
joined
()
as
NSString
)
.
float
Value
,
i
))
tokens
.
append
(
.
Number
((
keyword
.
joined
()
as
NSString
)
.
double
Value
,
i
))
keyword
=
[]
isMode
=
.
idle
}
...
...
This diff is collapsed.
Click to expand it.
memri-parser/expression-parser/Nodes.swift
+
3
-
3
View file @
7c3181ab
//
// Nodes.swift
// Kaleidoscope
//
//
Created
by Matthew Cheok on 15/11/15.
//
Based on work
by Matthew Cheok on 15/11/15.
// Copyright © 2015 Matthew Cheok. All rights reserved.
// Copyright © 2020 memri. All rights reserved.
//
import
Foundation
...
...
@@ -12,7 +12,7 @@ public protocol ExprNode: CustomStringConvertible {
}
public
struct
NumberNode
:
ExprNode
{
public
let
value
:
Float
public
let
value
:
Double
public
var
description
:
String
{
return
"NumberNode(
\(
value
)
)"
}
...
...
This diff is collapsed.
Click to expand it.
memri-parser/expression-parser/Parser.swift
+
1
-
0
View file @
7c3181ab
...
...
@@ -234,6 +234,7 @@ class Parser {
var
arguments
=
[
ExprNode
]()
if
case
Token
.
ParensClose
=
peekCurrentToken
()
{
// Do nothing
}
else
{
while
true
{
...
...
This diff is collapsed.
Click to expand it.
memri-parser/expression-parser/main.swift
+
12
-
1
View file @
7c3181ab
...
...
@@ -6,16 +6,27 @@
import
Foundation
//"""
//!(test + -5.63537) or 4/3 ? variable.func() : me.address[primary = true].country ? ((4+5 * 10) + test[10]) : 'asdads\\'asdad' + '')
//"""
var
lexer
=
Lexer
(
input
:
"""
!(test + -5.63537) or 4/3 ? variable.func() : me.address[primary = true].country ? ((4+5 * 10) + test[10]) : 'asdads
\\
'asdad' + '')
"""
)
let
dt
=
Date
()
let
tokens
=
lexer
.
tokenize
()
print
(
tokens
)
//
print(tokens)
print
(
Date
()
.
timeIntervalSince
(
dt
))
let
parser
=
Parser
(
tokens
)
let
tree
=
try
parser
.
parse
()
//let analyzer = Analyzer(tree)
//try analyzer.analyze()
let
interpreter
=
Interpreter
(
tree
,
{
lookup
in
return
10
},
{
lookup
,
args
in
return
20
})
let
result
=
interpreter
.
execute
()
print
(
result
??
"ERROR"
)
print
(
Date
()
.
timeIntervalSince
(
dt
))
print
(
tree
)
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Snippets