Compare commits
30 Commits
Author | SHA1 | Date |
---|---|---|
|
933fbf61c9 | |
|
bcfe12a442 | |
|
d54a25668f | |
|
00504483c5 | |
|
8a8188e07d | |
|
57a7fa3e43 | |
|
06c9650d6f | |
|
0fd419102e | |
|
259d654eaf | |
|
d22d2718a0 | |
|
5bd748b2e6 | |
|
bb898ea44e | |
|
3d646261b5 | |
|
990900ae9a | |
|
992897c4ff | |
|
05b430c346 | |
|
fcb082a9de | |
|
94d90611e1 | |
|
89f718ce34 | |
|
c6f27e1e69 | |
|
5f717f4427 | |
|
69157aec8c | |
|
53fd5518dc | |
|
feb505e932 | |
|
182d4bbb90 | |
|
bc5b48ec82 | |
|
1bfef0f5fc | |
|
a213c022ef | |
|
158a461ebf | |
|
1efdeaf3e7 |
Binary file not shown.
Binary file not shown.
|
@ -1,12 +0,0 @@
|
|||
To compile this under Linux:
|
||||
|
||||
gcc -o platy_gnu buffer.c buffer.h platy_bt.c -Wall -ansi -pedantic
|
||||
|
||||
To use:
|
||||
./platy_gnu ass1.pls [f|a|m]
|
||||
|
||||
f: fixed increment mode
|
||||
a: additive increment mode
|
||||
m: multiplicative mode
|
||||
|
||||
NOTE: Change buffer.h to use malloc.h instead of mm_maloc.h if running on anything that isn't macOS
|
|
@ -0,0 +1,328 @@
|
|||
# PLATYPUS Language Specification
|
||||
|
||||
### 2.1 Input Elements and Tokens
|
||||
|
||||
<input character> ->
|
||||
ASCII characters but not SEOF
|
||||
|
||||
<input> ->
|
||||
<input elements> SEOF
|
||||
|
||||
<input elements> ->
|
||||
<input element> | <input elements> <input element>
|
||||
|
||||
<token> ->
|
||||
<variable identifier> | <keyword> | <floating-point literal>
|
||||
| <integer literal> | <string literal> | <separator> | <operator>
|
||||
|
||||
### 2.2 White Space
|
||||
|
||||
<white space> ->
|
||||
ASCII SP character (space)
|
||||
| ASCII HT character (horizontal tab)
|
||||
| ASCII VT character (vertical tab)
|
||||
| ASCII FF character (form feed)
|
||||
| <line terminator>
|
||||
|
||||
<line terminator> ->
|
||||
CR | LF | CR LF
|
||||
|
||||
### 2.3 Comments
|
||||
|
||||
<comment> ->
|
||||
!< <opt_characters in line> <line terminator>
|
||||
|
||||
<characters in line> ->
|
||||
<comment character> | <characters in line> <comment character>
|
||||
|
||||
<comment character> ->
|
||||
<input character> but not <line terminator>
|
||||
|
||||
### 2.4 Variable Identifiers
|
||||
|
||||
<variable identifier> ->
|
||||
<arithmetic variable identifier> | <string variable identifier>
|
||||
|
||||
<arithmetic identifier> ->
|
||||
<letter> <opt_letters or digits>
|
||||
|
||||
<opt_letters or digits> ->
|
||||
ε | <letters or digits>
|
||||
|
||||
<letters or digits> ->
|
||||
<letter or digit> | <letters or digits> <letter or digit>
|
||||
|
||||
<letter> ->
|
||||
[a-z] | [A-Z]
|
||||
|
||||
<letter or digit> ->
|
||||
<letter> | <digit>
|
||||
|
||||
<string variable identifier> ->
|
||||
<arithmetic variable identifier>#
|
||||
|
||||
### 2.5 Keywords
|
||||
|
||||
<keyword> ->
|
||||
PLATYPUS | IF | THEN | ELSE | USING | REPEAT | INPUT | OUTPUT
|
||||
|
||||
### 2.6 Integer Literals
|
||||
|
||||
<integer literal> ->
|
||||
<decimal integer literal> | <octal integer literal>
|
||||
|
||||
<decimal integer literal> ->
|
||||
0 | <non-zero digit> <opt_digits>
|
||||
|
||||
<opt_digits> ->
|
||||
ε | <digits>
|
||||
|
||||
<digits> ->
|
||||
<digit> | <digits> <digit>
|
||||
|
||||
<digit> ->
|
||||
0 | <non-zero digit>
|
||||
|
||||
<non-zero digit> -> one of
|
||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
|
||||
|
||||
<octal integer literal> ->
|
||||
0 <octal digit> <octal digits>
|
||||
|
||||
<octal digit> ->
|
||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
|
||||
|
||||
<octal digits> ->
|
||||
<octal digit> | <octal digits> <octal digit>
|
||||
|
||||
|
||||
### 2.7 Floating-point Literals
|
||||
|
||||
<floating-point literal> ->
|
||||
<decimal integer literal> . <opt_digits>
|
||||
|
||||
### 2.8 String Literals
|
||||
|
||||
<opt_string literal> ->
|
||||
ε | <string literal>
|
||||
|
||||
<string literal> ->
|
||||
"<opt_string characters>"
|
||||
|
||||
<opt_string characters> ->
|
||||
ε | <string characters>
|
||||
|
||||
<string characters> ->
|
||||
<input character> | <string characters> <input character>
|
||||
|
||||
### 2.9 Separators
|
||||
|
||||
<separator> ->
|
||||
( | ) | { | } | , | ; | " |.
|
||||
|
||||
### 2.10 Operators
|
||||
|
||||
<operator> ->
|
||||
<arithmetic operator> | <string concatenation operator>
|
||||
| <relational operator> | <logical operator>
|
||||
| <assignment operator>
|
||||
|
||||
<arithmetic operator> ->
|
||||
+ | - | * | /
|
||||
|
||||
<string concatenation operator> ->
|
||||
<<
|
||||
|
||||
<relational operator> ->
|
||||
> | < | == | <>
|
||||
|
||||
<logical operator> ->
|
||||
.AND. | .OR.
|
||||
|
||||
<assignment operator> ->
|
||||
=
|
||||
|
||||
## 3. The PLATYPUS Syntactic Specification
|
||||
### 3.1 PLATYPUS Program
|
||||
|
||||
<program> ->
|
||||
PLATYPUS {<opt_statements>} SEOF
|
||||
|
||||
<opt_statements> ->
|
||||
ε | <statements>
|
||||
|
||||
<statements> ->
|
||||
<statement> | <statements> <statement>
|
||||
|
||||
### 3.2 Statements
|
||||
|
||||
<statement> ->
|
||||
<assignment statement>
|
||||
| <selection statement>
|
||||
| <iteration statement>
|
||||
| <input statement>
|
||||
| <output statement>
|
||||
|
||||
### 3.3 Assignment Statement
|
||||
|
||||
<assignment statement> ->
|
||||
<assignment expression> ;
|
||||
|
||||
<assignment expression> ->
|
||||
<arithmetic variable identifier> = <arithmetic expression>
|
||||
| <string variable identifier> = <string expression>
|
||||
|
||||
#### 3.2.2 Selection Statement (`if` statement)
|
||||
|
||||
<selection statement> ->
|
||||
IF (<conditional expression>) THEN <opt_statements>
|
||||
ELSE {<opt_statements>};
|
||||
|
||||
#### 3.2.3 Iteration Statement (the loop statement)
|
||||
|
||||
<iteration statement> ->
|
||||
USING (<assignment expression> , <conditional expression>, <assignment expression>) REPEAT { <opt_statements> };
|
||||
|
||||
#### 3.2.4 Input Statement
|
||||
|
||||
<input statement> ->
|
||||
INPUT (<variable list>);
|
||||
|
||||
<opt_variable list> ->
|
||||
ε | <variable list>
|
||||
|
||||
/** New Variable List version below
|
||||
<variable list> ->
|
||||
<variable identifier> | <variable list>,<variable identifier>
|
||||
**/
|
||||
|
||||
<variable list> ->
|
||||
<variable identifier> <variable list'>
|
||||
|
||||
<variable list'> ->
|
||||
, <variable identifier> <variable list'> | E
|
||||
|
||||
#### 3.2.5 Output Statement
|
||||
|
||||
<output statement> ->
|
||||
OUTPUT(<opt_variable list> | <opt_string literal>);
|
||||
|
||||
### 3.3 Expressions
|
||||
#### 3.3.1 Arithmetic Expressions
|
||||
|
||||
<arithmetic expression> ->
|
||||
<unary arithmetic expression>
|
||||
| <additive arithmetic expression>
|
||||
|
||||
<unary arithmetic expression> ->
|
||||
- <primary arithmetic expression>
|
||||
| + <primary arithmetic expression>
|
||||
|
||||
/** New Version of Additive Arithmetic Expressions below
|
||||
<additive arithmetic expression> ->
|
||||
<additive arithmetic expression> + <multiplicative arithmetic expression>
|
||||
| <additive arithmetic expression> - <multiplicative arithmetic expression>
|
||||
| <multiplicative arithmetic expression>
|
||||
**/
|
||||
|
||||
<additive arihtmetic expression> ->
|
||||
<multiplicative arithmetic expression> <additive arithmetic expression'>
|
||||
|
||||
<additive arithmetic expression'> ->
|
||||
+ <multiplicative arithmetic expression> <additive arithmetic expression'>
|
||||
| - <multiplicative arithmetic expression> <additive arithmetic expression'>
|
||||
|
||||
/** New Version of Mult. Arithmetic Expressions below
|
||||
<multiplicative arithmetic expression> ->
|
||||
<multiplicative arithmetic expression> * <primary arithmetic expression>
|
||||
| <multiplicative arithmetic expression> / <primary arithmetic expression>
|
||||
| <primary arithmetic expression>
|
||||
**/
|
||||
<multiplicative arithmetic expression> ->
|
||||
<primary arithmetic expression> <multiplicative arithmetic expression'>
|
||||
|
||||
<multiplicative arithmetic expression'> ->
|
||||
* <primary arithmetic expression> <multiplicative arithmetic expression'>
|
||||
| / <primary arithmetic expression> <multiplicative arithmetic expression'>
|
||||
|
||||
<primary arithmetic expression> ->
|
||||
<variable identifier>
|
||||
| <floating-point literal>
|
||||
| <integer literal>
|
||||
| (<arithmetic expression>)
|
||||
|
||||
#### 3.3.2 String Expression
|
||||
/** New version of String Expressions below
|
||||
<string expression> ->
|
||||
<primary string expression>
|
||||
| <string expression> << <primary string expression>
|
||||
**/
|
||||
<string expression> ->
|
||||
<primary string expression> <string expression'>
|
||||
|
||||
<string expression'> ->
|
||||
<< <primary string expression> <string expression'> | E
|
||||
|
||||
<primary string expression> ->
|
||||
<string variable identifier>
|
||||
| <string literal>
|
||||
|
||||
#### 3.3.3 Conditional Expression
|
||||
|
||||
<conditional expression> ->
|
||||
<logical OR expression>
|
||||
|
||||
/** New Logical OR and Logical AND expressions below
|
||||
<logical OR expression> ->
|
||||
<logical AND expression>
|
||||
| <logical OR expression> .OR. <logical AND expression>
|
||||
|
||||
<logical AND expression> ->
|
||||
<relational expression>
|
||||
| <logical AND expression> .AND. <relational expression>
|
||||
**/
|
||||
<logical OR expression> ->
|
||||
<logical AND expression> <logical OR expression'>
|
||||
|
||||
<logical OR expression'> ->
|
||||
.OR. <logical AND expression> <logical OR expression'>
|
||||
|
||||
<logical AND expression> ->
|
||||
<relational expression> <logical AND expression'>
|
||||
|
||||
<logical AND expression'> ->
|
||||
.AND. <relational expression> <logical AND expression'>
|
||||
|
||||
|
||||
#### 3.3.4 Relational Expressions
|
||||
|
||||
/** New version of Relational expressions below
|
||||
<relational expression> ->
|
||||
<primary a_relational expression> <relational operator> <primary a_relational expression>
|
||||
| <primary s_relational expression> <relational operator> <primary s_relational expression>
|
||||
**/
|
||||
|
||||
<relational expression> ->
|
||||
<primary a_relational expression> <primary a_relational expression'>
|
||||
| <primary s_relational expression> <primary s_relational expression'>
|
||||
|
||||
|
||||
<primary a_relational expression> ->
|
||||
<floating-point literal>
|
||||
| <integer literal>
|
||||
| <variable identifier>
|
||||
|
||||
<primary a_relational expression'> ->
|
||||
== <primary a_relational expression>
|
||||
| <> <primary a_relational expression>
|
||||
| > <primary a_relational expression>
|
||||
| < <primary a_relational expression>
|
||||
|
||||
<primary s_relational expression> ->
|
||||
<string literal> | <string variable identifier>
|
||||
|
||||
<primary s_relational expression'> ->
|
||||
== <primary s_relational expression>
|
||||
| <> <primary s_relational expression>
|
||||
| > <primary s_relational expression>
|
||||
| < <primary s_relational expression>
|
Binary file not shown.
18
README.md
18
README.md
|
@ -1,5 +1,5 @@
|
|||
# PLATYPUS
|
||||
*Buffer Descriptor for the PLATYPUS language specification*
|
||||
*Frontend compiler for the PLATYPUS language specification*
|
||||
|
||||
## Building
|
||||
|
||||
|
@ -8,12 +8,12 @@
|
|||
*gcc (tested in version 6.3.x) or clang (tested under LLVM clang-0800.0.42.1)*
|
||||
|
||||
- `make [gcc | clang]`
|
||||
- Default is to build both versions (this is an aftermath of testing behaviour from different compilers)
|
||||
- It is safe to modify the default to either gcc or clang if you don't have one of them
|
||||
- **NOTE: I haven't tested or created make targets for the scanner yet.**
|
||||
- No argument will build both versions (this is an aftermath of having to check behaviour in the binary from multiple compilers)
|
||||
- It is safe to modify the default to either gcc or clang if you wish.
|
||||
- **NOTE: I haven't tested or created make targets for the final implementation yet. This is somewhat buried deep into the backburner**
|
||||
### Windows
|
||||
#### Requires
|
||||
- `msvc` (tested under Visual Studio 2015 with Update 3, however VS2013 shouldn't behave abnormally either, nor should 2017)
|
||||
- `msvc` (tested under Visual Studio 2015 with Update 3, however VS 2012 and 2013 shouldn't behave abnormally either, nor should 2017)
|
||||
- Disable language extensions (use ANSI C)
|
||||
---
|
||||
## Running
|
||||
|
@ -31,10 +31,10 @@
|
|||
|
||||
# Notes
|
||||
|
||||
This is in no way complete, it is missing a scanner implementation, parser, symbol table, etc.
|
||||
**This is in no way complete, or ready for production in any shape or form.** It works up to the parser, but still contains incorrect grammar parsing and some edge cases that causes crashes.
|
||||
|
||||
You can modify the initial capacity and increment factor defined in `platy_bt.c` (should really make that a command line parameter in a future release)
|
||||
You can modify the initial capacity and increment factor defined in `platy.c` (should really make that a command line parameter in a future release)
|
||||
- Increment factor range for additive mode: `1 - 255`. (setting this to 0 implies fixed mode, regardless of the mode given in the command line)
|
||||
- Initial capacity range (in bytes): `0 - 32767 (SHRT_MAX)`
|
||||
- This is due to my environment's install locations for the C include libraries:
|
||||
- **Inside `buffer.h`, there is a `#DEFINE` line for `MACOS_DEP`. If you are using a Linux system or Windows and your malloc.h is actually named malloc.h, you can leave `#undef MACOS_DEP` alone, otherwise comment it out.**
|
||||
- This is an issue caused by my environment's install locations for the C include libraries:
|
||||
- **`buffer.h` contains an `#ifdef` directive checking if `WIN32` exists. Due to an upgrade issue with GCC in macOS (possibly only in my machine), `malloc.h` is actually named `mm_maloc.h`. If your system uses `malloc.h`, you can safely delete the check and use the regular filename instead.**
|
||||
|
|
2
buffer.c
2
buffer.c
|
@ -4,7 +4,7 @@
|
|||
* Author: Victor Fernandes, 040772243
|
||||
* Course: CST8152 - Compilers, Lab Section: 011
|
||||
* Date: February 1, 2017
|
||||
* Professor: Svillen Ranev
|
||||
* Professor: S^R
|
||||
* A character buffer utility with three modes of self-incrementation
|
||||
through dynamic memory allocation, and ability to set a mark flag.
|
||||
* Function list: b_create, b_isfull, b_isempty, b_size, b_capacity,
|
||||
|
|
3
buffer.h
3
buffer.h
|
@ -22,11 +22,12 @@
|
|||
/* standard header files */
|
||||
#include <stdio.h> /* standard input/output */
|
||||
|
||||
#ifdef MACOS_DEP
|
||||
#ifndef WIN32
|
||||
#include <mm_malloc.h> /* for dynamic memory allocation.*/
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h> /* implementation-defined data type ranges and limits */
|
||||
|
||||
/* constant definitions */
|
||||
|
|
|
@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "buffer", "buffer\buffer.vcx
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scanner", "scanner\scanner.vcxproj", "{C53261F2-8A2D-4F75-8E54-DBFD16A621BB}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stable", "Stable\Stable.vcxproj", "{C2CCF0F1-D771-4F57-89EA-F76727169CE3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
COMPILERS|x64 = COMPILERS|x64
|
||||
|
@ -41,6 +43,18 @@ Global
|
|||
{C53261F2-8A2D-4F75-8E54-DBFD16A621BB}.Release|x64.Build.0 = Release|x64
|
||||
{C53261F2-8A2D-4F75-8E54-DBFD16A621BB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C53261F2-8A2D-4F75-8E54-DBFD16A621BB}.Release|x86.Build.0 = Release|Win32
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.COMPILERS|x64.ActiveCfg = Release|x64
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.COMPILERS|x64.Build.0 = Release|x64
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.COMPILERS|x86.ActiveCfg = Debug|Win32
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.COMPILERS|x86.Build.0 = Debug|Win32
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Debug|x64.Build.0 = Debug|x64
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Release|x64.ActiveCfg = Release|x64
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Release|x64.Build.0 = Release|x64
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C2CCF0F1-D771-4F57-89EA-F76727169CE3}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -0,0 +1,874 @@
|
|||
/* File Name: parser.c
|
||||
* The PLATYPUS parsing program for the final assignment of
|
||||
How To Train Your Dragon (AKA Compilers)
|
||||
* Compiler: GNU GCC 6
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Course: CST8152 - Compilers, Lab Section: 011
|
||||
* Date: April 21, 2017
|
||||
* Professor: Svillen Ravev
|
||||
* Version: 0.1
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
/* Global variables for the parser */
|
||||
Token lookahead;
|
||||
int synerrno; /* Error counter */
|
||||
Buffer *sc_buf; /* Scanner buffer */
|
||||
extern char *kw_table[]; /* Keyword table with matching enum */
|
||||
extern STD sym_table; /* The symbol table */
|
||||
extern Buffer *str_LTBL; /* String literal table */
|
||||
extern int line; /* Line position of the Scanner */
|
||||
extern Token malar_next_token(Buffer *); /* Scanner function to get the next token */
|
||||
|
||||
/* Begins the source file parsing
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: malar_next_token, program, match, gen_incode
|
||||
* Parameters: pBuffer - The input buffer
|
||||
* Return value: N/A
|
||||
*/
|
||||
void parser(pBuffer in_buf)
|
||||
{
|
||||
synerrno = 0;
|
||||
sc_buf = in_buf;
|
||||
lookahead = malar_next_token(sc_buf);
|
||||
program();
|
||||
match(SEOF_T, NO_ATTR);
|
||||
gen_incode("PLATY: Source file parsed");
|
||||
}
|
||||
|
||||
/* Matches the given token code+attribute pair to the current lookahead token
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: syn_eh, syn_printe, malar_next_token
|
||||
* Parameters: pr_token_code, pr_token_attribute
|
||||
* Return value:
|
||||
* Algorithm:
|
||||
*/
|
||||
void match(int pr_token_code, int pr_token_attribute)
|
||||
{
|
||||
if (pr_token_code != lookahead.code)
|
||||
{
|
||||
syn_eh(pr_token_code);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pr_token_code)
|
||||
{
|
||||
case ART_OP_T:
|
||||
case REL_OP_T:
|
||||
case LOG_OP_T:
|
||||
case KW_T:
|
||||
if (pr_token_attribute != lookahead.attribute.get_int)
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (lookahead.code == SEOF_T)
|
||||
return;
|
||||
lookahead = malar_next_token(sc_buf);
|
||||
if (lookahead.code == ERR_T)
|
||||
{
|
||||
++synerrno;
|
||||
syn_printe();
|
||||
lookahead = malar_next_token(sc_buf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
syn_eh(pr_token_code);
|
||||
}
|
||||
|
||||
/* Error "recovery" function for the parser
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: syn_printe, malar_next_token, exit
|
||||
* Parameters: int pr_token_code
|
||||
* Return value:
|
||||
* Algorithm: Outputs a standard syn_printe error, and steps through
|
||||
the source file with the Scanner until it finds the next matching
|
||||
code needed by pr_token_code.
|
||||
*/
|
||||
void syn_eh(int pr_token_code)
|
||||
{
|
||||
syn_printe();
|
||||
++synerrno;
|
||||
|
||||
while (lookahead.code != SEOF_T)
|
||||
{
|
||||
lookahead = malar_next_token(sc_buf);
|
||||
if (lookahead.code == pr_token_code)
|
||||
{
|
||||
if (lookahead.code != SEOF_T)
|
||||
{
|
||||
lookahead = malar_next_token(sc_buf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pr_token_code != SEOF_T)
|
||||
exit(synerrno);
|
||||
}
|
||||
|
||||
/* Outputs an error message to stdout using the current lookahead token
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: printf, b_setmark
|
||||
* Parameters: N/A
|
||||
*/
|
||||
void syn_printe()
|
||||
{
|
||||
printf("PLATY: Syntax error: Line:%3d\n***** Token code: %3d Attribute: ", line, lookahead.code);
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case ERR_T:
|
||||
printf("%s\n", lookahead.attribute.err_lex);
|
||||
break;
|
||||
case SEOF_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case AVID_T:
|
||||
case SVID_T:
|
||||
printf("%s\n", sym_table.pstvr[lookahead.attribute.get_int].plex);
|
||||
break;
|
||||
case FPL_T:
|
||||
printf("%5.1f\n", lookahead.attribute.flt_value);
|
||||
break;
|
||||
case INL_T:
|
||||
printf("%d\n", lookahead.attribute.get_int);
|
||||
break;
|
||||
case STR_T:
|
||||
printf("%s\n", b_setmark(str_LTBL, lookahead.attribute.str_offset));
|
||||
break;
|
||||
case SCC_OP_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case ASS_OP_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case ART_OP_T:
|
||||
printf("%d\n", lookahead.attribute.get_int);
|
||||
break;
|
||||
case REL_OP_T:
|
||||
printf("%d\n", lookahead.attribute.get_int);
|
||||
break;
|
||||
case LOG_OP_T:
|
||||
printf("%d\n", lookahead.attribute.get_int);
|
||||
break;
|
||||
case LPR_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case RPR_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case LBR_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case RBR_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case KW_T:
|
||||
printf("%s\n", kw_table[lookahead.attribute.get_int]);
|
||||
break;
|
||||
case COM_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
case EOS_T:
|
||||
printf("NA\n");
|
||||
break;
|
||||
default:
|
||||
printf("PLATY: Scanner error: invalid token code: %d\n", lookahead.code);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates a message to stdout (can be later modified to generate C code)
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: printf
|
||||
* Parameters: char* code
|
||||
* Return value: N/A
|
||||
*/
|
||||
void gen_incode(char *code)
|
||||
{
|
||||
printf("%s\n", code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grammar functions ahoy
|
||||
*/
|
||||
|
||||
/*
|
||||
* <additive_arithmetic_expression> ->
|
||||
<multiplicative_arithmetic_expression> <additive_arithmetic_expression_prime>
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T, (}
|
||||
*/
|
||||
void additive_arithmetic_expression()
|
||||
{
|
||||
multiplicative_arithmetic_expression();
|
||||
additive_arithmetic_expression_prime();
|
||||
}
|
||||
|
||||
/*
|
||||
* <additive_arithmetic_expression> ->
|
||||
<multiplicative_arithmetic_expression> <additive_arithmetic_expression_prime>
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T, (}
|
||||
*/
|
||||
void additive_arithmetic_expression_prime()
|
||||
{
|
||||
if (lookahead.code == ART_OP_T &&
|
||||
lookahead.attribute.arr_op != MULT &&
|
||||
lookahead.attribute.arr_op != DIV)
|
||||
{
|
||||
match(lookahead.code, lookahead.attribute.arr_op);
|
||||
multiplicative_arithmetic_expression();
|
||||
additive_arithmetic_expression_prime();
|
||||
gen_incode("PLATY: Additive arithmetic expression parsed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <opt_LPR_T> <unary_arithmetic_expression> <opt_RPR_T> |
|
||||
<opt_LPR_T> <additive_arithmetic_expression> <opt_RPR_T>
|
||||
FIRST Set = {-, +, AVID_T, FPL_T, INL_T, (}
|
||||
*/
|
||||
void arithmetic_expression()
|
||||
{
|
||||
/* GCC complains that PLUS and MINUS enums aren't handled,
|
||||
but this is automatically handled in additive_arithmetic_expression()
|
||||
*/
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case ART_OP_T:
|
||||
switch (lookahead.attribute.arr_op)
|
||||
{
|
||||
case MULT:
|
||||
case DIV:
|
||||
syn_printe();
|
||||
return;
|
||||
}
|
||||
unary_arithmetic_expression();
|
||||
break;
|
||||
case AVID_T:
|
||||
case FPL_T:
|
||||
case INL_T:
|
||||
case LPR_T:
|
||||
additive_arithmetic_expression();
|
||||
break;
|
||||
case EOS_T:
|
||||
return;
|
||||
default:
|
||||
syn_printe();
|
||||
return;
|
||||
}
|
||||
gen_incode("PLATY: Arithmetic expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <assignment_expression> ->
|
||||
AVID = <arithmetic_expression> | SVID = <string_expression>
|
||||
FIRST Set = {AVID, SVID}
|
||||
*/
|
||||
void assignment_expression()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case AVID_T:
|
||||
match(AVID_T, NO_ATTR);
|
||||
match(ASS_OP_T, NO_ATTR);
|
||||
arithmetic_expression();
|
||||
gen_incode("PLATY: Assignment expression (arithmetic) parsed");
|
||||
break;
|
||||
case SVID_T:
|
||||
match(SVID_T, NO_ATTR);
|
||||
match(ASS_OP_T, NO_ATTR);
|
||||
string_expression();
|
||||
gen_incode("PLATY: Assignment expression (string) parsed");
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <assignment_statement> ->
|
||||
<assignment_expression> ;
|
||||
FIRST Set = {AVID, SVID}
|
||||
*/
|
||||
void assignment_statement()
|
||||
{
|
||||
assignment_expression();
|
||||
match(EOS_T, NO_ATTR);
|
||||
gen_incode("PLATY: Assignment statement parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <conditional_expression> ->
|
||||
<logical_or_expression>
|
||||
FIRST Set = {AVID_T, SVID_T, INL_T, SVID_T, STR_T}
|
||||
*/
|
||||
void conditional_expression()
|
||||
{
|
||||
logical_or_expression();
|
||||
gen_incode("PLATY: Conditional expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <input_statement> ->
|
||||
INPUT ( <variable_list> );
|
||||
FIRST Set = {INPUT}
|
||||
*/
|
||||
void input_statement()
|
||||
{
|
||||
match(KW_T, INPUT);
|
||||
match(LPR_T, NO_ATTR);
|
||||
variable_list();
|
||||
match(RPR_T, NO_ATTR);
|
||||
match(EOS_T, NO_ATTR);
|
||||
gen_incode("PLATY: Input statement parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <iteration_statement> ->
|
||||
USING ( <assignment_expression>, <conditional_expression>, <assignment_expression> ) REPEAT { <opt_statements> } ;
|
||||
FIRST Set = {USING}
|
||||
*/
|
||||
void iteration_statement()
|
||||
{
|
||||
match(KW_T, USING);
|
||||
match(LPR_T, NO_ATTR);
|
||||
assignment_expression();
|
||||
match(COM_T, NO_ATTR);
|
||||
assignment_expression();
|
||||
match(RPR_T, NO_ATTR);
|
||||
match(KW_T, REPEAT);
|
||||
match(LBR_T, NO_ATTR);
|
||||
opt_statements();
|
||||
match(RBR_T, NO_ATTR);
|
||||
match(EOS_T, NO_ATTR);
|
||||
gen_incode("PLATY: USING statement parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <logical_and_expression> ->
|
||||
<relational_expression> <logical_and_expression_prime>
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T, SVID_T, STR_T}
|
||||
*/
|
||||
void logical_and_expression()
|
||||
{
|
||||
relational_expression();
|
||||
logical_and_expression_prime();
|
||||
}
|
||||
|
||||
/*
|
||||
* <logical_and_expression_prime> ->
|
||||
.AND. <relational_expression> <logical_and_expression_prime> | E
|
||||
FIRST Set = { .AND., E}
|
||||
*/
|
||||
void logical_and_expression_prime()
|
||||
{
|
||||
if (lookahead.code == LOG_OP_T &&
|
||||
lookahead.attribute.log_op == AND)
|
||||
{
|
||||
match(LOG_OP_T, AND);
|
||||
relational_expression();
|
||||
logical_and_expression_prime();
|
||||
gen_incode("PLATY: Logical AND expression parsed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <logical_or_expression> ->
|
||||
<logical_and_expression> <logical_or_expression_prime>
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T, SVID_T, STR_T}
|
||||
*/
|
||||
void logical_or_expression()
|
||||
{
|
||||
logical_and_expression();
|
||||
logical_or_expression_prime();
|
||||
}
|
||||
|
||||
/*
|
||||
* <logical_or_expression_prime> ->
|
||||
.OR. <logical_and_expression> <logical_or_expression_prime>
|
||||
FIRST Set = { .OR., E }
|
||||
*/
|
||||
void logical_or_expression_prime()
|
||||
{
|
||||
if (lookahead.code == LOG_OP_T &&
|
||||
lookahead.attribute.log_op == OR)
|
||||
{
|
||||
logical_and_expression();
|
||||
logical_or_expression_prime();
|
||||
gen_incode("PLATY: Logical OR expression parsed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <multiplicative_arithmetic_expression> ->
|
||||
<primary_arithmetic_expression> <multiplicative_arithmetic_expression_prime>
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T, (}
|
||||
*/
|
||||
void multiplicative_arithmetic_expression()
|
||||
{
|
||||
primary_arithmetic_expression();
|
||||
multiplicative_arithmetic_expression_prime();
|
||||
}
|
||||
|
||||
/*
|
||||
* <multiplicative_arithmetic_expression_prime> ->
|
||||
<primary_arithmetic_expression> <multiplicative_arithmetic_expression_prime>
|
||||
FIRST Set = {*, /, E}
|
||||
*/
|
||||
void multiplicative_arithmetic_expression_prime()
|
||||
{
|
||||
if (lookahead.code == ART_OP_T &&
|
||||
lookahead.attribute.arr_op != PLUS &&
|
||||
lookahead.attribute.arr_op != MINUS)
|
||||
{
|
||||
match(lookahead.code, lookahead.attribute.arr_op);
|
||||
primary_arithmetic_expression();
|
||||
multiplicative_arithmetic_expression_prime();
|
||||
gen_incode("PLATY: Multiplicative arithmetic expression parsed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <opt_statements> ->
|
||||
<statements> | E
|
||||
FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT, E}
|
||||
*/
|
||||
void opt_statements()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case KW_T:
|
||||
switch (lookahead.attribute.kwt_idx)
|
||||
{
|
||||
case PLATYPUS:
|
||||
case ELSE:
|
||||
case THEN:
|
||||
case REPEAT:
|
||||
gen_incode("PLATY: Opt_statements parsed");
|
||||
return;
|
||||
}
|
||||
case AVID_T:
|
||||
case SVID_T:
|
||||
statements();
|
||||
break;
|
||||
default:
|
||||
gen_incode("PLATY: Opt_statements parsed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <output_statement> ->
|
||||
OUTPUT ( <output_statement_prime> );
|
||||
|
||||
<output_statement_prime> ->
|
||||
<variable_list> | <STR_T>
|
||||
|
||||
FIRST(<output_statement>) = {OUTPUT}
|
||||
FIRST Set = {AVID_T, SVID_T, E}
|
||||
|
||||
This can be done in one function
|
||||
*/
|
||||
void output_statement()
|
||||
{
|
||||
match(KW_T, OUTPUT);
|
||||
match(LPR_T, NO_ATTR);
|
||||
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case AVID_T:
|
||||
case SVID_T:
|
||||
variable_list();
|
||||
break;
|
||||
case STR_T:
|
||||
match(STR_T, NO_ATTR);
|
||||
gen_incode("PLATY: Output list (string literal) parsed");
|
||||
break;
|
||||
default:
|
||||
gen_incode("PLATY: Output list (empty) parsed");
|
||||
}
|
||||
match(RPR_T, NO_ATTR);
|
||||
match(EOS_T, NO_ATTR);
|
||||
gen_incode("PLATY: OUTPUT statement parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <primary_a_relational_expression> ->
|
||||
AVID_T | FPL_T | INL_T
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T}
|
||||
*/
|
||||
void primary_a_relational_expression()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case AVID_T:
|
||||
case FPL_T:
|
||||
case INL_T:
|
||||
match(lookahead.code, NO_ATTR);
|
||||
break;
|
||||
case LOG_OP_T:
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
gen_incode("PLATY: Primary a_relational expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <primary_arithmetic_expression> ->
|
||||
AVID_T | FPL_T | INL_T | ( <arithmetic_expression> )
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T, (}
|
||||
*/
|
||||
void primary_arithmetic_expression()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case AVID_T:
|
||||
case FPL_T:
|
||||
case INL_T:
|
||||
match(lookahead.code, lookahead.attribute.arr_op);
|
||||
break;
|
||||
case LPR_T:
|
||||
match(lookahead.code, lookahead.attribute.arr_op);
|
||||
arithmetic_expression();
|
||||
match(RPR_T, NO_ATTR);
|
||||
default:
|
||||
syn_printe();
|
||||
return;
|
||||
}
|
||||
gen_incode("PLATY: Primary arithmetic expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <primary_s_relational_expression> ->
|
||||
<primary_string_expression>
|
||||
FIRST Set = {SVID_T, STR_T}
|
||||
*/
|
||||
void primary_s_relational_expression()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case SVID_T:
|
||||
case AVID_T:
|
||||
primary_string_expression();
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
gen_incode("PLATY: Primary s_relational expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <primary_string_expression> ->
|
||||
SVID_T | STR_T
|
||||
FIRST Set = {SVID_T, STR_T}
|
||||
*/
|
||||
void primary_string_expression()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case SVID_T:
|
||||
case STR_T:
|
||||
match(lookahead.code, NO_ATTR);
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
gen_incode("PLATY: Primary string expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <program> ->
|
||||
PLATYPUS { <opt_statements> }
|
||||
FIRST Set = {PLATYPUS}
|
||||
*/
|
||||
void program()
|
||||
{
|
||||
match(KW_T, PLATYPUS);
|
||||
match(LBR_T, NO_ATTR);
|
||||
opt_statements();
|
||||
match(RBR_T, NO_ATTR);
|
||||
gen_incode("PLATY: Program parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <relational_expression> ->
|
||||
<primary_a_relational_expression> <primary_a_relational_expression>
|
||||
| <primary_s_relational_expression> <primary_s_relational_expression_prime>
|
||||
FIRST Set = {AVID_T, FPL_T, INL_T, SVID_T, STR_T}
|
||||
*/
|
||||
void relational_expression()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case AVID_T:
|
||||
case FPL_T:
|
||||
case INL_T:
|
||||
primary_a_relational_expression();
|
||||
relational_expression_prime();
|
||||
break;
|
||||
case SVID_T:
|
||||
case STR_T:
|
||||
primary_s_relational_expression();
|
||||
relational_expression_prime_string();
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
gen_incode("PLATY: Relational expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <relational_expression_prime> ->
|
||||
== <primary_a_relational_expression>
|
||||
| <> <primary_a_relational_expression>
|
||||
| > <primary_a_relational_expression>
|
||||
| < <primary_a_relational_expression>
|
||||
FIRST Set = { ==, <>, >, <}
|
||||
*/
|
||||
void relational_expression_prime()
|
||||
{
|
||||
if (lookahead.code == REL_OP_T)
|
||||
{
|
||||
switch (lookahead.attribute.rel_op)
|
||||
{
|
||||
case EQ:
|
||||
case NE:
|
||||
case GT:
|
||||
case LT:
|
||||
match(lookahead.code, lookahead.attribute.arr_op);
|
||||
primary_a_relational_expression();
|
||||
return;
|
||||
}
|
||||
}
|
||||
syn_printe();
|
||||
}
|
||||
|
||||
/*
|
||||
* <relational_expression_prime_string> ->
|
||||
== <primary_s_relational_expression>
|
||||
| <> <primary_s_relational_expression>
|
||||
| > <primary_s_relational_expression>
|
||||
| < <primary_s_relational_expression>
|
||||
FIRST Set = {==, <>, >, <}
|
||||
*/
|
||||
void relational_expression_prime_string()
|
||||
{
|
||||
if (lookahead.code == REL_OP_T)
|
||||
{
|
||||
switch (lookahead.attribute.rel_op)
|
||||
{
|
||||
case EQ:
|
||||
case NE:
|
||||
case GT:
|
||||
case LT:
|
||||
match(lookahead.code, lookahead.attribute.arr_op);
|
||||
primary_s_relational_expression();
|
||||
return;
|
||||
}
|
||||
}
|
||||
syn_printe();
|
||||
}
|
||||
|
||||
/*
|
||||
* <selection_statement> ->
|
||||
IF ( <conditional_expression> ) THEN <opt_statements> ELSE { <opt_statements> } ;
|
||||
FIRST Set = {IF}
|
||||
*/
|
||||
void selection_statement()
|
||||
{
|
||||
match(KW_T, IF);
|
||||
match(LPR_T, NO_ATTR);
|
||||
conditional_expression();
|
||||
match(RPR_T, NO_ATTR);
|
||||
match(KW_T, THEN);
|
||||
opt_statements();
|
||||
match(KW_T, ELSE);
|
||||
match(LBR_T, NO_ATTR);
|
||||
opt_statements();
|
||||
match(RBR_T, NO_ATTR);
|
||||
match(EOS_T, NO_ATTR);
|
||||
gen_incode("PLATY: IF statement parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <statement> ->
|
||||
<assignment_statement>
|
||||
| <selection_statement>
|
||||
| <iteration_statement>
|
||||
| <input_statement>
|
||||
| <output_statement>
|
||||
FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT}
|
||||
*/
|
||||
void statement()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case AVID_T:
|
||||
case SVID_T:
|
||||
assignment_statement();
|
||||
break;
|
||||
case KW_T:
|
||||
switch (lookahead.attribute.kwt_idx)
|
||||
{
|
||||
case IF:
|
||||
selection_statement();
|
||||
break;
|
||||
case USING:
|
||||
iteration_statement();
|
||||
break;
|
||||
case INPUT:
|
||||
input_statement();
|
||||
break;
|
||||
case OUTPUT:
|
||||
output_statement();
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <statements> ->
|
||||
<statement> <statements_prime>
|
||||
FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT}
|
||||
*/
|
||||
void statements()
|
||||
{
|
||||
statement();
|
||||
statements_prime();
|
||||
}
|
||||
|
||||
/*
|
||||
* <statements_prime> ->
|
||||
<statement> <statements_prime> | E
|
||||
FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT}
|
||||
*/
|
||||
void statements_prime()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case KW_T:
|
||||
switch (lookahead.attribute.kwt_idx)
|
||||
{
|
||||
case PLATYPUS:
|
||||
case ELSE:
|
||||
case THEN:
|
||||
case REPEAT:
|
||||
return;
|
||||
}
|
||||
case AVID_T:
|
||||
case SVID_T:
|
||||
statement();
|
||||
statements_prime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <string_expression> ->
|
||||
<primary_string_expression> <string_expression_prime>
|
||||
FIRST Set = {SVID_T, STR_T}
|
||||
*/
|
||||
void string_expression()
|
||||
{
|
||||
primary_string_expression();
|
||||
string_expression_prime();
|
||||
gen_incode("PLATY: String expression parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <string_expression_prime>
|
||||
<< <primary_string_expression> <stirng_expression_prime> | E
|
||||
FIRST Set = {<< , E}
|
||||
*/
|
||||
void string_expression_prime()
|
||||
{
|
||||
if (lookahead.code == SCC_OP_T)
|
||||
{
|
||||
match(SCC_OP_T, NO_ATTR);
|
||||
primary_string_expression();
|
||||
string_expression_prime();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <unary_arithmetic_expression> ->
|
||||
- <primary_arithmetic_expression>
|
||||
| + <primary_arithmetic_expression>
|
||||
FIRST Set = {-, +}
|
||||
*/
|
||||
void unary_arithmetic_expression()
|
||||
{
|
||||
/* Again, GCC complains about PLUS and MINUS enums */
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case ART_OP_T:
|
||||
switch (lookahead.attribute.arr_op)
|
||||
{
|
||||
case MULT:
|
||||
case DIV:
|
||||
syn_printe();
|
||||
return;
|
||||
}
|
||||
match(lookahead.code, lookahead.attribute.arr_op);
|
||||
primary_arithmetic_expression();
|
||||
gen_incode("PLATY: Unary arithmetic expression parsed");
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <variable_identifier> ->
|
||||
AVID_T | SVID_T
|
||||
FIRST Set = {AVID_T, SVID_T}
|
||||
*/
|
||||
void variable_identifier()
|
||||
{
|
||||
switch (lookahead.code)
|
||||
{
|
||||
case AVID_T:
|
||||
case SVID_T:
|
||||
match(lookahead.code, NO_ATTR);
|
||||
break;
|
||||
default:
|
||||
syn_printe();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* <variable_list> ->
|
||||
<variable_identifier> <variable_list_prime>
|
||||
FIRST Set = {AVID_T, SVID_T}
|
||||
*/
|
||||
void variable_list()
|
||||
{
|
||||
variable_identifier();
|
||||
variable_list_prime();
|
||||
gen_incode("PLATY: Variable list parsed");
|
||||
}
|
||||
|
||||
/*
|
||||
* <variable_list_prime> ->
|
||||
, <variable_identifier> <variable_list_prime> | E
|
||||
FIRST Set = {AVID_T, SVID_T, E}
|
||||
*/
|
||||
void variable_list_prime()
|
||||
{
|
||||
if (lookahead.code != COM_T)
|
||||
return;
|
||||
match(COM_T, NO_ATTR);
|
||||
variable_identifier();
|
||||
variable_list_prime();
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/* File Name: parser.h
|
||||
* Parser function definitions for the PLATYPUS Compiler
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Course: CST8152 - Compilers, Lab Section: 011
|
||||
* Date: April 17, 2017
|
||||
* Professor: S^R
|
||||
* Version: 0.1
|
||||
*/
|
||||
#ifndef PARSER_H_
|
||||
#define PARSER_H_
|
||||
|
||||
#include "token.h"
|
||||
#include "stable.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/* Keyword enum to match kw_table in table.h */
|
||||
enum kw {
|
||||
NO_ATTR = -1,
|
||||
ELSE,
|
||||
IF,
|
||||
INPUT,
|
||||
OUTPUT,
|
||||
PLATYPUS,
|
||||
REPEAT,
|
||||
THEN,
|
||||
USING
|
||||
};
|
||||
|
||||
/* Main parser functions */
|
||||
void parser(Buffer* const);
|
||||
void gen_incode(char*);
|
||||
void match(int, int);
|
||||
void syn_eh(int);
|
||||
void syn_printe(void);
|
||||
|
||||
/* Literally the entire grammar */
|
||||
void additive_arithmetic_expression(void);
|
||||
void additive_arithmetic_expression_prime(void);
|
||||
void arithmetic_expression(void);
|
||||
void assignment_expression(void);
|
||||
void assignment_statement(void);
|
||||
void conditional_expression(void);
|
||||
void input_statement(void);
|
||||
void iteration_statement(void);
|
||||
void logical_and_expression(void);
|
||||
void logical_and_expression_prime(void);
|
||||
void logical_or_expression(void);
|
||||
void logical_or_expression_prime(void);
|
||||
void multiplicative_arithmetic_expression(void);
|
||||
void multiplicative_arithmetic_expression_prime(void);
|
||||
void opt_statements(void);
|
||||
void output_statement(void);
|
||||
void primary_a_relational_expression(void);
|
||||
void primary_arithmetic_expression(void);
|
||||
void primary_s_relational_expression(void);
|
||||
void primary_string_expression(void);
|
||||
void program(void);
|
||||
void relational_expression(void);
|
||||
void relational_expression_prime(void);
|
||||
void relational_expression_prime_string(void);
|
||||
void selection_statement(void);
|
||||
void statement(void);
|
||||
void statements(void);
|
||||
void statements_prime(void);
|
||||
void string_expression(void);
|
||||
void string_expression_prime(void);
|
||||
void unary_arithmetic_expression(void);
|
||||
void variable_identifier(void);
|
||||
void variable_list(void);
|
||||
void variable_list_prime(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,266 @@
|
|||
/* File name: platy.c
|
||||
* Purpose:This is the main program for Assignment#4 - Platypus Parser
|
||||
* CST8152 - Compilers
|
||||
* Version: 1.17.01
|
||||
* Author: S^R
|
||||
* Date: 18 March 2017
|
||||
*/
|
||||
|
||||
/* The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects
|
||||
* to suppress the warnings about using "unsafe" functions like fopen()
|
||||
* and standard sting library functions defined in string.h.
|
||||
* The define does not have any effect in other compilers projects.
|
||||
*/
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* Constants for calls to exit()*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "token.h"
|
||||
#include "stable.h" /*Do not remove this line. SiR */
|
||||
#include "stable.h" /*Do not remove this line. SiR */
|
||||
/* Input buffer parameters */
|
||||
#define INIT_CAPACITY 200 /* initial buffer capacity */
|
||||
#define INC_FACTOR 15 /* increment factor */
|
||||
/* String Literal Table parameters */
|
||||
#define STR_INIT_CAPACITY 100 /* initial string literal table capacity */
|
||||
#define STR_CAPACITY_INC 50 /* initial string literal table capacity inc */
|
||||
/* Symbol Table default size */
|
||||
#define ST_DEF_SIZE 100
|
||||
|
||||
/*check for ANSI C compliancy */
|
||||
#define ANSI_C 0
|
||||
#if defined(__STDC__)
|
||||
#undef ANSI_C
|
||||
#define ANSI_C 1
|
||||
#endif
|
||||
|
||||
/* Global objects - variables */
|
||||
static Buffer *sc_buf; /* pointer to input (source) buffer */
|
||||
Buffer * str_LTBL; /* this buffer implements String Literal Table */
|
||||
/* it is used as a repository for string literals */
|
||||
int scerrnum; /* run-time error number = 0 by default (ANSI) */
|
||||
STD sym_table; /* Symbol Table Descriptor */
|
||||
/*external objects */
|
||||
extern int synerrno /* number of syntax errors reported by the parser */;
|
||||
extern int line; /* source code line number - defined in scanner.c */
|
||||
/* function declarations (prototypes) */
|
||||
extern void parser(Buffer * sc_buf);
|
||||
/* For testing purposes */
|
||||
extern void scanner_init(Buffer * sc_buf);
|
||||
/* extern Token malpar_next_token(Buffer * sc_buf);*/
|
||||
|
||||
void err_printf(char *fmt, ...);
|
||||
void display (Buffer *ptrBuffer);
|
||||
long get_filesize(char *fname);
|
||||
void garbage_collect(void);
|
||||
|
||||
|
||||
/* main function takes a PLATYPUS source file as
|
||||
* an argument at the command line.
|
||||
* usage: parser source_file_name [-stz size][-sts:A | -sts:D]
|
||||
*/
|
||||
int main(int argc, char ** argv){
|
||||
|
||||
FILE *fi; /* input file handle */
|
||||
int loadsize = 0; /*the size of the file loaded in the buffer */
|
||||
int st_def_size = ST_DEF_SIZE; /* Sumbol Table default size */
|
||||
char sort_st = 0; /*Symbol Table sort switch */
|
||||
int ansi_c = !ANSI_C; /* ANSI C flag */
|
||||
/* Check if the compiler option is set to compile ANSI C */
|
||||
/* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/
|
||||
if(ansi_c){
|
||||
err_printf("Date: %s Time: %s",__DATE__, __TIME__);
|
||||
err_printf("ERROR: Compiler is not ANSI C compliant!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*check for correct arrguments - source file name */
|
||||
if (argc <= 1){
|
||||
/* __DATE__, __TIME__, __LINE__, __FILE__ are predefined preprocessor macros*/
|
||||
err_printf("Date: %s Time: %s",__DATE__, __TIME__);
|
||||
err_printf("Runtime error at line %d in file %s", __LINE__, __FILE__);
|
||||
err_printf("%s%s%s",argv[0],": ","Missing source file name.");
|
||||
err_printf("%s%s%s","Usage: ", "parser", " source_file_name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* check for optional switches - symbol table size and/or sort */
|
||||
if (argc == 3){
|
||||
if (strcmp(argv[2],"-sts:A") && strcmp(argv[2],"-sts:D") ){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(strcmp(argv[2],"-sts:A"))
|
||||
sort_st = 'D';
|
||||
else
|
||||
sort_st = 'A';
|
||||
}
|
||||
/* symbol table size specified */
|
||||
if (argc == 4){
|
||||
if (strcmp(argv[2],"-stz")){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* convert the symbol table size */
|
||||
st_def_size = atoi(argv[3]);
|
||||
if (st_def_size <= 0){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (argc == 5){
|
||||
if (strcmp(argv[2],"-stz")){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* convert the symbol table size */
|
||||
st_def_size = atoi(argv[3]);
|
||||
if (st_def_size <= 0){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strcmp(argv[4],"-sts:A")&& strcmp(argv[4],"-sts:D") ){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(strcmp(argv[4],"-sts:A"))
|
||||
sort_st = 'D';
|
||||
else
|
||||
sort_st = 'A';
|
||||
}
|
||||
/* create a source code input buffer - multiplicative mode */
|
||||
sc_buf = b_create(INIT_CAPACITY,INC_FACTOR,'m');
|
||||
if (sc_buf == NULL){
|
||||
err_printf("%s%s%s",argv[0],": ","Could not create source buffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* create symbol table */
|
||||
sym_table = st_create(st_def_size);
|
||||
if (!sym_table.st_size){
|
||||
err_printf("%s%s%s",argv[0],": ","Could not create symbol table");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*open source file */
|
||||
if ((fi = fopen(argv[1],"r")) == NULL){
|
||||
err_printf("%s%s%s%s",argv[0],": ", "Cannot open file: ",argv[1]);
|
||||
exit (1);
|
||||
}
|
||||
/* load source file into input buffer */
|
||||
printf("Reading file %s ....Please wait\n",argv[1]);
|
||||
loadsize = b_load (fi,sc_buf);
|
||||
if(loadsize == R_FAIL1)
|
||||
err_printf("%s%s%s",argv[0],": ","Error in loading buffer.");
|
||||
|
||||
/* close source file */
|
||||
fclose(fi);
|
||||
/*find the size of the file */
|
||||
if (loadsize == LOAD_FAIL){
|
||||
printf("The input file %s %s\n", argv[1],"is not completely loaded.");
|
||||
printf("Input file size: %ld\n", get_filesize(argv[1]));
|
||||
}
|
||||
/* pack and display the source buffer */
|
||||
|
||||
if(b_pack(sc_buf)){
|
||||
display(sc_buf);
|
||||
}
|
||||
/* create string Literal Table */
|
||||
str_LTBL = b_create(INIT_CAPACITY,INC_FACTOR,'a');
|
||||
if (str_LTBL == NULL){
|
||||
err_printf("%s%s%s",argv[0],": ","Could not create string buffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*registrer exit function */
|
||||
atexit(garbage_collect);
|
||||
|
||||
/*Testbed for buffer, scanner,symbol table and parser*/
|
||||
|
||||
/* Initialize scanner */
|
||||
scanner_init(sc_buf);
|
||||
/* Add SEOF (EOF) to input buffer */
|
||||
b_addc(sc_buf, EOF);
|
||||
/* Start parsing */
|
||||
printf("\nParsing the source file...\n\n");
|
||||
|
||||
parser(sc_buf);
|
||||
|
||||
/* print Symbol Table */
|
||||
/*
|
||||
if(sym_table.st_size && sort_st){
|
||||
st_print(sym_table);
|
||||
if(sort_st){
|
||||
printf("\nSorting symbol table...\n");
|
||||
st_sort(sym_table,sort_st);
|
||||
st_print(sym_table);
|
||||
}
|
||||
}
|
||||
*/
|
||||
return (EXIT_SUCCESS); /* same effect as exit(0) */
|
||||
}/*end of main */
|
||||
|
||||
/* Error printing function with variable number of arguments
|
||||
*/
|
||||
void err_printf( char *fmt, ... ){
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Move to new line */
|
||||
if( strchr(fmt,'\n') == NULL )
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
/* The function return the size of an open file
|
||||
*/
|
||||
long get_filesize(char *fname){
|
||||
FILE *input;
|
||||
long flength;
|
||||
input = fopen(fname, "r");
|
||||
if(input == NULL){
|
||||
err_printf("%s%s","Cannot open file: ",fname);
|
||||
return 0;
|
||||
}
|
||||
fseek(input, 0L, SEEK_END);
|
||||
flength = ftell(input);
|
||||
fclose(input);
|
||||
return flength;
|
||||
}
|
||||
|
||||
/* The function display buffer contents
|
||||
*/
|
||||
void display (Buffer *ptrBuffer){
|
||||
printf("\nPrinting input buffer parameters:\n\n");
|
||||
printf("The capacity of the buffer is: %d\n",b_capacity(ptrBuffer));
|
||||
printf("The current size of the buffer is: %d\n",b_size(ptrBuffer));
|
||||
printf("\nPrinting input buffer contents:\n\n");
|
||||
b_print(ptrBuffer);
|
||||
}
|
||||
|
||||
/* the functions frees the allocated memory */
|
||||
void garbage_collect(void){
|
||||
if(synerrno)
|
||||
printf("\nSyntax errors: %d\n",synerrno);
|
||||
printf("\nCollecting garbage...\n");
|
||||
b_free(sc_buf);
|
||||
b_free(str_LTBL);
|
||||
st_destroy(sym_table);
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* File name: platy_bt.c
|
||||
* Purpose:This is the main program for Assignment #1, CST8152, Winter 17
|
||||
* Version: 1.17.1
|
||||
* Author: Svillen Ranev
|
||||
* Author: S^R
|
||||
* Date: 9 January 2017
|
||||
*/
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Purpose:This is the main program for Assignment #2 - Scanner
|
||||
* CST8152 - Compilers
|
||||
* Version: 1.17.1
|
||||
* Author: Svillen Ranev
|
||||
* Author: S^R
|
||||
* Date: 30 January 2017
|
||||
*/
|
||||
|
||||
|
@ -201,10 +201,10 @@ void print_token(Token t){
|
|||
printf("SEOF_T\n" );
|
||||
break;
|
||||
case AVID_T:
|
||||
printf("AVID_T\t\t%s\n",t.attribute.vid_lex);
|
||||
printf("AVID_T\t\t%d\n",t.attribute.vid_offset);
|
||||
break;
|
||||
case SVID_T:
|
||||
printf("SVID_T\t\t%s\n",t.attribute.vid_lex);
|
||||
printf("SVID_T\t\t%d\n",t.attribute.vid_offset);
|
||||
break;
|
||||
case FPL_T:
|
||||
printf("FPL_T\t\t%f\n",t.attribute.flt_value);
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
/* File name: platy_tt.c
|
||||
* Purpose:This is the main program for Assignment #3 - Symbol Table
|
||||
* CST8152 - Compilers
|
||||
* Version: 1.17.01
|
||||
* Author: S^R
|
||||
* Date: 1 March 2017
|
||||
*/
|
||||
|
||||
/* The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects
|
||||
* to suppress the warnings about using "unsafe" functions like fopen()
|
||||
* and standard sting library functions defined in string.h.
|
||||
* The define does not have any effect in other compiler projects.
|
||||
*/
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* Constants for calls to exit()*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "token.h"
|
||||
#include "stable.h" /*Do not remove this line. SiR */
|
||||
|
||||
/* constant definitions */
|
||||
/* Input buffer parameters */
|
||||
#define INIT_CAPACITY 200 /* initial buffer capacity */
|
||||
#define INC_FACTOR 15 /* increment factor */
|
||||
/* String Literal Table parameters */
|
||||
#define STR_INIT_CAPACITY 100 /* initial string literal table capacity */
|
||||
#define STR_CAPACITY_INC 50 /* initial string literal table capacity inc */
|
||||
/* Symbol Table default size */
|
||||
#define ST_DEF_SIZE 100
|
||||
|
||||
/*check for ANSI C compliancy */
|
||||
#define ANSI_C 0
|
||||
#if defined(__STDC__)
|
||||
#undef ANSI_C
|
||||
#define ANSI_C 1
|
||||
#endif
|
||||
|
||||
/* Global objects - variables */
|
||||
|
||||
static Buffer *sc_buf; /* pointer to input (source) buffer */
|
||||
Buffer * str_LTBL; /* this buffer implements String Literal Table */
|
||||
/* it is used as a repository for string literals */
|
||||
int scerrnum; /* run-time error number = 0 by default (ANSI) */
|
||||
STD sym_table; /* Symbol Table Descriptor */
|
||||
|
||||
/*external objects */
|
||||
extern int line; /* source code line numbers - defined in scanner.c */
|
||||
extern int scanner_init(Buffer * sc_buf);
|
||||
extern Token malar_next_token(Buffer * sc_buf);
|
||||
/*function declarations */
|
||||
void err_printf(char *fmt, ...);
|
||||
void display (Buffer *ptrBuffer);
|
||||
long get_filesize(char *fname);
|
||||
void garbage_collect(void);
|
||||
|
||||
/* The main function takes a PLATYPUS source file and optional switches
|
||||
* as command line arguments.
|
||||
* usage: stable source_file_name [-stz size][-sts:A | -sts:D]
|
||||
*/
|
||||
int main(int argc, char ** argv){
|
||||
|
||||
FILE *fi; /* input file handle */
|
||||
Token t; /* token produced by the scanner */
|
||||
int loadsize = 0; /*the size of the file loaded in the buffer */
|
||||
int st_def_size = ST_DEF_SIZE; /* Sumbol Table default size */
|
||||
char sort_st = 0; /*Symbol Table sort switch */
|
||||
int ansi_c = !ANSI_C; /* ANSI C flag */
|
||||
/* Check if the compiler option is set to compile ANSI C */
|
||||
/* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/
|
||||
if(ansi_c){
|
||||
err_printf("Date: %s Time: %s",__DATE__, __TIME__);
|
||||
err_printf("ERROR: Compiler is not ANSI C compliant!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*check for correct arrguments - source file name */
|
||||
if (argc <= 1){
|
||||
/* __DATE__, __TIME__, __LINE__, __FILE__ are predefined preprocessor macros*/
|
||||
err_printf("Date: %s Time: %s",__DATE__, __TIME__);
|
||||
err_printf("Runtime error at line %d in file %s", __LINE__, __FILE__);
|
||||
err_printf("%s%s%s",argv[0],": ","Missing source file name.");
|
||||
err_printf("%s%s%s","Usage: ", "stable", " source_file_name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* check for optional switches - symbol table size and/or sort */
|
||||
if (argc == 3){
|
||||
if (strcmp(argv[2],"-sts:A") && strcmp(argv[2],"-sts:D") ){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/*set sort switch*/
|
||||
if(strcmp(argv[2],"-sts:A"))
|
||||
sort_st = 'D';
|
||||
else
|
||||
sort_st = 'A';
|
||||
}
|
||||
/* symbol table size specified */
|
||||
if (argc == 4){
|
||||
if (strcmp(argv[2],"-stz")){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* convert the symbol table size */
|
||||
st_def_size = atoi(argv[3]);
|
||||
if (st_def_size <= 0){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (argc == 5){
|
||||
if (strcmp(argv[2],"-stz")){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* convert the symbol table size */
|
||||
st_def_size = atoi(argv[3]);
|
||||
if (st_def_size <= 0){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strcmp(argv[4],"-sts:A")&& strcmp(argv[4],"-sts:D") ){
|
||||
err_printf("%s%s%s",argv[0],": ","Invalid switch.");
|
||||
err_printf("%s%s\b\b\b\b%s","Usage: ", argv[0], " source file name [-stz size][-sts:A | -sts:D]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(strcmp(argv[4],"-sts:A"))
|
||||
sort_st = 'D';
|
||||
else
|
||||
sort_st = 'A';
|
||||
}
|
||||
|
||||
/* create a source code input buffer - multiplicative mode */
|
||||
sc_buf = b_create(INIT_CAPACITY,INC_FACTOR,'m');
|
||||
if (sc_buf == NULL){
|
||||
err_printf("%s%s%s",argv[0],": ","Could not create source buffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* create symbol table */
|
||||
sym_table = st_create(st_def_size);
|
||||
if (!sym_table.st_size){
|
||||
err_printf("%s%s%s",argv[0],": ","Could not create symbol table");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*open source file */
|
||||
if ((fi = fopen(argv[1],"r")) == NULL){
|
||||
err_printf("%s%s%s%s",argv[0],": ", "Cannot open file: ",argv[1]);
|
||||
exit (1);
|
||||
}
|
||||
/* load source file into input buffer */
|
||||
printf("Reading file %s ....Please wait\n",argv[1]);
|
||||
loadsize = b_load (fi,sc_buf);
|
||||
if(loadsize == R_FAIL1)
|
||||
err_printf("%s%s%s",argv[0],": ","Error in loading buffer.");
|
||||
|
||||
/* close source file */
|
||||
fclose(fi);
|
||||
/*find the size of the file */
|
||||
if (loadsize == LOAD_FAIL){
|
||||
printf("The input file %s %s\n", argv[1],"is not completely loaded.");
|
||||
printf("Input file size: %ld\n", get_filesize(argv[1]));
|
||||
}
|
||||
/* pack and display the source buffer */
|
||||
|
||||
if(b_pack(sc_buf)){
|
||||
display(sc_buf);
|
||||
}
|
||||
|
||||
/* create string Literal Table */
|
||||
str_LTBL = b_create(INIT_CAPACITY,INC_FACTOR,'a');
|
||||
if (str_LTBL == NULL){
|
||||
err_printf("%s%s%s",argv[0],": ","Could not create string buffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*registrer exit function */
|
||||
atexit(garbage_collect);
|
||||
|
||||
/*Testbed for the scanner and the symbol table*/
|
||||
/* add SEOF to input program buffer*/
|
||||
b_addc(sc_buf,'\0');
|
||||
|
||||
/* Initialize the scanner*/
|
||||
if(scanner_init(sc_buf)){;
|
||||
err_printf("%s%s%s",argv[0],": ","Empty program buffer - scanning canceled");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Scanning source file...\n\n");
|
||||
|
||||
do{
|
||||
t= malar_next_token(sc_buf);
|
||||
}while(t.code != SEOF_T);
|
||||
/* print Symbol Table */
|
||||
if(sym_table.st_size){
|
||||
st_print(sym_table);
|
||||
if(sort_st){
|
||||
printf("\nSorting symbol table...\n");
|
||||
st_sort(sym_table,sort_st);
|
||||
st_print(sym_table);
|
||||
}
|
||||
}
|
||||
/*Test bed for type and update functions */
|
||||
|
||||
/*Test bed for bonus*/
|
||||
return (0); /* same effect as exit(EXIT_SUCCESS) */
|
||||
}
|
||||
|
||||
/* Error printing function with variable number of arguments
|
||||
*/
|
||||
void err_printf( char *fmt, ... ){
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Move to new line */
|
||||
if( strchr(fmt,'\n') == NULL )
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
/* The function return the size of an open file
|
||||
*/
|
||||
long get_filesize(char *fname){
|
||||
FILE *input;
|
||||
long flength;
|
||||
input = fopen(fname, "r");
|
||||
if(input == NULL){
|
||||
err_printf("%s%s","Cannot open file: ",fname);
|
||||
return 0;
|
||||
}
|
||||
fseek(input, 0L, SEEK_END);
|
||||
flength = ftell(input);
|
||||
fclose(input);
|
||||
return flength;
|
||||
}
|
||||
|
||||
/* The function display buffer contents
|
||||
*/
|
||||
void display (Buffer *ptrBuffer){
|
||||
printf("\nPrinting input buffer parameters:\n\n");
|
||||
printf("The capacity of the buffer is: %d\n",b_capacity(ptrBuffer));
|
||||
printf("The current size of the buffer is: %d\n",b_size(ptrBuffer));
|
||||
printf("The reallocation flag is: %d\n",b_rflag(ptrBuffer));
|
||||
printf("\nPrinting input buffer contents:\n\n");
|
||||
b_print(ptrBuffer);
|
||||
}
|
||||
|
||||
/* The function frees all dynamically allocated memory.
|
||||
This function is always called
|
||||
despite how the program terminates - normally or abnormally.
|
||||
*/
|
||||
void garbage_collect(void){
|
||||
printf("\nCollecting garbage...\n");
|
||||
b_free(sc_buf);
|
||||
b_free(str_LTBL);
|
||||
st_destroy(sym_table);
|
||||
}
|
79
scanner.c
79
scanner.c
|
@ -5,7 +5,7 @@
|
|||
* scanner_init() must be called before using the scanner.
|
||||
* The file is incomplete;
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Provided by: Svillen Ranev
|
||||
* Provided by: S^R
|
||||
* Version: 1.17.1
|
||||
* Date: 30 January 2017
|
||||
* Function list: scanner_init, malar_next_token, get_next_state, char_class,
|
||||
|
@ -32,6 +32,7 @@
|
|||
/* project header files */
|
||||
#include "buffer.h"
|
||||
#include "token.h"
|
||||
#include "stable.h"
|
||||
#include "table.h"
|
||||
|
||||
#define DEBUG /* for conditional processing */
|
||||
|
@ -44,8 +45,8 @@
|
|||
It is defined in platy_st.c */
|
||||
extern Buffer * str_LTBL; /*String literal table */
|
||||
int line; /* current line number of the source code */
|
||||
extern int scerrnum; /* defined in platy_st.c - run-time error number */
|
||||
|
||||
extern int synerrno; /* defined in platy_st.c - run-time error number */
|
||||
extern STD sym_table; /* symbol table */
|
||||
/* Local(file) global objects - variables */
|
||||
static Buffer *lex_buf; /*pointer to temporary lexeme buffer*/
|
||||
|
||||
|
@ -73,7 +74,7 @@ int scanner_init(Buffer * sc_buf) {
|
|||
b_reset(str_LTBL);
|
||||
line = 1;
|
||||
return EXIT_SUCCESS;/*0*/
|
||||
/* scerrnum = 0; *//*no need - global ANSI C */
|
||||
/* synerrno = 0; *//*no need - global ANSI C */
|
||||
}
|
||||
/* Reads the source code buffer and generates a token
|
||||
* Author: Victor Fernandes
|
||||
|
@ -106,7 +107,8 @@ Token malar_next_token(Buffer * sc_buf)
|
|||
pBuffer err_lex_buf;
|
||||
|
||||
if (sc_buf == NULL) {
|
||||
scerrnum = 1;
|
||||
synerrno
|
||||
= 1;
|
||||
return aa_table[ES]("RUN TIME ERROR: "); /* WHOOPS */
|
||||
}
|
||||
|
||||
|
@ -174,7 +176,7 @@ Token malar_next_token(Buffer * sc_buf)
|
|||
if (c == '<') { /* It's a comment line */
|
||||
/* Consume chars until line ends */
|
||||
for (; c != '\0' && c != '\r' && c != '\n' && c != 255; c = b_getc(sc_buf));
|
||||
line++;
|
||||
++line;
|
||||
continue;
|
||||
}
|
||||
else { /* Bad character, pump out an error token */
|
||||
|
@ -186,6 +188,7 @@ Token malar_next_token(Buffer * sc_buf)
|
|||
t.attribute.err_lex[2] = '\0';
|
||||
/* Consume the rest of the caracters to ignore the line*/
|
||||
for (; c != '\0' && c != '\r' && c != '\n' && c != 255; c = b_getc(sc_buf));
|
||||
++line;
|
||||
return t;
|
||||
}
|
||||
case '=':
|
||||
|
@ -265,7 +268,7 @@ Token malar_next_token(Buffer * sc_buf)
|
|||
|
||||
b_retract_to_mark(sc_buf);
|
||||
|
||||
lex_buf = b_create(1, 1, 'a');
|
||||
lex_buf = b_create(20, 8, 'a');
|
||||
|
||||
/* Copy the scanned lexeme into lexical buffer */
|
||||
for (; lexstart < lexend; ++lexstart) {
|
||||
|
@ -277,7 +280,8 @@ Token malar_next_token(Buffer * sc_buf)
|
|||
t = aa_table[state](b_setmark(lex_buf, 0));
|
||||
}
|
||||
else {
|
||||
scerrnum = 1;
|
||||
synerrno
|
||||
= 1;
|
||||
t = aa_table[ES]("RUN TIME ERROR: ");
|
||||
return t;
|
||||
}
|
||||
|
@ -370,9 +374,10 @@ int char_class(char c)
|
|||
Return values: Token
|
||||
*/
|
||||
Token aa_func02(char lexeme[]) {
|
||||
unsigned int i, kw_idx; /* Variable to contain keyword table index */
|
||||
unsigned kw_idx, offset; /* Variable to contain keyword table index */
|
||||
Token t;
|
||||
char* temp_str;
|
||||
char v_type;
|
||||
/*char* temp_str;*/
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Lexeme: '%s'\n", lexeme);
|
||||
|
@ -387,17 +392,11 @@ Token aa_func02(char lexeme[]) {
|
|||
|
||||
/* Not a keyword? Must be AVID*/
|
||||
t.code = AVID_T;
|
||||
if ((temp_str = (char*)calloc(VID_LEN + 1, sizeof(char))) == NULL) {
|
||||
/*if ((temp_str = (char*)calloc(VID_LEN + 1, sizeof(char))) == NULL) {
|
||||
return aa_table[ES]("RUN TIME ERROR: ");
|
||||
}
|
||||
|
||||
for (i = 0; i < (VID_LEN) && i < strlen(lexeme); i++) {
|
||||
temp_str[i] = lexeme[i];
|
||||
}
|
||||
|
||||
strncpy(t.attribute.vid_lex, temp_str, VID_LEN);
|
||||
t.attribute.vid_lex[strlen(temp_str)] = '\0';
|
||||
free(temp_str);
|
||||
strncpy(temp_str, lexeme, VID_LEN);*/
|
||||
|
||||
switch (lexeme[0]) { /* Read first character of lexeme for implicit type (not used yet?)*/
|
||||
case 'i':
|
||||
|
@ -405,11 +404,21 @@ Token aa_func02(char lexeme[]) {
|
|||
case 'd':
|
||||
case 'n':
|
||||
/* Integer */
|
||||
v_type = 'I';
|
||||
break;
|
||||
default:
|
||||
/* Floating point*/
|
||||
v_type = 'F';
|
||||
break;
|
||||
}
|
||||
if ((offset = st_install(sym_table, lexeme, v_type, line)) == -1){
|
||||
printf("Error: Install failed - Symbol Table is full.\n");
|
||||
st_store(sym_table);
|
||||
free(lexeme);
|
||||
exit(1);
|
||||
}
|
||||
t.attribute.vid_offset = offset;
|
||||
/*free(temp_str);*/
|
||||
|
||||
return t;
|
||||
}
|
||||
|
@ -424,24 +433,25 @@ Token aa_func02(char lexeme[]) {
|
|||
*/
|
||||
Token aa_func03(char lexeme[]) {
|
||||
Token t;
|
||||
unsigned int i;
|
||||
unsigned offset;/*
|
||||
char* temp_str;
|
||||
if ((temp_str = (char*)calloc(VID_LEN + 2, sizeof(char))) == NULL) {
|
||||
return aa_table[ES]("RUN TIME ERROR: ");
|
||||
}*/
|
||||
|
||||
/*strncpy(temp_str, lexeme, VID_LEN);*/
|
||||
lexeme[strlen(lexeme) - 1] = '#'; /* Add # to end of the SVID */
|
||||
|
||||
if ((offset = st_install(sym_table, lexeme, 'S', line)) == -1){
|
||||
printf("Error: Install failed - Symbol Table is full.\n");
|
||||
st_store(sym_table);
|
||||
free(lexeme);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < (VID_LEN) && i < strlen(lexeme); i++) {
|
||||
temp_str[i] = lexeme[i];
|
||||
}
|
||||
|
||||
temp_str[strlen(temp_str) - 1] = '#'; /* Add# to end of the SVID */
|
||||
temp_str[strlen(temp_str)] = '\0';
|
||||
|
||||
strncpy(t.attribute.vid_lex, temp_str, VID_LEN);
|
||||
t.attribute.vid_lex[strlen(temp_str)] = '\0';
|
||||
free(temp_str);
|
||||
|
||||
t.code = SVID_T;
|
||||
t.attribute.vid_offset = offset;
|
||||
/*free(temp_str);*/
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -510,7 +520,7 @@ Token aa_func10(char lexeme[]) {
|
|||
t.code = INL_T;
|
||||
new_olval = atool(lexeme);
|
||||
|
||||
if (new_olval < 0 || new_olval > 32767) {
|
||||
if (new_olval < 0 || new_olval > PLT_SHRT_MAX) {
|
||||
t = aa_table[ES](lexeme);
|
||||
return t;
|
||||
}
|
||||
|
@ -549,11 +559,12 @@ Token aa_func12(char lexeme[]) {
|
|||
*/
|
||||
Token aa_func13(char lexeme[]) {
|
||||
Token t;
|
||||
unsigned int i;
|
||||
unsigned int i = strlen(lexeme);
|
||||
t.code = ERR_T;
|
||||
/*
|
||||
for (i = 0; i < (ERR_LEN) && i < strlen(lexeme); i++)
|
||||
t.attribute.err_lex[i] = lexeme[i];
|
||||
|
||||
*/
|
||||
if (strlen(lexeme) > ERR_LEN) {
|
||||
t.attribute.err_lex[i - 1] = '.';
|
||||
t.attribute.err_lex[i - 2] = '.';
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
/* Filename: stable.c
|
||||
* Compiler: msvc (Visual Studio 2015)
|
||||
* Store and provide functions for the symbol table database
|
||||
* CST8152, Assignment #3
|
||||
* Professor: S^R
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.1
|
||||
* Date: 24 March 2017
|
||||
*/
|
||||
#include "stable.h"
|
||||
|
||||
#define PLSBD_SZ 128
|
||||
#define PLSBD_INC 64
|
||||
|
||||
#define DEBUG
|
||||
#undef DEBUG
|
||||
|
||||
/* Forward function declarations */
|
||||
static void st_setsize(void);
|
||||
static void st_incoffset(void);
|
||||
extern STD sym_table;
|
||||
|
||||
/* Create a symbol table
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: malloc, b_create, free
|
||||
* Parameters:
|
||||
int - size of the symbol table
|
||||
* Return value:
|
||||
STD - The symbol table
|
||||
* Algorithm:
|
||||
*/
|
||||
STD st_create(int st_size) {
|
||||
STD new_stable;
|
||||
|
||||
new_stable.plsBD = NULL;
|
||||
new_stable.pstvr = (STVR*)malloc((size_t)st_size * sizeof(STVR));
|
||||
if (st_size <= 0 || (new_stable.pstvr == NULL)) {
|
||||
new_stable.st_size = 0;
|
||||
}
|
||||
new_stable.plsBD = b_create(PLSBD_SZ, PLSBD_INC, 'a');
|
||||
if (new_stable.plsBD == NULL) {
|
||||
free(new_stable.plsBD);
|
||||
new_stable.st_size = 0;
|
||||
}
|
||||
|
||||
new_stable.st_size = st_size;
|
||||
new_stable.st_offset = 0;
|
||||
|
||||
return new_stable;
|
||||
}
|
||||
|
||||
/* Install a new entry in the symbol table
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: st_lookup, b_setmark, b_size, b_addc, b_rflag, st_incoffset
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
char - The lexeme to be stored
|
||||
char - the type of the lexeme
|
||||
int - the line in the source file where the lexeme was found
|
||||
* Return value:
|
||||
int - the element offset of where the symbol table is pointing to
|
||||
-1 if an internal error occurs
|
||||
* Algorithm:
|
||||
*/
|
||||
int st_install(STD s_table, char *lexeme, char type, int line) {
|
||||
int offset = -1, i, j, lex_len, lex_offset = 0, flag = 0;
|
||||
|
||||
/* Cannot add new entry, table full */
|
||||
if (s_table.st_offset >= s_table.st_size)
|
||||
return -1;
|
||||
|
||||
/* Look for an existing entry in the symbol table */
|
||||
if (s_table.st_offset > 0)
|
||||
offset = st_lookup(s_table, lexeme);
|
||||
|
||||
if (offset > -1)
|
||||
return offset;
|
||||
|
||||
/* Add lexeme to the symbol table's lexeme buffer */
|
||||
lex_len = strlen(lexeme);
|
||||
for (i = 0; i <= lex_len; ++i) {
|
||||
if (!b_addc(s_table.plsBD, lexeme[i]))
|
||||
return -1;
|
||||
if (b_rflag(s_table.plsBD) == SET_R_FLAG) { /* Trigger reassignment loop once lexeme is stored */
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
/* If reallocation happened...*/
|
||||
if (flag == 1) {
|
||||
for (j = 0; j < s_table.st_offset; ++j) {
|
||||
s_table.pstvr[j].plex = b_setmark(s_table.plsBD, (short) s_table.pstvr[j].i_value.str_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set proper pointer values on symbol table */
|
||||
/* Get buffer offset location of the lexeme stored */
|
||||
lex_offset = b_size(s_table.plsBD) - (strlen(lexeme) + 1);
|
||||
|
||||
s_table.pstvr[s_table.st_offset].plex = b_setmark(s_table.plsBD, (short) lex_offset);
|
||||
s_table.pstvr[s_table.st_offset].o_line = line;
|
||||
s_table.pstvr[s_table.st_offset].i_value.str_offset = lex_offset;
|
||||
|
||||
/* Set the default mask before setting the rest of the masks */
|
||||
s_table.pstvr[s_table.st_offset].status_field = DFT_MASK;
|
||||
|
||||
switch (type) {
|
||||
case 'I': /* Integer type */
|
||||
s_table.pstvr[s_table.st_offset].status_field |= INT_MASK;
|
||||
s_table.pstvr[s_table.st_offset].i_value.int_val = 0;
|
||||
|
||||
break;
|
||||
case 'F': /* Floating point type */
|
||||
s_table.pstvr[s_table.st_offset].status_field |= FLT_MASK;
|
||||
s_table.pstvr[s_table.st_offset].i_value.fpl_val = 0.0f;
|
||||
break;
|
||||
case 'S': /* String type */
|
||||
s_table.pstvr[s_table.st_offset].status_field |= STR_MASK;
|
||||
s_table.pstvr[s_table.st_offset].i_value.int_val = -1;
|
||||
s_table.pstvr[s_table.st_offset].i_value.fpl_val = -1.0f;
|
||||
break;
|
||||
default:
|
||||
return -1; /* Not supposed to fall into here */
|
||||
}
|
||||
|
||||
/* Increment the symbol table offset */
|
||||
st_incoffset();
|
||||
return s_table.st_offset;
|
||||
|
||||
}
|
||||
|
||||
/* Look up the lexeme string in the symbol table's buffer
|
||||
* Author: Victor Fernandes
|
||||
* Version: 0.1
|
||||
* Called functions: b_setmark, strcmp, strlen
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
char - The lexeme to be searched
|
||||
* Return value:
|
||||
int - the element offset index in the symbol table
|
||||
-1 if no element was found
|
||||
*/
|
||||
int st_lookup(STD s_table, char *lexeme) {
|
||||
int i; /* idx: index location for symbol table, i: increment counter*/
|
||||
#ifdef DEBUG
|
||||
printf("Looking up %s...", lexeme);
|
||||
#endif
|
||||
for (i = s_table.st_offset - 1; i >= 0; --i) {
|
||||
if (strcmp(lexeme, s_table.pstvr[i].plex) == 0) {
|
||||
#ifdef DEBUG
|
||||
printf("YES\n");
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("NO\n");
|
||||
#endif
|
||||
return -1; /* Found nothing */
|
||||
}
|
||||
|
||||
/* Change the data type indicator of the variable entry located in vid_offset.
|
||||
* Author: Victor Fernandes
|
||||
* Version: 0.1
|
||||
* Called functions: N/A
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
int - the offset location of the VID
|
||||
char - the new type of the VID
|
||||
* Return value:
|
||||
1 if change successful, -1 if no change was made or internal error
|
||||
*/
|
||||
int st_change_type(STD s_table, int vid_offset, char v_type) {
|
||||
|
||||
/* Do nothing if update flag has already been set */
|
||||
if ((s_table.pstvr[vid_offset].status_field & U_MASK)) return -1;
|
||||
|
||||
/* Reset to new type with default mask and update flag
|
||||
Note: Can separate the statements to set the update flag at the
|
||||
end, but this resets AND updates at once
|
||||
*/
|
||||
/*sym_table.pstvr[vid_offset].status_field = sym_table.pstvr[vid_offset].status_field & DFT_U_MASK;*/
|
||||
s_table.pstvr[vid_offset].status_field &= DFT_U_MASK;
|
||||
|
||||
switch (v_type) {
|
||||
case 'I': /* Integer type */
|
||||
s_table.pstvr[vid_offset].status_field |= INT_MASK;
|
||||
break;
|
||||
case 'F': /* Floating point type */
|
||||
s_table.pstvr[vid_offset].status_field |= FLT_MASK;
|
||||
break;
|
||||
case 'S': /* String type, do nothing as it cannot be changed */
|
||||
break;
|
||||
default:
|
||||
return -1; /* Not supposed to fall into here */
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* Change the i_value of the variable located by vid_offset to new Value
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: N/A
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
int - the offset location of the VID
|
||||
Value - the new value of the VID
|
||||
* Return value: the offset location of the VID
|
||||
*/
|
||||
int st_change_value(STD s_table, int vid_offset, Value value) {
|
||||
s_table.pstvr[vid_offset].i_value = value;
|
||||
return vid_offset;
|
||||
}
|
||||
|
||||
/* Get the type of the variable specified by vid_offset
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: N/A
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
int - the offset of the VID in the table
|
||||
* Return value:
|
||||
char - the type of the VID ('I','F', or 'S')
|
||||
-1 if there is an invalid value set
|
||||
*/
|
||||
char st_get_type(STD s_table, int vid_offset) {
|
||||
unsigned short mask;
|
||||
mask = s_table.pstvr[vid_offset].status_field & CHK_MASK;
|
||||
switch (mask) {
|
||||
case INT_MASK:
|
||||
return 'I';
|
||||
case FLT_MASK:
|
||||
return 'F';
|
||||
case STR_MASK:
|
||||
return 'S';
|
||||
default:
|
||||
return -1; /* Not supposed to fall into here */
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the i_value of the variable specified by vid_offset
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions:
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
int - the offset of the VID in the table
|
||||
* Return value:
|
||||
Value - the value of the VID
|
||||
Incorrect parameters will cause undefined behaviour
|
||||
*/
|
||||
Value st_get_value(STD s_table, int vid_offset) {
|
||||
return s_table.pstvr[vid_offset].i_value;
|
||||
}
|
||||
|
||||
/* Free memory used by the symbol table
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: free, b_free
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
*/
|
||||
void st_destroy(STD s_table) {
|
||||
if (s_table.pstvr != NULL) {
|
||||
free(s_table.pstvr);
|
||||
s_table.pstvr = NULL;
|
||||
}
|
||||
b_free(s_table.plsBD);
|
||||
}
|
||||
|
||||
/* Print the contents of the symbol table to standard output
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: printf
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
* Return value:
|
||||
int - the number of items printed to stdout
|
||||
*/
|
||||
int st_print(STD s_table) {
|
||||
int i;
|
||||
|
||||
if (s_table.st_size <= 0) return -1;
|
||||
|
||||
printf("Symbol Table\n____________\nLine Number\tVariable Identifier\n");
|
||||
for (i = 0; i <= s_table.st_offset - 1 ; ++i)
|
||||
printf("%2d\t\t%s\n", s_table.pstvr[i].o_line, s_table.pstvr[i].plex);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Store the symbol table to a file named $stable.ste.
|
||||
It overwrites any existing file named $stable.ste.
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: fopen, fprintf, st_get_type, fclose, printf
|
||||
* Parameters:
|
||||
STD - The symbol table
|
||||
* Return value:
|
||||
int - the number of items stored
|
||||
-1 if the file stream cannot be opened
|
||||
*/
|
||||
int st_store(STD s_table) {
|
||||
FILE *out; /* The target file*/
|
||||
int i;
|
||||
|
||||
/* Windows does not like fopen, and fopen_s is Windows-only. This will ensure the
|
||||
* use of the proper function call if PLATYPUS is being built on a non-windows system.
|
||||
* Best approach is to add _CRT_SECURE_NO_WARNINGS to the preprocessor definitions, but
|
||||
* this works, too.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
if (fopen_s(&out, ST_FILE_NAME, "w+") != 0 || out == NULL)
|
||||
#else
|
||||
if ((out = fopen(ST_FILE_NAME, "w+")) == NULL)
|
||||
#endif
|
||||
return -1; /* Can't open file, stop. */
|
||||
|
||||
fprintf(out, "%d", s_table.st_size);
|
||||
|
||||
for (i = 0; i < s_table.st_offset; ++i) {
|
||||
fprintf(out, " %4X %d %s %d",
|
||||
s_table.pstvr[i].status_field, /* Status flag */
|
||||
(int)strlen(s_table.pstvr[i].plex), /* Length of lexeme */
|
||||
s_table.pstvr[i].plex, /* The lexeme itself */
|
||||
s_table.pstvr[i].o_line); /* Line number */
|
||||
|
||||
/* Initial value */
|
||||
char type = st_get_type(s_table, i);
|
||||
switch (type) {
|
||||
case 'I':
|
||||
case 'F':
|
||||
case 'S':
|
||||
fprintf(out, " %c", type);
|
||||
}
|
||||
}
|
||||
fclose(out);
|
||||
printf("Symbol Table stored\n");
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* Internal function to set the table size to 0.
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: N/A
|
||||
* Parameters: N/A
|
||||
* Return value: N/A
|
||||
*/
|
||||
static void st_setsize(void) {
|
||||
sym_table.st_size = 0;
|
||||
}
|
||||
|
||||
/* Internal function to increment st_offset by 1.
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions: N/A
|
||||
* Parameters: N/A
|
||||
* Return value: N/A
|
||||
*/
|
||||
static void st_incoffset(void) {
|
||||
++sym_table.st_offset;
|
||||
}
|
||||
|
||||
|
||||
/* Sorts the table by variable name in ascending/descending order
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions:
|
||||
* Parameters:
|
||||
* Return value:
|
||||
* Algorithm:
|
||||
*/
|
||||
int st_sort(STD s_table, char s_order) {
|
||||
/* Compiler warning about unused parameters,
|
||||
* this is fine for this dummy method
|
||||
*/
|
||||
return 0; /* SYKE! */
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* Filename: stable.h
|
||||
* Compiler: msvc (Visual Studio 2015)
|
||||
* Function declarations for the symbol table
|
||||
* CST8152, Assignment #3
|
||||
* Professor: S^R
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.1
|
||||
* Date: 24 March 2017
|
||||
*/
|
||||
|
||||
#ifndef STABLE_H_
|
||||
#define STABLE_H_
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "buffer.h"
|
||||
|
||||
/* Masks
|
||||
16-bit field MSB-> 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 <-LSB
|
||||
0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0
|
||||
*/
|
||||
#define DFT_MASK 0xFFF8 /* Default mask */
|
||||
#define U_MASK 0x0001 /* Update mask */
|
||||
#define INT_MASK 0x0004 /* Integer mask */
|
||||
#define FLT_MASK 0x0002 /* Floating point mask */
|
||||
#define STR_MASK 0x0006 /* String mask*/
|
||||
|
||||
#define CHK_MASK 0x0006 /* Type check mask */
|
||||
#define DFT_U_MASK 0xFFF9 /* Default mask with update flag */
|
||||
|
||||
#define ST_FILE_NAME "$stable.ste"
|
||||
|
||||
typedef union InitialValue {
|
||||
int int_val; /* Integer variable initial value */
|
||||
float fpl_val; /* Floating-point variable initial value */
|
||||
int str_offset; /* String variable initial value (location offset) */
|
||||
} Value;
|
||||
|
||||
typedef struct SymbolTableVidRecord {
|
||||
unsigned short status_field; /* Variable record status field */
|
||||
char *plex; /* Pointer to lexeme (VID name) in CA (character array) */
|
||||
int o_line; /* Line of first occurence */
|
||||
Value i_value; /* Variable initial value */
|
||||
void *reserved; /* Reserved for future use, not needed right now */
|
||||
} STVR;
|
||||
|
||||
typedef struct SymbolTableDescriptor {
|
||||
STVR *pstvr; /* Pointer to array of STVR */
|
||||
int st_size; /* Size in number of STVR elements */
|
||||
int st_offset; /* Offset in number of STVR elements */
|
||||
Buffer *plsBD; /* Pointer to the lexeme storage buffer descriptor */
|
||||
} STD;
|
||||
|
||||
STD st_create(int);
|
||||
int st_install(STD, char*, char, int);
|
||||
int st_lookup(STD, char*);
|
||||
int st_change_type(STD, int, char);
|
||||
int st_change_value(STD, int, Value);
|
||||
char st_get_type(STD, int);
|
||||
Value st_get_value(STD, int);
|
||||
void st_destroy(STD);
|
||||
int st_print(STD);
|
||||
int st_store(STD);
|
||||
int st_sort(STD, char);
|
||||
|
||||
#endif
|
114
table.h
114
table.h
|
@ -4,7 +4,7 @@
|
|||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 1.17.1
|
||||
* Date: 30 January 2017
|
||||
* Provided by: Svillen Ranev
|
||||
* Provided by: S^R
|
||||
*/
|
||||
|
||||
#ifndef TABLE_H_
|
||||
|
@ -38,29 +38,31 @@
|
|||
#define ESWR 13 /* Error state (no retract) */
|
||||
#define IS -1 /* Invalid state */
|
||||
|
||||
/*Avoid platform dependency and use fixed 2-byte short */
|
||||
#define PLT_SHRT_MAX 32767
|
||||
/* State transition table definition */
|
||||
|
||||
#define TABLE_COLUMNS 7
|
||||
/*transition table - type of states defined in separate table */
|
||||
int st_table[][TABLE_COLUMNS] = {
|
||||
/* INPUT COLUMNS:
|
||||
COLUMN # | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|
||||
|[a-zA-Z]| 0 |[1-7]|[8-9]| . | # | other |
|
||||
*/
|
||||
/* State 0 */ {1, 6 , 4 , 4 , ES , ES , ES},
|
||||
/* State 1 */ {1, 1 , 1 , 1 , 2 , 3 , 2 },
|
||||
/* State 2 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 3 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 4 */ {ES, 4 , 4 , 4 , 7 , 5 , 5 },
|
||||
/* State 5 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 6 */ {ES, 9 , 9 , ES, 7 , ES , 5 },
|
||||
/* State 7 */ {8 , 7 , 7 , 7, 8 , 8 , 8 },
|
||||
/* State 8 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 9 */ {ES, ES , 11, ES, ES , ES , 10},
|
||||
/* State 10 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 11 */ {ES, 11 , 11, ES, ES , ES , 10},
|
||||
/* State 12 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 13 */ {IS, IS , IS, IS, IS , IS , IS}
|
||||
/* INPUT COLUMNS:
|
||||
COLUMN # | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|
||||
|[a-zA-Z]| 0 |[1-7]|[8-9]| . | # | other |
|
||||
*/
|
||||
/* State 0 */ {1, 6 , 4 , 4 , IS , IS , IS},
|
||||
/* State 1 */ {1, 1 , 1 , 1 , 2 , 3 , 2 },
|
||||
/* State 2 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 3 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 4 */ {ES, 4 , 4 , 4 , 7 , 5 , 5 },
|
||||
/* State 5 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 6 */ {ES, 9 , 9 , ES, 7 , ES , 5 },
|
||||
/* State 7 */ {8 , 7 , 7 , 7, 8 , 8 , 8 },
|
||||
/* State 8 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 9 */ {ES, 9 , 11, ES, ES , ES , 10},
|
||||
/* State 10 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 11 */ {ES, 11 , 11, ES, ES , ES , 10},
|
||||
/* State 12 */ {IS, IS , IS, IS, IS , IS , IS},
|
||||
/* State 13 */ {IS, IS , IS, IS, IS , IS , IS}
|
||||
|
||||
};
|
||||
/* Accepting state table definition */
|
||||
|
@ -70,20 +72,20 @@ int st_table[][TABLE_COLUMNS] = {
|
|||
|
||||
int as_table[] = {
|
||||
|
||||
/* State 0 */ NOAS,
|
||||
/* State 1 */ NOAS,
|
||||
/* State 2 */ ASWR,
|
||||
/* State 3 */ ASNR,
|
||||
/* State 4 */ NOAS,
|
||||
/* State 5 */ ASWR,
|
||||
/* State 6 */ NOAS,
|
||||
/* State 7 */ NOAS,
|
||||
/* State 8 */ ASWR,
|
||||
/* State 9 */ NOAS,
|
||||
/* State 10 */ ASWR,
|
||||
/* State 11 */ NOAS,
|
||||
/* State 12 */ ASNR,
|
||||
/* State 13 */ ASWR
|
||||
/* State 0 */ NOAS,
|
||||
/* State 1 */ NOAS,
|
||||
/* State 2 */ ASWR,
|
||||
/* State 3 */ ASNR,
|
||||
/* State 4 */ NOAS,
|
||||
/* State 5 */ ASWR,
|
||||
/* State 6 */ NOAS,
|
||||
/* State 7 */ NOAS,
|
||||
/* State 8 */ ASWR,
|
||||
/* State 9 */ NOAS,
|
||||
/* State 10 */ ASWR,
|
||||
/* State 11 */ NOAS,
|
||||
/* State 12 */ ASNR,
|
||||
/* State 13 */ ASWR
|
||||
|
||||
};
|
||||
|
||||
|
@ -111,21 +113,21 @@ typedef Token(*PTR_AAF)(char *lexeme);
|
|||
|
||||
PTR_AAF aa_table[] = {
|
||||
|
||||
/* State 0 */ NULL,
|
||||
/* State 1 */ NULL,
|
||||
/* State 2 */ aa_func02,
|
||||
/* State 3 */ aa_func03,
|
||||
/* State 4 */ NULL,
|
||||
/* State 5 */ aa_func05,
|
||||
/* State 6 */ NULL,
|
||||
/* State 7 */ NULL,
|
||||
/* State 8 */ aa_func08,
|
||||
/* State 9 */ NULL,
|
||||
/* State 10 */ aa_func10,
|
||||
/* State 11 */ NULL,
|
||||
/* State 12 */ aa_func12,
|
||||
/* State 13 */ aa_func13
|
||||
|
||||
/* State 0 */ NULL,
|
||||
/* State 1 */ NULL,
|
||||
/* State 2 */ aa_func02,
|
||||
/* State 3 */ aa_func03,
|
||||
/* State 4 */ NULL,
|
||||
/* State 5 */ aa_func05,
|
||||
/* State 6 */ NULL,
|
||||
/* State 7 */ NULL,
|
||||
/* State 8 */ aa_func08,
|
||||
/* State 9 */ NULL,
|
||||
/* State 10 */ aa_func10,
|
||||
/* State 11 */ NULL,
|
||||
/* State 12 */ aa_func12,
|
||||
/* State 13 */ aa_func13
|
||||
|
||||
};
|
||||
|
||||
/* Keyword lookup table (.AND. and .OR. are not keywords) */
|
||||
|
@ -133,14 +135,14 @@ PTR_AAF aa_table[] = {
|
|||
#define KWT_SIZE 8
|
||||
|
||||
char * kw_table[] = {
|
||||
"ELSE",
|
||||
"IF",
|
||||
"INPUT",
|
||||
"OUTPUT",
|
||||
"PLATYPUS",
|
||||
"REPEAT",
|
||||
"THEN",
|
||||
"USING"
|
||||
"ELSE",
|
||||
"IF",
|
||||
"INPUT",
|
||||
"OUTPUT",
|
||||
"PLATYPUS",
|
||||
"REPEAT",
|
||||
"THEN",
|
||||
"USING"
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
### FUNCTION DEFINITIONS ###
|
||||
/* Purpose:
|
||||
/*
|
||||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 0.0.1
|
||||
* Called functions:
|
||||
|
|
4
token.h
4
token.h
|
@ -4,7 +4,7 @@
|
|||
* Author: Victor Fernandes, 040772243
|
||||
* Version: 1.17.1
|
||||
* Date: 30 January 2017
|
||||
* Provided by: Svillen Ranev
|
||||
* Provided by: S^R
|
||||
* The file is complete and MUST NOT be modified.
|
||||
*/
|
||||
#ifndef TOKEN_H_
|
||||
|
@ -62,7 +62,7 @@ typedef union TokenAttribute{
|
|||
short str_offset; /* sring literal offset from the beginning of */
|
||||
/* the string literal buffer (str_LTBL->cb_head) */
|
||||
float flt_value; /* floating-point literal attribute (value) */
|
||||
char vid_lex[VID_LEN+1]; /* variable identifier token attribute */
|
||||
int vid_offset; /* the vid_offset member replaces vid_lex */
|
||||
char err_lex[ERR_LEN+1]; /* error token attribite */
|
||||
} TA;
|
||||
|
||||
|
|
Loading…
Reference in New Issue