CIS552: Advanced Programming

Similar documents
Parsing. Zhenjiang Hu. May 31, June 7, June 14, All Right Reserved. National Institute of Informatics

EECS 700 Functional Programming

University of Utrecht. 1992; Fokker, 1995), the use of monads to structure functional programs (Wadler,

CSCE 314 Programming Languages. Monadic Parsing

CSCE 314 Programming Languages. Functional Parsers

CSCE 314 Programming Languages. Monadic Parsing

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Functional Parsers

Monadic Parsing. 1 Chapter 13 in the book Programming in Haskell (2nd ed.) by. 2 Chapters 10 and 16 in the book Real World Haskell by Bryan

Polymorphism Overview (1A) Young Won Lim 2/20/18

CSE399: Advanced Programming. Handout 2

CSc 372. Comparative Programming Languages. 4 : Haskell Basics. Department of Computer Science University of Arizona

CSc 372 Comparative Programming Languages. 4 : Haskell Basics

FROWN An LALR(k) Parser Generator

Parsing Expressions. Slides by Koen Lindström Claessen & David Sands

CSCE 314 Programming Languages

Monads seen so far: IO vs Gen

Expressions. Parsing Expressions. Showing and Reading. Parsing. Parsing Numbers. Expressions. Such as. Can be modelled as a datatype

Background Type Classes (1B) Young Won Lim 6/14/18

Informatics 1 Functional Programming Lectures 15 and 16. IO and Monads. Don Sannella University of Edinburgh

Introduction to Haskell

Monads and all that III Applicative Functors. John Hughes Chalmers University/Quviq AB

Informatics 1 Functional Programming 19 Tuesday 23 November IO and Monads. Philip Wadler University of Edinburgh

Background Type Classes (1B) Young Won Lim 6/28/18

Advanced Programming Handout 7. Monads and Friends (SOE Chapter 18)

Recursion and Induction: Haskell; Primitive Data Types; Writing Function Definitions

Monads. Functional Programming (CS4011) Monads

Lecture C-10: Parser Combinators - Introduction

Haskell through HUGS THE BASICS

CSCE 314 Programming Languages

Logical Methods in... using Haskell Getting Started

Standard prelude. Appendix A. A.1 Classes

MIT Specifying Languages with Regular Expressions and Context-Free Grammars. Martin Rinard Massachusetts Institute of Technology

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

Thoughts on Assignment 4 Haskell: Flow of Control

CS 209 Functional Programming

INTRODUCTION TO FUNCTIONAL PROGRAMMING

Structurally Recursive Descent Parsing. Nils Anders Danielsson (Nottingham) Joint work with Ulf Norell (Chalmers)

Functional Parsing A Multi-Lingual Killer- Application

MIT Specifying Languages with Regular Expressions and Context-Free Grammars

CS 320: Concepts of Programming Languages

CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

A First Look at ML. Chapter Five Modern Programming Languages, 2nd ed. 1

Functional Programming

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

PROGRAMMING IN HASKELL. Chapter 5 - List Comprehensions

CSc 520. Principles of Programming Languages 11: Haskell Basics

Informatics 1 Functional Programming Lecture 7. Map, filter, fold. Don Sannella University of Edinburgh

Parsing. On to ReadP. Part III: Using the ReadP package. Primitives Repeated from Hutton s Parser.hs. First Examples

2. First Program Stuff

Fusion-powered EDSLs

Monads. Bonus lecture 2017 David Sands

Writing a Lexer. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, February 6, Glenn G.

CS 11 Haskell track: lecture 4. n This week: Monads!

2.2 Syntax Definition

Chapter 15. Functional Programming. Topics. Currying. Currying: example. Currying: example. Reduction

Programming in Haskell Aug Nov 2015

The Haskell HOP: Higher-order Programming

INFOB3TC Solutions for the Exam

Semantics of programming languages

B The SLLGEN Parsing System

The List Datatype. CSc 372. Comparative Programming Languages. 6 : Haskell Lists. Department of Computer Science University of Arizona

Haskell Overview II (2A) Young Won Lim 8/9/16

CSc 372 Comparative Programming Languages

CS 320: Concepts of Programming Languages

Monad Background (3A) Young Won Lim 10/5/17

CS /534 Compiler Construction University of Massachusetts Lowell. NOTHING: A Language for Practice Implementation

Chapter 3: CONTEXT-FREE GRAMMARS AND PARSING Part2 3.3 Parse Trees and Abstract Syntax Trees

Applicative, traversable, foldable

Lecture 19: Functions, Types and Data Structures in Haskell

Programming Paradigms

Programming Languages

Functional Parsing. Languages for Lunch 10/14/08 James E. Heliotis & Axel T. Schreiner

A tour of the Haskell Prelude

Applicative, traversable, foldable

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Functions

According to Larry Wall (designer of PERL): a language by geniuses! for geniuses. Lecture 7: Haskell. Haskell 98. Haskell (cont) - Type-safe!

7. Introduction to Denotational Semantics. Oscar Nierstrasz

Parsing CSP-CASL with Parsec

CS 3360 Design and Implementation of Programming Languages. Exam 1

Monad Background (3A) Young Won Lim 11/18/17

Recursive definition of sets and structural induction

Shell CSCE 314 TAMU. Higher Order Functions

COMP Logic for Computer Scientists. Lecture 23

CIS 194: Homework 4. Due Wednesday, February 18, What is a Number?

Haskell: Lists. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Friday, February 24, Glenn G.

Functional Programming in Haskell Part I : Basics

Haskell Overview II (2A) Young Won Lim 8/23/16

An introduction to functional programming. July 23, 2010

Parsing. Note by Baris Aktemur: Our slides are adapted from Cooper and Torczon s slides that they prepared for COMP 412 at Rice.

It parses an input string of tokens by tracing out the steps in a leftmost derivation.

Programming Languages Fall 2013

Monad Background (3A) Young Won Lim 11/8/17

Haskell Programs. Haskell Fundamentals. What are Types? Some Very Basic Types. Types are very important in Haskell:

Haskell & functional programming, some slightly more advanced stuff. Matteo Pradella

Algebraic Types. Chapter 14 of Thompson

CS422 - Programming Language Design

These notes are intended exclusively for the personal usage of the students of CS352 at Cal Poly Pomona. Any other usage is prohibited without

Semantics of programming languages

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Transcription:

CIS552: Advanced Programming Handout 8 What is a Parser? A parser is a program that analyzes a piece of text to deine its structure (and, typically, returns a tree representing this structure). The World is Full of Parsers! Almost every real-life program involves some kind of parsing... Hugs and GHC parse Haskell programs Unix shells (bash, sh, etc.) parse shell scripts Explorer, Mozilla, etc., parse HTML Command-line utilities parse command lines etc., etc. In Haskell, a parser is naturally viewed as a function: type Parser = String -> Tree However, a parser might not actually use up the whole string, so we also return the unused portion of the input: type Parser = String -> (Tree,String)

Also, a given string might be parseable in many ways (including zero!), so we generalize to a list of results: The result returned by a parser might not always be a tree, so we generalize once more to make the Parser type polymorphic: type Parser = String -> [(Tree,String)] type Parser a = String -> [(a,string)] Finally, for the sake of readability, let s change the type declaration into a newtype and add a constructor on the right-hand side. The convenience function parse takes a parser and applies it to a given string. newtype Parser a = Parser (String -> [(a,string)]) Primitive Parsers parse :: Parser a -> String -> [(a,string)] parse (Parser p) = p Parsing an Arbitrary Character Parsing Nothing (Successfully) The parser item fails if the input is empty, and consumes the first character otherwise: item :: Parser Char item = Parser (\cs -> case cs of "" -> [] (c:cs) -> [(c,cs)]) parse item "hello" [( h,"ello")] The parser returnp a always succeeds, returning the value a without consuming any input: returnp :: a returnp a = Parser (\cs -> [(a,cs)]) parse (returnp 5) "hello" [(5,"hello")] parse item "" []

Putting Parsers in Sequence Example p seqp q is a parser that first applies p and then applies q to each result from p. seqp :: Parser a -> (a -> Parser b) -> Parser b p seqp q = Parser (\cs -> concat [parse (q a) cs (a,cs ) <- parse p cs]) parsetwo :: Parser (Char,Char) parsetwo = item seqp \x -> item seqp \y -> return (x,y) parse parsetwo "hello" [(( h, e ),"llo")] parse parsetwo "h" [] Note that, if any parser in a sequence fails, then the whole sequence fails. The Parser Monad The definitions of returnp and seqp have the right types (and obey the required laws) to make Parser into a monad. Parsers Are a Monad instance Monad Parser where return = returnp (>>=) = seqp The Parser Monad Having made this instance declaration, we can use do syntax to simplify the presentation of the parsetwo function: parsetwo2 :: Parser (Char,Char) parsetwo2 = do x <- item y <- item return (x,y) More Primitives

Parsing Nothing (Unsuccessfully) Parsing a Character If It Satisfies Some Test The parser zerop always fails: zerop :: Parser a zerop = Parser (\cs -> []) The parser sat p behaves like item if the first character on the input string satisfies the predicate p; otherwise it fails. sat sat p :: (Char -> Bool) -> Parser Char = do c <- item if p c then return c else zerop parse (sat (== h )) "hello" [( h,"ello")] parse (sat (== x )) "hello" [] Examples Nondeinistic Choice char :: Char -> Parser Char char c = sat (c ==) alphachar :: Parser Char alphachar = sat isalpha numchar :: Parser Char numchar = sat isdigit digit :: Parser Int digit = do {c <- numchar; return (ord c - ord 0 )} p q yields all the results of applying either p or q to the whole input string. choosep :: Parser a p q = Parser (\cs -> parse p cs ++ parse q cs) alphanum :: Parser Char (isalpha and isdigit come from the Char module in the standard library.) alphanum = alphachar numchar Another Example Yet Another Example p = do { x <- item; return ("Got "++[x]) } do { x <- item; return ("Parsed "++[x]) } parse p "xyz" [("Got x","yz"),("parsed x","yz")] This parser yields a function: addop :: Parser (Int -> Int -> Int) addop = do {char + ; return (+)} do {char - ; return (-)} For example: calc = do x <- digit; op <- addop; y <- digit parse calc "1+2" [(3,"")]

Regognizing a String string s is a parser that recognizes (and returns) exactly the string s: Recursive Parsers string :: String -> Parser String string "" = return "" string (c:cs) = do {char c; string cs; return (c:cs)} Parsing a Sequence A Parser for Arithmetic Expressions many :: Parser a -> Parser [a] many p = many1 p return [] many1 :: Parser a -> Parser [a] many1 p = do {a <- p; as <- many p; return (a:as)} calc1 = do x <- digit op <- addop y <- calc1 digit parse (many numchar) "123ab" [("123","ab"),("12","3ab"),("1","23ab"),("","123ab")] parse calc1 "3+4-1" [(6,""),(7,"-1"),(3,"+4-1")] Note that, for simplicity, we re taking + and - to be right-associative for the moment. Query: What happens if we exchange the arguments to choosep? Multiplication-like Operators As before... mulop :: Parser (Int -> Int -> Int) A Complete Parser mulop = do {char * ; return (*)} do {char / ; return (div)}

expr = do x <- ; op <- addop; y <- expr = do x <- factor; op <- mulop; y <- factor Complete Parser factor = digit do {char ( ; n <- expr; char ) ; return n} A Little More Abstraction Note the similarity in the definitions of expr and. expr = do x <- ; op <- addop; y <- expr = do x <- factor; op <- mulop; y <- factor Can we express them both as instances of a common abstraction? parse expr "(3+4)*5" [(35,""),(7,"*5")] A Little More Abstraction The parser chainl p op consumes a non-empty sequence of ps from the front of the input and combines them together (in the style of foldl) using op. chainl1 :: Parser a -> Parser (a -> a -> a) p chainl1 op = do {a <- p; rest a} where rest a = do {f <- op; b <- p; rest (f a b)} return a A Better Arithmetic Expression Parser expr2,2,factor2 :: Parser Int expr2 = 2 chainl1 addop 2 = factor2 chainl1 mulop factor2 = digit do {char ( ; n <- expr2; char ) ; return n} A similar chaining function also works for empty sequences: chainl :: Parser a -> Parser (a -> a -> a) -> a chainl p op a = (p chainl1 op) return a A Better Arithmetic Expression Parser As a side-benefit, our new expression parser also makes subtraction and division (and addition and multiplication) left-associative: parse expr "9-3-2" -- old [(8,""),(6,"-2"),(9,"-3-2")] Efficiency parse expr2 "9-3-2" -- new [(4,""),(6,"-2"),(9,"-3-2")]

Deinistic Choice Usually, we are interested in getting just one parse of the input string, not all possible parses. The parser p +++ q yields just the first result from by p, if any, and otherwise the first result from q. (+++) :: Parser a p +++ q = Parser (\cs -> case parse (p q) cs of [] -> [] (x:xs) -> [x]) More Efficient Sequencing We can now redefine many in s of +++. many :: Parser a -> Parser [a] many p = many1 p +++ return [] many1 :: Parser a -> Parser [a] many1 p = do {a <- p; as <- many p; return (a:as)} This change ensures that many always returns exactly one result. More Efficient Chaining Similarly, we can redefine chainl and chainl1 in s of +++. chainl1 :: Parser a -> Parser (a -> a -> a) p chainl1 op = do {a <- p; rest a} where rest a = do {f <- op; b <- p; rest (f a b)} +++ return a Wrap Up chainl :: Parser a -> Parser (a -> a -> a) -> a chainl p op a = (p chainl1 op) +++ return a More on Functional Parsing Parsing technology is a large and complex research area, extending back to the 1950s and still continuing today. (E.g., see many recent papers on Generalized LR parsing, packrat parsing, etc.) Functional parsing is also an active research topic, whose surface we have just scratched here. further efficiency improvements error reporting and correction infix operator precedence support for almost deinistic grammars The MonadPlus Class MonadPlus is an extension of the Monad class that adds a couple of extra operations. It is not as critical as Monad, but there are some library functions that rely on MonadPlus for a few useful things. class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a Parsers are an instance of MonadPlus: instance MonadPlus Parser where mzero = zerop mplus = choosep