Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Completed hand-written parser example.
- Loading branch information
Showing
7 changed files
with
164 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
|
||
# The top level rule indicates how to link everything together into calc | ||
|
||
calc: main.o scanner.o parser.o | ||
gcc main.o scanner.o parser.o -o calc -lm | ||
|
||
# This pattern indicates that any .o file depends | ||
# upon the .c file of the same name, and all of the .h files. | ||
# So, if a .o file is needed, it is built automatically. | ||
|
||
%.o: %.c *.h | ||
gcc -Wall -c -g $< -o $@ | ||
|
||
# clean causes all intermediate files to be deleted. | ||
|
||
clean: | ||
rm -f *.o calc | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Hand-Written LL(1) Parser and Scanner | ||
------------------------------------- | ||
|
||
This shows a simple example of a hand-written scanner | ||
and a hand-written recursive-descent parser for an LL(1) | ||
expression language. The program attempts to parse the | ||
input and determine whether the parse succeeds, but | ||
does not evaluate the expression. | ||
|
||
Some suggested exercises: | ||
- Modify the program to compute the value of the expression, if it parses. | ||
|
||
- Modify the scanner and parser to handle more complex expressions, | ||
such as floating point values and additional operators. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "parser.h" | ||
#include <stdio.h> | ||
|
||
int main() | ||
{ | ||
printf("Enter an expression, followed by Control-D to indicate EOF.\n"); | ||
if(parse_P()) { | ||
printf("Expression is valid.\n"); | ||
return 0; | ||
} else { | ||
printf("Expression is NOT valid.\n"); | ||
return 1; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef PARSER_H | ||
#define PARSER_H | ||
|
||
int parse_P(); | ||
int parse_E(); | ||
int parse_E_prime(); | ||
int parse_T(); | ||
int parse_T_prime(); | ||
int parse_F(); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#include "scanner.h" | ||
#include <stdio.h> | ||
#include <ctype.h> | ||
|
||
static int putback_valid = 0; | ||
static token_t putback_value = TOKEN_ERROR; | ||
|
||
token_t scan_token() | ||
{ | ||
if(putback_valid) { | ||
putback_valid = 0; | ||
return putback_value; | ||
} | ||
|
||
int c; | ||
retry: | ||
c = fgetc(stdin); | ||
|
||
if(c=='*') { | ||
return TOKEN_MULTIPLY; | ||
} else if(c=='+') { | ||
return TOKEN_PLUS; | ||
} else if(c=='(') { | ||
return TOKEN_LPAREN; | ||
} else if(c==')') { | ||
return TOKEN_RPAREN; | ||
} else if(isdigit(c)) { | ||
do { | ||
c = fgetc(stdin); | ||
} while(isdigit(c)); | ||
ungetc(c,stdin); | ||
return TOKEN_INT; | ||
} else if(isspace(c)) { | ||
goto retry; | ||
} else if(c==EOF) { | ||
return TOKEN_EOF; | ||
} else { | ||
return TOKEN_ERROR; | ||
} | ||
} | ||
|
||
int expect_token( token_t kind ) | ||
{ | ||
token_t t = scan_token(); | ||
if(t==kind) { | ||
return 1; | ||
} else { | ||
putback_token(t); | ||
return 0; | ||
} | ||
} | ||
|
||
void putback_token( token_t t ) | ||
{ | ||
putback_value = t; | ||
putback_valid = 1; | ||
} | ||
|
||
const char * token_string( token_t t ) | ||
{ | ||
switch(t) { | ||
case TOKEN_MULTIPLY: | ||
return "*"; | ||
case TOKEN_PLUS: | ||
return "+"; | ||
case TOKEN_LPAREN: | ||
return "("; | ||
case TOKEN_RPAREN: | ||
return ")"; | ||
case TOKEN_INT: | ||
return "INTEGER"; | ||
case TOKEN_EOF: | ||
return "EOF"; | ||
case TOKEN_ERROR: | ||
default: | ||
return "ERROR"; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#ifndef SCANNER_H | ||
#define SCANNER_H | ||
|
||
typedef enum { | ||
TOKEN_PLUS, | ||
TOKEN_MULTIPLY, | ||
TOKEN_LPAREN, | ||
TOKEN_RPAREN, | ||
TOKEN_INT, | ||
TOKEN_ERROR, | ||
TOKEN_EOF | ||
} token_t; | ||
|
||
token_t scan_token(); | ||
int expect_token( token_t t ); | ||
void putback_token( token_t t ); | ||
const char * token_string( token_t t ); | ||
|
||
#endif |