Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CodeSamples
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CompilerConstruction
CodeSamples
Commits
bae2db4f
Commit
bae2db4f
authored
5 years ago
by
Ronald Charles Moore
Browse files
Options
Downloads
Patches
Plain Diff
removed leftover
parent
c4342872
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
recursiveDescentParsers/cplusplus/interpret++/interpreter.cpp
+0
-244
0 additions, 244 deletions
...rsiveDescentParsers/cplusplus/interpret++/interpreter.cpp
with
0 additions
and
244 deletions
recursiveDescentParsers/cplusplus/interpret++/interpreter.cpp
deleted
100644 → 0
+
0
−
244
View file @
c4342872
// This code made available to his students by
// Prof. Ronald Moore
// https://fbi.h-da.de/personen/ronald-moore/
// mailto:ronald.moore@h-da.de
// with no warranties whatsoever!
#include
<cassert>
#include
<cctype>
// for isspace
#include
<cstdlib>
// for strtod
#include
<iostream>
#include
<fstream>
#include
<string>
// include <vector>
// ===================
// LEXICAL ANALYSIS
// The following are taken to be tokens:
// left and right parenthesis, the plus and minus characters,
// as well as asterisk and forward slash -- and numbers.
// In the script, substraction and division are not supported,
// but it seems like time to add them.
// Preliminaries and Utilities
// ============================
// Utility Types
typedef
double
numberType
;
// feel fee to change this to something else like int or float or bigint....
typedef
enum
Token
{
tok_number
=
'n'
,
tok_lparen
=
'('
,
tok_rparen
=
')'
,
tok_plus
=
'+'
,
tok_minus
=
'-'
,
tok_times
=
'*'
,
tok_div
=
'/'
,
tok_eof
=
'E'
,
bad_tok
=
'X'
}
Token
;
// global variables -- sue me if you don't like that!
static
std
::
istream
*
input
=
&
(
std
::
cin
);
// until proven otherwise
static
std
::
string
currentLine
(
""
);
static
int
currentLineNumber
=
-
1
;
static
int
currentColumnNumber
=
0
;
static
int
currentTokenLength
=
0
;
static
Token
next_token
;
// again with the global variables...
static
numberType
currentNumber
;
// = zero....
static
void
printErrorMsg
(
const
std
::
string
Error
)
{
std
::
cout
<<
"ERROR on line "
<<
currentLineNumber
<<
", column "
<<
currentColumnNumber
<<
" : "
<<
Error
<<
std
::
endl
;
std
::
cout
<<
currentLine
;
for
(
int
col
=
0
;
col
<
currentColumnNumber
-
1
;
col
++
)
std
::
cout
<<
'-'
;
std
::
cout
<<
'^'
<<
std
::
endl
;
}
// end printErrorMsg
// The Lexer
// ==========
static
bool
skippedWhiteSpace
(
)
{
// return true if not at EOF, i.e. if skipped
while
(
true
)
{
int
currentLineLength
=
currentLine
.
length
();
while
(
currentColumnNumber
<
currentLineLength
)
if
(
isspace
(
currentLine
[
currentColumnNumber
]
)
)
currentColumnNumber
++
;
else
// if NOT isspace()
return
true
;
// if we're here, we're at the end of a line.
std
::
getline
(
*
input
,
currentLine
);
currentLineNumber
++
;
currentColumnNumber
=
0
;
if
(
!
*
input
)
// EOF!!
return
false
;
// else, repeat!
// Which is the same as
// return skippedWhiteSpace() -- i.e. tail recursion.
};
};
static
Token
gettok
(
)
{
assert
(
input
);
// we assume nullptr != input
if
(
!
*
input
)
return
bad_tok
;
// else, we can read from input
// Skip white space, going to next line as necessary
if
(
!
skippedWhiteSpace
(
)
)
return
tok_eof
;
// We're have visible text in front of us.
char
currentChar
=
currentLine
[
currentColumnNumber
];
currentColumnNumber
++
;
// usually, but see num...
switch
(
currentChar
)
{
case
'('
:
return
tok_lparen
;
case
')'
:
return
tok_rparen
;
case
'+'
:
return
tok_plus
;
case
'-'
:
return
tok_minus
;
case
'*'
:
return
tok_times
;
case
'/'
:
return
tok_div
;
default
:
// either we have a number in front of us, or we don't
assert
(
0
<
currentColumnNumber
);
char
*
alpha
=
&
(
currentLine
[
currentColumnNumber
-
1
]);
// minus one because we incremented it before the switch
char
*
omega
=
nullptr
;
// until we call strtod...
double
tmpValue
=
strtod
(
alpha
,
&
omega
);
if
(
alpha
==
omega
)
{
return
bad_tok
;
// !!!
};
// else if strtod found a real number (or at least a double)
currentNumber
=
tmpValue
;
// let C++ do the converison
currentColumnNumber
+=
(
omega
-
alpha
)
-
1
;
// minus one because we incremented it before the switch
return
tok_number
;
};
// end switch
assert
(
false
);
// we should never get here!
return
bad_tok
;
}
// end gettok
// PARSING!!!
// ===========
//
// The grammar we are going to parse here is:
// Grammar:
// E → T E´
// E´ → + T E´ | - T E´ | ε
// T → F T´
// T´ → * F T´ | / F T´ | ε
// F → ( E ) | num
// Note that the recursive descent function for (e.g.) E´
// is nameded "E2ndHalf"-
// Forward Declarations
static
numberType
E
();
static
numberType
E2ndHalf
();
static
numberType
T
();
static
numberType
T2ndHalf
();
static
numberType
F
();
// E → T E´
numberType
E
()
{
return
T
()
+
E2ndHalf
();
}
// T → F T´
numberType
T
()
{
return
F
()
*
T2ndHalf
();
}
// E´ → + T E´ | - T E´ | ε
numberType
E2ndHalf
()
{
switch
(
next_token
)
{
case
tok_plus
:
next_token
=
gettok
();
// eat +
return
T
()
+
E2ndHalf
();
case
tok_minus
:
next_token
=
gettok
();
// eat -
return
(
-
1.0
*
T
())
+
E2ndHalf
();
default
:
return
0.0
;
};
}
// end E2ndHalf
// T´ → * F T´ | / F T´ | ε
numberType
T2ndHalf
()
{
numberType
tmp
,
rhs
,
acc
;
switch
(
next_token
)
{
case
tok_times
:
next_token
=
gettok
();
// eat *
return
F
()
*
T2ndHalf
();
case
tok_div
:
next_token
=
gettok
();
// eat /
tmp
=
F
();
if
(
0.0
!=
tmp
)
return
(
1.0
/
tmp
)
*
T2ndHalf
();
// else if T() returned zero
printErrorMsg
(
"Division by zero!"
);
// fall through to default return one
default
:
return
1.0
;
};
}
// end T2ndHalf
// F → ( E ) | num
numberType
F
()
{
numberType
result
=
0
;
switch
(
next_token
)
{
case
tok_lparen
:
next_token
=
gettok
();
// eat lparen
result
=
E
();
if
(
tok_rparen
==
next_token
)
{
next_token
=
gettok
();
// eat rparen
return
result
;
};
// else if rparen not found
printErrorMsg
(
"Expected Right Parenthesis"
);
return
0.0
;
case
tok_number
:
result
=
currentNumber
;
// side-effect of last gettok()
next_token
=
gettok
();
// eat id
return
result
;
default
:
printErrorMsg
(
"Expected Left Parenthesis or number"
);
return
0.0
;
};
}
// main (!)
// =========
int
main
(
int
argc
,
char
**
argv
)
{
if
(
2
!=
argc
)
{
std
::
cerr
<<
"Usage: "
<<
argv
[
0
]
<<
" <fileName>.
\n
"
<<
"You provided "
<<
argc
-
1
<<
" arguments, we take exactly one (only).
\n
"
;
return
(
-
1
);
};
// else if 1 == argc ....
std
::
string
fileName
(
argv
[
1
]
);
if
(
"-"
!=
fileName
)
{
static
std
::
ifstream
ifs
(
fileName
);
input
=
&
ifs
;
}
// Prime the pump!
next_token
=
gettok
(
);
// get tokens and dump them...
while
(
tok_eof
!=
next_token
)
{
std
::
cout
<<
currentLineNumber
<<
":"
<<
currentLine
<<
std
::
endl
;
numberType
value
=
E
(
);
std
::
cout
<<
"INTERPRETER: "
<<
value
<<
std
::
endl
;
};
std
::
cout
<<
"End Of File!"
<<
std
::
endl
;
return
0
;
// Alles klar!!!
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
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!
Save comment
Cancel
Please
register
or
sign in
to comment