#include <stdio.h>
#include <string.h>
#include <ctype.h>
// =====================================================================
// Shift-Reduce Parser
// Grammar:
// E -> E + E
// E -> E * E
// E -> id
// E -> (E)
// =====================================================================
#define MAX 100
char stack[ MAX] [ 20 ] ; // The parser stack (each cell = a symbol like "E", "+", "id", etc.)
int top = - 1 ; // Stack pointer
// ---------- Stack helpers ----------
void push( const char * sym)
{
top++;
}
void pop( )
{
if ( top >= 0 ) top--;
}
// Print current stack state
void printStack( const char * action)
{
for ( int i = 0 ; i <= top; i++ )
}
// ---------- Reduce rules ----------
// Try to reduce the top of the stack using grammar rules.
// Returns 1 if a reduction was made, 0 otherwise.
int tryReduce( )
{
// Rule: E -> (E)
// Stack top-2 = "(", top-1 = "E", top = ")"
if ( top >= 2 &&
strcmp ( stack
[ top
- 2 ] , "(" ) == 0 && strcmp ( stack
[ top
- 1 ] , "E" ) == 0 && {
pop( ) ; pop( ) ; pop( ) ; // remove ), E, (
push( "E" ) ; // push E
printStack( "Reduce" ) ;
return 1 ;
}
// Rule: E -> E * E
// Stack top-2 = "E", top-1 = "*", top = "E"
if ( top >= 2 &&
strcmp ( stack
[ top
- 2 ] , "E" ) == 0 && strcmp ( stack
[ top
- 1 ] , "*" ) == 0 && {
pop( ) ; pop( ) ; pop( ) ;
push( "E" ) ;
printStack( "Reduce" ) ;
return 1 ;
}
// Rule: E -> E + E
// Stack top-2 = "E", top-1 = "+", top = "E"
if ( top >= 2 &&
strcmp ( stack
[ top
- 2 ] , "E" ) == 0 && strcmp ( stack
[ top
- 1 ] , "+" ) == 0 && {
pop( ) ; pop( ) ; pop( ) ;
push( "E" ) ;
printStack( "Reduce" ) ;
return 1 ;
}
// Rule: E -> id
// Top is an identifier (not a special symbol)
if ( top >= 0 &&
strcmp ( stack
[ top
] , "E" ) != 0 && strcmp ( stack
[ top
] , "+" ) != 0 && strcmp ( stack
[ top
] , "*" ) != 0 && strcmp ( stack
[ top
] , "(" ) != 0 && {
pop( ) ;
push( "E" ) ;
printStack( "Reduce" ) ;
return 1 ;
}
return 0 ; // No reduction possible
}
// ---------- Tokenizer (get next token, skip whitespace) ----------
// Returns the next token from input starting at position *pos.
// Tokens: "(", ")", "+", "*", or an identifier string.
// Returns 0 if no more tokens, 1 if a token was written into `out`.
int nextToken( const char * input, int * pos, char * out)
{
// Skip whitespace
while ( * pos
< len
&& isspace ( ( unsigned char ) input
[ * pos
] ) ) ( * pos) ++;
if ( * pos >= len) return 0 ; // No more tokens
char ch = input[ * pos] ;
// Single-character tokens: operators and parentheses
if ( ch == '+' || ch == '*' || ch == '(' || ch == ')' )
{
out[ 0 ] = ch;
out[ 1 ] = '\0 ' ;
( * pos) ++;
return 1 ;
}
// Identifier: letters and digits
if ( isalpha ( ( unsigned char ) ch
) || ch
== '_' ) {
int start = * pos;
while ( * pos
< len
&& ( isalnum ( ( unsigned char ) input
[ * pos
] ) || input
[ * pos
] == '_' ) ) ( * pos) ++;
int tlen = * pos - start;
out[ tlen] = '\0 ' ;
return 1 ;
}
// Unknown character — skip it
( * pos) ++;
return 0 ;
}
// ---------- Main parser ----------
void shiftReduceParse( const char * input)
{
top = - 1 ; // Reset stack
int pos = 0 ;
char token[ 50 ] ;
while ( nextToken( input, & pos, token) )
{
// SHIFT: push the current token onto the stack
push( token) ;
printStack( "Shift" ) ;
// After each shift, try to reduce as many times as possible
while ( tryReduce( ) ) ;
}
// After all input consumed, try one final round of reductions
while ( tryReduce( ) ) ;
// Check if parse succeeded (stack should contain exactly one "E")
if ( top
== 0 && strcmp ( stack
[ 0 ] , "E" ) == 0 ) else
}
int main( )
{
char input[ 200 ] ;
printf ( "Enter an Expression:\n " ) ; fgets ( input
, 200 , stdin
) ;
// Remove newline if present
if ( len > 0 && input[ len - 1 ] == '\n ' )
input[ len - 1 ] = '\0 ' ;
shiftReduceParse( input) ;
return 0 ;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGN0eXBlLmg+CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gIFNoaWZ0LVJlZHVjZSBQYXJzZXIKLy8gIEdyYW1tYXI6Ci8vICAgIEUgLT4gRSArIEUKLy8gICAgRSAtPiBFICogRQovLyAgICBFIC0+IGlkCi8vICAgIEUgLT4gKEUpCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKI2RlZmluZSBNQVggMTAwCgpjaGFyIHN0YWNrW01BWF1bMjBdOyAvLyBUaGUgcGFyc2VyIHN0YWNrIChlYWNoIGNlbGwgPSBhIHN5bWJvbCBsaWtlICJFIiwgIisiLCAiaWQiLCBldGMuKQppbnQgdG9wID0gLTE7ICAgICAgICAvLyBTdGFjayBwb2ludGVyCgovLyAtLS0tLS0tLS0tIFN0YWNrIGhlbHBlcnMgLS0tLS0tLS0tLQoKdm9pZCBwdXNoKGNvbnN0IGNoYXIgKnN5bSkKewogICAgdG9wKys7CiAgICBzdHJjcHkoc3RhY2tbdG9wXSwgc3ltKTsKfQoKdm9pZCBwb3AoKQp7CiAgICBpZiAodG9wID49IDApIHRvcC0tOwp9CgovLyBQcmludCBjdXJyZW50IHN0YWNrIHN0YXRlCnZvaWQgcHJpbnRTdGFjayhjb25zdCBjaGFyICphY3Rpb24pCnsKICAgIHByaW50ZigiJXM6ICIsIGFjdGlvbik7CiAgICBmb3IgKGludCBpID0gMDsgaSA8PSB0b3A7IGkrKykKICAgICAgICBwcmludGYoIiVzICIsIHN0YWNrW2ldKTsKICAgIHByaW50ZigiXG4iKTsKfQoKLy8gLS0tLS0tLS0tLSBSZWR1Y2UgcnVsZXMgLS0tLS0tLS0tLQovLyBUcnkgdG8gcmVkdWNlIHRoZSB0b3Agb2YgdGhlIHN0YWNrIHVzaW5nIGdyYW1tYXIgcnVsZXMuCi8vIFJldHVybnMgMSBpZiBhIHJlZHVjdGlvbiB3YXMgbWFkZSwgMCBvdGhlcndpc2UuCgppbnQgdHJ5UmVkdWNlKCkKewogICAgLy8gUnVsZTogRSAtPiAoRSkKICAgIC8vIFN0YWNrIHRvcC0yID0gIigiLCB0b3AtMSA9ICJFIiwgdG9wID0gIikiCiAgICBpZiAodG9wID49IDIgJiYKICAgICAgICBzdHJjbXAoc3RhY2tbdG9wIC0gMl0sICIoIikgPT0gMCAmJgogICAgICAgIHN0cmNtcChzdGFja1t0b3AgLSAxXSwgIkUiKSA9PSAwICYmCiAgICAgICAgc3RyY21wKHN0YWNrW3RvcF0sICAgICAiKSIpID09IDApCiAgICB7CiAgICAgICAgcG9wKCk7IHBvcCgpOyBwb3AoKTsgICAgICAgICAgLy8gcmVtb3ZlICksIEUsICgKICAgICAgICBwdXNoKCJFIik7ICAgICAgICAgICAgICAgICAgICAvLyBwdXNoIEUKICAgICAgICBwcmludFN0YWNrKCJSZWR1Y2UiKTsKICAgICAgICByZXR1cm4gMTsKICAgIH0KCiAgICAvLyBSdWxlOiBFIC0+IEUgKiBFCiAgICAvLyBTdGFjayB0b3AtMiA9ICJFIiwgdG9wLTEgPSAiKiIsIHRvcCA9ICJFIgogICAgaWYgKHRvcCA+PSAyICYmCiAgICAgICAgc3RyY21wKHN0YWNrW3RvcCAtIDJdLCAiRSIpID09IDAgJiYKICAgICAgICBzdHJjbXAoc3RhY2tbdG9wIC0gMV0sICIqIikgPT0gMCAmJgogICAgICAgIHN0cmNtcChzdGFja1t0b3BdLCAgICAgIkUiKSA9PSAwKQogICAgewogICAgICAgIHBvcCgpOyBwb3AoKTsgcG9wKCk7CiAgICAgICAgcHVzaCgiRSIpOwogICAgICAgIHByaW50U3RhY2soIlJlZHVjZSIpOwogICAgICAgIHJldHVybiAxOwogICAgfQoKICAgIC8vIFJ1bGU6IEUgLT4gRSArIEUKICAgIC8vIFN0YWNrIHRvcC0yID0gIkUiLCB0b3AtMSA9ICIrIiwgdG9wID0gIkUiCiAgICBpZiAodG9wID49IDIgJiYKICAgICAgICBzdHJjbXAoc3RhY2tbdG9wIC0gMl0sICJFIikgPT0gMCAmJgogICAgICAgIHN0cmNtcChzdGFja1t0b3AgLSAxXSwgIisiKSA9PSAwICYmCiAgICAgICAgc3RyY21wKHN0YWNrW3RvcF0sICAgICAiRSIpID09IDApCiAgICB7CiAgICAgICAgcG9wKCk7IHBvcCgpOyBwb3AoKTsKICAgICAgICBwdXNoKCJFIik7CiAgICAgICAgcHJpbnRTdGFjaygiUmVkdWNlIik7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CgogICAgLy8gUnVsZTogRSAtPiBpZAogICAgLy8gVG9wIGlzIGFuIGlkZW50aWZpZXIgKG5vdCBhIHNwZWNpYWwgc3ltYm9sKQogICAgaWYgKHRvcCA+PSAwICYmCiAgICAgICAgc3RyY21wKHN0YWNrW3RvcF0sICJFIikgIT0gMCAmJgogICAgICAgIHN0cmNtcChzdGFja1t0b3BdLCAiKyIpICE9IDAgJiYKICAgICAgICBzdHJjbXAoc3RhY2tbdG9wXSwgIioiKSAhPSAwICYmCiAgICAgICAgc3RyY21wKHN0YWNrW3RvcF0sICIoIikgIT0gMCAmJgogICAgICAgIHN0cmNtcChzdGFja1t0b3BdLCAiKSIpICE9IDApCiAgICB7CiAgICAgICAgcG9wKCk7CiAgICAgICAgcHVzaCgiRSIpOwogICAgICAgIHByaW50U3RhY2soIlJlZHVjZSIpOwogICAgICAgIHJldHVybiAxOwogICAgfQoKICAgIHJldHVybiAwOyAvLyBObyByZWR1Y3Rpb24gcG9zc2libGUKfQoKLy8gLS0tLS0tLS0tLSBUb2tlbml6ZXIgKGdldCBuZXh0IHRva2VuLCBza2lwIHdoaXRlc3BhY2UpIC0tLS0tLS0tLS0KLy8gUmV0dXJucyB0aGUgbmV4dCB0b2tlbiBmcm9tIGlucHV0IHN0YXJ0aW5nIGF0IHBvc2l0aW9uICpwb3MuCi8vIFRva2VuczogIigiLCAiKSIsICIrIiwgIioiLCBvciBhbiBpZGVudGlmaWVyIHN0cmluZy4KLy8gUmV0dXJucyAwIGlmIG5vIG1vcmUgdG9rZW5zLCAxIGlmIGEgdG9rZW4gd2FzIHdyaXR0ZW4gaW50byBgb3V0YC4KCmludCBuZXh0VG9rZW4oY29uc3QgY2hhciAqaW5wdXQsIGludCAqcG9zLCBjaGFyICpvdXQpCnsKICAgIGludCBsZW4gPSBzdHJsZW4oaW5wdXQpOwoKICAgIC8vIFNraXAgd2hpdGVzcGFjZQogICAgd2hpbGUgKCpwb3MgPCBsZW4gJiYgaXNzcGFjZSgodW5zaWduZWQgY2hhcilpbnB1dFsqcG9zXSkpCiAgICAgICAgKCpwb3MpKys7CgogICAgaWYgKCpwb3MgPj0gbGVuKSByZXR1cm4gMDsgLy8gTm8gbW9yZSB0b2tlbnMKCiAgICBjaGFyIGNoID0gaW5wdXRbKnBvc107CgogICAgLy8gU2luZ2xlLWNoYXJhY3RlciB0b2tlbnM6IG9wZXJhdG9ycyBhbmQgcGFyZW50aGVzZXMKICAgIGlmIChjaCA9PSAnKycgfHwgY2ggPT0gJyonIHx8IGNoID09ICcoJyB8fCBjaCA9PSAnKScpCiAgICB7CiAgICAgICAgb3V0WzBdID0gY2g7CiAgICAgICAgb3V0WzFdID0gJ1wwJzsKICAgICAgICAoKnBvcykrKzsKICAgICAgICByZXR1cm4gMTsKICAgIH0KCiAgICAvLyBJZGVudGlmaWVyOiBsZXR0ZXJzIGFuZCBkaWdpdHMKICAgIGlmIChpc2FscGhhKCh1bnNpZ25lZCBjaGFyKWNoKSB8fCBjaCA9PSAnXycpCiAgICB7CiAgICAgICAgaW50IHN0YXJ0ID0gKnBvczsKICAgICAgICB3aGlsZSAoKnBvcyA8IGxlbiAmJiAoaXNhbG51bSgodW5zaWduZWQgY2hhcilpbnB1dFsqcG9zXSkgfHwgaW5wdXRbKnBvc10gPT0gJ18nKSkKICAgICAgICAgICAgKCpwb3MpKys7CiAgICAgICAgaW50IHRsZW4gPSAqcG9zIC0gc3RhcnQ7CiAgICAgICAgc3RybmNweShvdXQsIGlucHV0ICsgc3RhcnQsIHRsZW4pOwogICAgICAgIG91dFt0bGVuXSA9ICdcMCc7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CgogICAgLy8gVW5rbm93biBjaGFyYWN0ZXIg4oCUIHNraXAgaXQKICAgICgqcG9zKSsrOwogICAgcmV0dXJuIDA7Cn0KCi8vIC0tLS0tLS0tLS0gTWFpbiBwYXJzZXIgLS0tLS0tLS0tLQoKdm9pZCBzaGlmdFJlZHVjZVBhcnNlKGNvbnN0IGNoYXIgKmlucHV0KQp7CiAgICB0b3AgPSAtMTsgLy8gUmVzZXQgc3RhY2sKCiAgICBpbnQgcG9zID0gMDsKICAgIGNoYXIgdG9rZW5bNTBdOwoKICAgIHdoaWxlIChuZXh0VG9rZW4oaW5wdXQsICZwb3MsIHRva2VuKSkKICAgIHsKICAgICAgICAvLyBTSElGVDogcHVzaCB0aGUgY3VycmVudCB0b2tlbiBvbnRvIHRoZSBzdGFjawogICAgICAgIHB1c2godG9rZW4pOwogICAgICAgIHByaW50U3RhY2soIlNoaWZ0Iik7CgogICAgICAgIC8vIEFmdGVyIGVhY2ggc2hpZnQsIHRyeSB0byByZWR1Y2UgYXMgbWFueSB0aW1lcyBhcyBwb3NzaWJsZQogICAgICAgIHdoaWxlICh0cnlSZWR1Y2UoKSk7CiAgICB9CgogICAgLy8gQWZ0ZXIgYWxsIGlucHV0IGNvbnN1bWVkLCB0cnkgb25lIGZpbmFsIHJvdW5kIG9mIHJlZHVjdGlvbnMKICAgIHdoaWxlICh0cnlSZWR1Y2UoKSk7CgogICAgLy8gQ2hlY2sgaWYgcGFyc2Ugc3VjY2VlZGVkIChzdGFjayBzaG91bGQgY29udGFpbiBleGFjdGx5IG9uZSAiRSIpCiAgICBpZiAodG9wID09IDAgJiYgc3RyY21wKHN0YWNrWzBdLCAiRSIpID09IDApCiAgICAgICAgcHJpbnRmKCJTdHJpbmcgQWNjZXB0ZWRcbiIpOwogICAgZWxzZQogICAgICAgIHByaW50ZigiU3RyaW5nIFJlamVjdGVkXG4iKTsKfQoKaW50IG1haW4oKQp7CiAgICBjaGFyIGlucHV0WzIwMF07CiAgICBwcmludGYoIkVudGVyIGFuIEV4cHJlc3Npb246XG4iKTsKICAgIGZnZXRzKGlucHV0LCAyMDAsIHN0ZGluKTsKCiAgICAvLyBSZW1vdmUgbmV3bGluZSBpZiBwcmVzZW50CiAgICBpbnQgbGVuID0gc3RybGVuKGlucHV0KTsKICAgIGlmIChsZW4gPiAwICYmIGlucHV0W2xlbiAtIDFdID09ICdcbicpCiAgICAgICAgaW5wdXRbbGVuIC0gMV0gPSAnXDAnOwoKICAgIHNoaWZ0UmVkdWNlUGFyc2UoaW5wdXQpOwoKICAgIHJldHVybiAwOwp9