Implementing Languages (FluentConf)

Implementing Languages (FluentConf)

Programming is hard. Making compilers is harder. Or so people think. The truth is that making a compiler is just a series of small steps, using regular language constructs. It's so easy, we'll make one in this talk.

061e3bae4ce4234a2194d20a382e5d19?s=128

Christopher Pitt

March 08, 2016
Tweet

Transcript

  1. Implementing Languages

  2. Thanks FluentConf

  3. Thanks SilverStripe

  4. I Am Not A Special Snowflake

  5. Compilers Are Not Important

  6. Great Books On The Subject

  7. None
  8. None
  9. Why Is This Useful?

  10. Why Is This Useful? ▸ Improving productivity ▸ Communicating in

    a common domain language ▸ Alternative computational models
  11. Tools You Can Use

  12. Tools You Can Use ▸ Compiler generators ▸ String manipulation

    and state machines
  13. int minutes = 90;

  14. Grammar

  15. Grammar ▸ List of rules which define structure and syntax

    ▸ Each rule is called a lexeme
  16. int minutes = 90; e ! type id = value

    | type id
  17. Lexer

  18. Lexer ▸ Breaks code string into tokens ▸ Lexer ignores

    nesting
  19. e ! type id = value | type id ["type",

    "int"], ["id", "minutes"], ["assign", "="], ["value", "90"],
  20. Parser

  21. Parser ▸ Arranges tokens in a hierarchy ▸ Checks tokens

    for syntax errors
  22. ["type", "int"], ["id", "minutes"], ["assign", "="], ["value", "90"], ["definition", [

    "int", "minutes", "90", ]]
  23. Abstract Syntax Tree

  24. Abstract Syntax Tree ▸ Represents constructs in the compiler's language

  25. ["definition", [ "int", "minutes", "90", ]] new Definition( "int", "minutes",

    "90", )
  26. Interpreter

  27. Interpreter ▸ Calculates immediate effect to context ▸ Always accepts

    and returns a context
  28. new Definition( "int", "minutes", "90", ) let context = {};

    for (let i = 0; i < objects.length; i++) { context = objects[i].applyTo(context); }
  29. Compiler

  30. Compiler ▸ Writes the AST to a new language ▸

    Checks constructs for semantic errors in target language
  31. Recap

  32. int minutes = 90; e ! type id = value

    | type id
  33. e ! type id = value | type id ["type",

    "int"], ["id", "minutes"], ["assign", "="], ["value", "90"],
  34. ["type", "int"], ["id", "minutes"], ["assign", "="], ["value", "90"], ["definition", [

    "int", "minutes", "90", ]]
  35. ["definition", [ "int", "minutes", "90", ]] new Definition( "int", "minutes",

    "90", )
  36. new Definition( "int", "minutes", "90", ) let context = {};

    for (let i = 0; i < objects.length; i++) { context = objects[i].applyTo(context); }
  37. Yay!

  38. Parser Expression Grammar

  39. Parser Expression Grammar ▸ Uses pattern matching to tokenise and

    organise lexemes ▸ Generates a reusable interpreter and/or compiler
  40. { var context = {}; function __set(key, value) { context[key]

    = value; } function __get(key) { return context[key]; } }
  41. start = expression* expression = _ definition _ / _

    inspection _ _ "whitespace" = [ \t\r\n]*
  42. definition "definition" = t:type _ i:id _ assign _ v:value

    _ terminal { __set(i, v); } / t:type _ i:id _ terminal { __set(i, null); }
  43. type "type" = "int" id "identity" = letters:[a-z]+ { return

    letters.join(""); } assign "assign" = "=" value "value" = numbers:[0-9]+ { return parseInt(numbers.join(""), 10); } terminal "terminal" = ";"
  44. inspection "inspection" = "inspect" _ i:id _ terminal { console.log(__get(i));

    }
  45. Thanks CONFERENCES.OREILLY.COM/FLUENT/JAVASCRIPT-HTML-US/PUBLIC/SCHEDULE/DETAIL/46342 @ASSERTCHRIS