Add completed PS1
parent
932684a02a
commit
ce24a13954
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
CFLAGS+= -g
|
||||
scanner: scanner.c
|
||||
clean:
|
||||
-rm -f scanner
|
|
@ -0,0 +1,165 @@
|
|||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ERROR -1
|
||||
#define N_STATES 8
|
||||
#define ACCEPT N_STATES
|
||||
|
||||
// Buffer for accepted characters, to interpret when in accepting state
|
||||
char lexical_buffer[256];
|
||||
|
||||
// Program internal state
|
||||
int
|
||||
state = 0, // Current state in the automaton
|
||||
transition_table[N_STATES][256], // Table form of the automaton
|
||||
lexical_position = 0, // Track position in character buffer
|
||||
x = 421, y = 298, // Set starting point at page center
|
||||
dx = 0, dy = 0; // Horizontal/vertical shift values
|
||||
|
||||
|
||||
/*
|
||||
* When a complete command has been scanned, this
|
||||
* function translates it into postscript
|
||||
*/
|
||||
void interpret_lexical_buffer ( void );
|
||||
|
||||
|
||||
/*
|
||||
* Prepare the table form of the automaton
|
||||
*/
|
||||
void
|
||||
initialize_transition_table ( void )
|
||||
{
|
||||
memset ( transition_table, 0, N_STATES*256*sizeof(int) );
|
||||
for ( int s=0; s<N_STATES; s++ )
|
||||
for ( int i=0; i<256; i++ )
|
||||
transition_table[s][i] = ERROR;
|
||||
|
||||
// Transition table is based on the following table:
|
||||
// ┌───────┬───┬───┬───┬───┬───┬───────┬───┬───┬────────┐
|
||||
// │ State │ d │ x │ y │ = │ - │ [0-9] │ g │ o │ \n │
|
||||
// ├───────┼───┼───┼───┼───┼───┼───────┼───┼───┼────────┤
|
||||
// │ 0 │ 1 │ │ │ │ │ │ 5 │ │ │
|
||||
// │ 1 │ │ 2 │ 2 │ │ │ │ │ │ │
|
||||
// │ 2 │ │ │ │ 3 │ │ │ │ │ │
|
||||
// │ 3 │ │ │ │ │ 4 │ 4 │ │ │ │
|
||||
// │ 4 │ │ │ │ │ │ 4 │ │ │ ACCEPT │
|
||||
// │ 5 │ │ │ │ │ │ │ │ 6 │ │
|
||||
// │ 6 │ │ │ │ │ │ │ │ │ ACCEPT │
|
||||
// └───────┴───┴───┴───┴───┴───┴───────┴───┴───┴────────┘
|
||||
// Table is created from regex /(go|d(x|y)=-?[0-9]+)\n/g
|
||||
|
||||
/* STATE 0 */
|
||||
transition_table[0]['d'] = 1;
|
||||
transition_table[0]['g'] = 5;
|
||||
|
||||
/* STATE 1 */
|
||||
transition_table[1]['x'] = 2;
|
||||
transition_table[1]['y'] = 2;
|
||||
|
||||
/* STATE 2 */
|
||||
transition_table[2]['='] = 3;
|
||||
|
||||
/* STATE 3 */
|
||||
transition_table[3]['-'] = 4;
|
||||
for (int c = '0'; c <= '9'; c++)
|
||||
transition_table[3][c] = 4;
|
||||
|
||||
/* STATE 5 */
|
||||
transition_table[4]['\n'] = ACCEPT;
|
||||
for (int c = '0'; c <= '9'; c++)
|
||||
transition_table[4][c] = 4;
|
||||
|
||||
/* STATE 6 */
|
||||
transition_table[5]['o'] = 6;
|
||||
|
||||
/* STATE 7 */
|
||||
transition_table[6]['\n'] = ACCEPT;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Reset the automaton after completing a command */
|
||||
void
|
||||
reset ( void )
|
||||
{
|
||||
state = 0;
|
||||
lexical_position = 0;
|
||||
memset ( lexical_buffer, 0, 256*sizeof(char) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main function:
|
||||
* - Initialize the program to start drawing
|
||||
* - Scan command
|
||||
* - Translate accepted command string into postscript
|
||||
* - Reset automaton
|
||||
* - Repeat
|
||||
*/
|
||||
int
|
||||
main ()
|
||||
{
|
||||
// Prepare the table representation of the automaton
|
||||
initialize_transition_table();
|
||||
|
||||
// Start drawing from the initial coordinates
|
||||
printf ( "<< /PageSize [842 595] >> setpagedevice\n" );
|
||||
printf ( "%d %d moveto\n", x, y );
|
||||
|
||||
// Read characters until end-of-file or failure
|
||||
int read = 0;
|
||||
while ( read != EOF )
|
||||
{
|
||||
// Fetch the next character and store it in the lexical buffer
|
||||
read = getchar();
|
||||
lexical_buffer[lexical_position] = read;
|
||||
lexical_position += 1;
|
||||
|
||||
// Change state according to the table
|
||||
state = transition_table[state][read];
|
||||
|
||||
// Check for error or accepting states:
|
||||
// * stop the program on error
|
||||
// * interpret the contents of the lexical buffer when valid
|
||||
switch (state)
|
||||
{
|
||||
case ERROR:
|
||||
fprintf ( stderr, "Invalid input\n" );
|
||||
exit ( EXIT_FAILURE );
|
||||
break;
|
||||
case ACCEPT:
|
||||
interpret_lexical_buffer();
|
||||
reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf ( "stroke\n" );
|
||||
printf ( "showpage\n" );
|
||||
exit ( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
/* This function interprets correct statements after they have been accepted */
|
||||
void
|
||||
interpret_lexical_buffer ( void )
|
||||
{
|
||||
if ( lexical_buffer[1] == 'x' )
|
||||
sscanf ( &lexical_buffer[3], "%d", &dx );
|
||||
else if ( lexical_buffer[1] == 'y' )
|
||||
sscanf ( &lexical_buffer[3], "%d", &dy );
|
||||
else if ( strncmp ( lexical_buffer, "go", 2 ) == 0 )
|
||||
{
|
||||
x = x + dx;
|
||||
y = y + dy;
|
||||
printf ( "%d %d lineto\n", x, y );
|
||||
printf ( "%d %d moveto\n", x, y );
|
||||
}
|
||||
else
|
||||
fprintf ( stderr, "Unknown command accepted by the scanner:\n%s\n",
|
||||
lexical_buffer
|
||||
);
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Loading…
Reference in New Issue