As we have seen, token attribute values are supplied via yylval, as in. More on Yacc s value stack

Similar documents
CSE302: Compiler Design

Compiler Lab. Introduction to tools Lex and Yacc

Syntax Analysis Part IV

CSCI Compiler Design

Syntax-Directed Translation

Yacc: A Syntactic Analysers Generator

LECTURE 11. Semantic Analysis and Yacc

Lex & Yacc. By H. Altay Güvenir. A compiler or an interpreter performs its task in 3 stages:

Using an LALR(1) Parser Generator

Lex & Yacc. by H. Altay Güvenir. A compiler or an interpreter performs its task in 3 stages:

Introduction to Yacc. General Description Input file Output files Parsing conflicts Pseudovariables Examples. Principles of Compilers - 16/03/2006

Chapter 2: Syntax Directed Translation and YACC

PRACTICAL CLASS: Flex & Bison

Principles of Programming Languages

COMPILER CONSTRUCTION LAB 2 THE SYMBOL TABLE. Tutorial 2 LABS. PHASES OF A COMPILER Source Program. Lab 2 Symbol table

Syntax-Directed Translation. Introduction

Prof. Mohamed Hamada Software Engineering Lab. The University of Aizu Japan

Yacc Yet Another Compiler Compiler

An Introduction to LEX and YACC. SYSC Programming Languages

Context-free grammars

Parsing How parser works?

Compiler construction 2002 week 5

Compiler Construction: Parsing

CSC 467 Lecture 3: Regular Expressions

Compiler construction in4020 lecture 5

Compiler construction 2005 lecture 5

Syn S t yn a t x a Ana x lysi y s si 1

Introduction to Lex & Yacc. (flex & bison)

I 1 : {E E, E E +E, E E E}

Lesson 10. CDT301 Compiler Theory, Spring 2011 Teacher: Linus Källberg

TDDD55 - Compilers and Interpreters Lesson 3

Yacc. Generator of LALR(1) parsers. YACC = Yet Another Compiler Compiler symptom of two facts: Compiler. Compiler. Parser

COMPILERS AND INTERPRETERS Lesson 4 TDDD16

Compiler Design 1. Yacc/Bison. Goutam Biswas. Lect 8

COP5621 Exam 3 - Spring 2005

Lexical and Parser Tools

TDDD55- Compilers and Interpreters Lesson 3

Lex & Yacc (GNU distribution - flex & bison) Jeonghwan Park

Compil M1 : Front-End

COMPILER CONSTRUCTION Seminar 02 TDDB44

Compiler Construction

Applications of Context-Free Grammars (CFG)

Lexical and Syntax Analysis

Preparing for the ACW Languages & Compilers

Compiler Construction

CS4850 SummerII Lex Primer. Usage Paradigm of Lex. Lex is a tool for creating lexical analyzers. Lexical analyzers tokenize input streams.

Big Picture: Compilation Process. CSCI: 4500/6500 Programming Languages. Big Picture: Compilation Process. Big Picture: Compilation Process.

Syntax Analysis Part VIII

Compiler Design Prof. Y. N. Srikant Department of Computer Science and Automation Indian Institute of Science, Bangalore

Using Lex or Flex. Prof. James L. Frankel Harvard University

Gechstudentszone.wordpress.com

A Bison Manual. You build a text file of the production (format in the next section); traditionally this file ends in.y, although bison doesn t care.

CS415 Compilers Context-Sensitive Analysis Type checking Symbol tables

Lecture 14 Sections Mon, Mar 2, 2009

IN4305 Engineering project Compiler construction

RYERSON POLYTECHNIC UNIVERSITY DEPARTMENT OF MATH, PHYSICS, AND COMPUTER SCIENCE CPS 710 FINAL EXAM FALL 96 INSTRUCTIONS

I. OVERVIEW 1 II. INTRODUCTION 3 III. OPERATING PROCEDURE 5 IV. PCLEX 10 V. PCYACC 21. Table of Contents

Etienne Bernard eb/textes/minimanlexyacc-english.html

EXPERIMENT NO : M/C Lenovo Think center M700 Ci3,6100,6th Gen. H81, 4GB RAM,500GB HDD

CS143 Handout 04 Summer 2011 June 22, 2011 flex In A Nutshell

Figure 2.1: Role of Lexical Analyzer

Topic 5: Syntax Analysis III

2068 (I) Attempt all questions.

Lexical Analysis. Implementing Scanners & LEX: A Lexical Analyzer Tool

More On Syntax Directed Translation

Syntax Analysis The Parser Generator (BYacc/J)

Big Picture: Compilation Process. CSCI: 4500/6500 Programming Languages. Big Picture: Compilation Process. Big Picture: Compilation Process

Context-Free Grammar. Concepts Introduced in Chapter 2. Parse Trees. Example Grammar and Derivation

CS143 Handout 12 Summer 2011 July 1 st, 2011 Introduction to bison

LECTURE 7. Lex and Intro to Parsing

Summary: Semantic Analysis

Over-simplified history of programming languages

Parsing Techniques. AST Review. AST Data Structures. Implicit AST Construction. AST Construction CS412/CS413. Introduction to Compilers Tim Teitelbaum

COMP 181. Prelude. Prelude. Summary of parsing. A Hierarchy of Grammar Classes. More power? Syntax-directed translation. Analysis

flex is not a bad tool to use for doing modest text transformations and for programs that collect statistics on input.

Hyacc comes under the GNU General Public License (Except the hyaccpar file, which comes under BSD License)

Programming Language Syntax and Analysis

Lex and Yacc. More Details

Module 8 - Lexical Analyzer Generator. 8.1 Need for a Tool. 8.2 Lexical Analyzer Generator Tool

Handout 7, Lex (5/30/2001)

Syntax-Directed Translation. Lecture 14

Semantic actions for declarations and expressions

Semantic Analysis with Attribute Grammars Part 3

Semantic actions for declarations and expressions. Monday, September 28, 15

Syntax-Directed Translation Part I

Flex and lexical analysis

Parsing Techniques. AST Review. AST Data Structures. LL AST Construction. AST Construction CS412/CS413. Introduction to Compilers Tim Teitelbaum

Parsing and Pattern Recognition

LR Parsing. Leftmost and Rightmost Derivations. Compiler Design CSE 504. Derivations for id + id: T id = id+id. 1 Shift-Reduce Parsing.

Syntax-Directed Translation. Concepts Introduced in Chapter 5. Syntax-Directed Definitions

EXPERIMENT NO : M/C Lenovo Think center M700 Ci3,6100,6th Gen. H81, 4GB RAM,500GB HDD

SYED AMMAL ENGINEERING COLLEGE (An ISO 9001:2008 Certified Institution) Dr. E.M. Abdullah Campus, Ramanathapuram

Group A Assignment 3(2)

Structure of a compiler. More detailed overview of compiler front end. Today we ll take a quick look at typical parts of a compiler.

TDDD55- Compilers and Interpreters Lesson 2

Review main idea syntax-directed evaluation and translation. Recall syntax-directed interpretation in recursive descent parsers

Syntax-Directed Translation. CS Compiler Design. SDD and SDT scheme. Example: SDD vs SDT scheme infix to postfix trans

HW8 Use Lex/Yacc to Turn this: Into this: Lex and Yacc. Lex / Yacc History. A Quick Tour. if myvar == 6.02e23**2 then f(..!

Compiler Front-End. Compiler Back-End. Specific Examples

Automatic Scanning and Parsing using LEX and YACC

Transcription:

More on Yacc s value stack As we noted last time, Yacc uses a second stack to store the attribute values of the tokens and terminals in the parse stack. For a token, the attributes are computed by the lexical analyzer, and pushed on the value stack when the token is shifted. For a variable, the attributes are computed when (just before) a reduction to that variable is carried out, and pushed onto the value stack when the variable is pushed onto the parse stack. (After popping the values corresponding to the rhs of the production used in the reduction.) All of this works nicely for S-attributed definitions: syntax-directed definitions that use only synthesized attributes. As we have seen, token attribute values are supplied via yylval, as in %token NUMBER expr : expr + NUMBER { $$ = $1 + $3 expr - NUMBER { $$ = $1 - $3 NUMBER { $$ = $1 ( expr ) { $$ = $2 #include "lex.yy.c" yyerror(char *s) { printf("%s\n", s) main() { yyparse() number 0 [1-9][0-9]* [ ] { {number { sscanf(yytext, "%d", &yylval) return NUMBER \n. { return yytext[0] int yywrap() { return (1) When the token is shifted, yylval is pushed onto the attribute stack. 1 2

The type used in the value stack can be changed. For instance, we can use doubles, as in your hwk... #include <stdio.h> #define YYSTYPE double % %token NUMBER %left + - %left * / %right UMINUS lines : lines expr \n { printf("%g\n", $2) lines \n expr : expr + expr { $$ = $1 + $3 expr - expr { $$ = $1 - $3 expr * expr { $$ = $1 * $3 expr / expr { $$ = $1 / $3 ( expr ) { $$ = $2 - expr %prec UMINUS { $$ = - $2 NUMBER #include "lex.yy.c" number [0-9]+\.? [0-9]*\.[0-9]+ [ ] { {number { sscanf(yytext, "%lf", &yylval) return NUMBER \n. { return yytext[0] There are other possibilities... #include <ctype.h> % %union { char s[64] char c %type <s> expr %token <c> DIGIT %left + - line : line expr \n { printf("%s\n", $2) expr : expr + expr { strcpy($$,strcat(strcat($1,$3),"+")) expr - expr { strcpy($$,strcat(strcat($1,$3),"-")) ( expr ) { strcpy($$,$2) DIGIT { $$[0] = $1 $$[1] = \0 yylex() { int c while ((c=getchar()) == ) if (isdigit(c)) { yylval.c = c return DIGIT return c yyerror(char *s) { printf("%s\n", s) main() { yyparse() 3 4

Although we assume that the attributes of tokens are synthesized, those attributes may still depend on other aspects of the parse... For example, in a desk calculator (as in Appendix A of the Yacc document) we may allow assignments of values to identifiers. In this case it may be convenient to have synthesized attributes lexeme and value for token id. Interestingly, the value attribute at a node would presumably be computed by looking up id.lexeme in a symbol table If the lexeme is not already in the table, make an entry for it (and perhaps give it a default value). If the lexeme is already in the table, then get the corresponding value from the table. Notice that this value is in some sense inherited: it is there because of a previous occurrence of an identifier with the same lexeme, perhaps in an assignment statement. #include <stdio.h> struct id { char *s double v #define TABLESIZE 4 struct id table[tablesize] struct id *entry(char *) % %union { double v struct id *i %type <v> expr %token <v> NUM %token <i> ID stat : expr { printf("%g\n", $1) ID = expr { $1->v = $3 number [0-9]+\.? [0-9]*\.[0-9]+ id [a-za-z][a-za-z0-9]* {number { sscanf(yytext, "%lf", &yylval.v) return NUM {id { yylval.i = entry(yytext) return ID Here entry should return the id pointer for the lexeme s table entry if the lexeme is new, entry enters it in the table. 5 6

Inherited attributes So far we have focused on synthesized attributes, with good reason they are convenient for use with LR parsers. Once we allow inherited attributes, it becomes more difficult to annotate the parse tree. In fact, if there are cycles in the semantic rules, it may be impossible. Certainly there is no guarantee that the attributes can be computed in a single pass through the tree in any order much less bottom-up order. Unfortunately, inherited attributes are in some cases more natural. Here is an example involving variable declarations: D T L L L, id $1.type := $$.type addentry($3.lexeme,$$.type) L id addentry($1.lexeme,$$.type) D T L L L, id $1.type := $$.type addentry($3.lexeme,$$.type) L id addentry($1.lexeme,$$.type) Not difficult to build and annotate a parse tree for int x, y, for example, but let s parse it bottom up and try to think about computing attributes as we go: STACK INPUT ACTION int id, id$ shift int id, id$ r2 { T.type = integer T id, id$ shift T id, id$ r5 { addentry(id.lexeme,l.type)!! T L, id $ r4 { L.type = L1.type, addentry(id.lexeme,l1.type)!! T L1 $ r1 { L1.type = T.type D $ accept As the book explains, this is a case when we can finesse the problem, but you have to manipulate the attribute value stack... 7 8

D T L L L, id L id $1.type := $$.type addentry($3.lexeme,$$.type) addentry($1.lexeme,$$.type) D T L L L, id L id $1.type := $$.type addentry($3.lexeme,$$.type) addentry($1.lexeme,$$.type) In this case, an LR parser can manage to make the crucial symbol table entries. The key is that you can get by without computing L.type attributes instead notice that T.type sits at the bottom of the attribute stack throughout the parse. Just before you reduce by the fourth production, you will have id.lexeme on top of the attribute stack, and T.type will be three down from the top. So you are still able to make the type entry in the symbol table (by reaching down into the stack ). Similarly, just before you reduce by the fifth production, you will have id.lexeme on top of the attribute stack, and T.type will be one down from the top. So what does this approach look like? Instead of the above, we have: D T L L L, id addentry($3.lexeme,$0.type) L id addentry($1.lexeme,$0.type) STACK INPUT ACTION int id, id$ shift int id, id$ r2 { $$.type = integer T id, id$ shift T id, id$ r5 { addentry(id.lexeme,$0.type)!! T L, id $ r4 { addentry(id.lexeme,$0.type)!! T L1 $ r1 { L1.type = T.type D $ accept 9 10

The book discusses how this might be approached systematically (when it can be done at all). Of course another approach is available here. We can alter the syntax-directed definition, making it possible to perform all actions at the time of reduction during a bottom up parse, without having to know about values of non-rhs elements that may be buried in the value stack. D T L L L, id $1.type := $$.type addentry($3.lexeme,$$.type) L id addentry($1.lexeme,$$.type) D D D T id $$.type := $1.type addentry($2.lexeme,$1.type) D D, id $$.type := $1.type addentry($3.lexeme,$1.type) In fact, in this case we eliminate all inherited attributes. This syntax-directed definition is arguably less natural though. Let s look at the sneak-a-peak mechanism in action in Yacc... #include <stdio.h> % %token NUMBER trick : NUMBER list \n list : list x { printf("%d down 2\n",$0) x { printf("%d down 1\n",$0) #include "lex.yy.c" yyerror(char *s) { printf("%s\n", s) main() { yyparse() number 0 [1-9][0-9]* [ ] { {number { sscanf(yytext, "%d", &yylval) return NUMBER \n. { return yytext[0] int yywrap() { return (1) 11 12

> yacc l26.y > lex l26.l > cc -o l26y y.tab.c >./l26y 777 x x x 777 down 1 777 down 2 777 down 2 T NUMBER L \n L L x L x printf("%d down 2\n",$0) printf("%d down 1\n",$0) For next time and after Last homework due. Final on Saturday 12/16 at noon. Open book, open notes. Cumulative. Assigned reading, lectures, lecture notes, homeworks, labs. STACK INPUT ACTION NUMBERxxx\n$ shift NUMBER xxx\n$ shift NUMBER x xx\n$ r3 { printf("%d down 1\n",$0) NUMBER L xx\n$ shift NUMBER L x x\n$ r2 { printf("%d down 2\n",$0) NUMBER L x\n$ shift NUMBER L x \n$ r2 { printf("%d down 2\n",$0) NUMBER L \n$ shift NUMBER L \n $ r1 T $ accept 13 14