Visual Studio Code互換なsyntax highlighterの実装

Visual Studio Code互換なsyntax highlighterの実装

3781f49ea2c76d6ecf0c6cda46096d49?s=128

omochimetaru

March 01, 2019
Tweet

Transcript

  1. Visual Studio Codeޓ׵ͳ syntax highlighterͷ࣮૷ Θ͍Θ͍swiftc #9 omochimetaru 1

  2. Syntax highlight ςΩετΛͦͷߏจʹԠͯ͡৭෇͚͢Δ →ߏจղੳ͕ඞཁ 2

  3. ߏจͷղੳ ྫ͑͹SwiftίϯύΠϥ lib/Parse/Lexer.cpp lib/Parse/Parser.cpp ෳࡶͰ๲େͳϩδοΫ ϓϩάϥϛϯά͕ඞཁ 3

  4. ςΩετΤσΟλ ͍Ζ͍ΖͳݴޠߏจʹରԠ ઃఆϑΝΠϧͷܗͰΤσΟλͷϦϏϧυແ͠ʹ௥ Ճ/࡟আ͕Մೳ 4

  5. ۙ೥ͷτϨϯυ • TextMate • Sublime Text • Atom • Visual

    Studio Code ͜ΕΒશ͕ͯTextMateܗࣜΛ࠾༻ 5
  6. TextMate Syntaxͷશମߏ଄ Syntax parser͕ςΩετΛτʔΫϯྻʹ෼ׂ͢Δ τʔΫϯʹ͸είʔϓׂ͕Γ౰ͯΒΕΔ ςʔϚγεςϜ͕είʔϓʹج͍ͮͯண৭͢Δ ͜ͷ࿩ͷςʔϚ͸લஈͷSyntax parser͚ͩ 6

  7. Scopes 7

  8. 8

  9. VSCodeͷSyntaxΠϯεϖΫ λ Command + Shift + P → Developer: Inspect

    TM Scopes ΍ͬͯΈΑ͏ 9
  10. Scopes είʔϓ͸ೖΕࢠʹͳ͍ͬͯΔɺ͔ͭɺ ͦΕͧΕͷείʔϓ΋֊૚Խ͞Ε͍ͯΔ ॊೈͳண৭ઃఆ͕Ͱ͖Δ ΦʔτΠϯσϯτɺΞ΢τϥΠϯநग़ɺίʔυ ϑΥʔϧσΟϯάͳͲ͕࡞ΕΔ 10

  11. ߏจͷೖΕࢠ 11

  12. 12

  13. ߏจͷೖΕࢠ ͋Δݴޠͷߏจͷதʹɺ ผͷݴޠͷߏจΛຒΊࠐΊΔ 13

  14. TextMate Syntaxͷղઆ جຊฤ ஫: Ҏ߱ͷ༻ޠ΍໋໊͸ΦϑΟγϟϧͳ΋ͷͱ ๻ͷউखͳ໋໊͕ࠞࡏ͢Δ (ެࣜจॻෆ଍ͷͨΊ) 14

  15. ؆୯ͳ࣮ྫ JSONͷߏจఆٛ https://github.com/Microsoft/vscode/blob/ master/extensions/json/syntaxes/ JSON.tmLanguage.json Ҏޙɺ͜ͷJSONϑΝΠϧΛదٓলུ͠ͳ͕ΒҾ ༻͢Δ 15

  16. { "name": "JSON (Javascript Next)", "scopeName": "source.json", "patterns": [ ],

    "repository": { "array": { }, "comments": { }, "constant": { }, "number": { }, "object": { }, "string": { }, "objectkey": { }, "stringcontent": { }, "value": { } } } 16
  17. ߏจఆٛͷߏ଄ • ͋Δݴޠͷߏจͷ͜ͱΛGrammarͱݺͿ • Grammar͸RuleΛͨ͘͞Μ༻ҙͨ͠΋ͷ • Rule͸Repositoryʹ໊લͱڞʹ֨ೲ͞ΕΔ • Grammar͸ͦΕࣗ਎ϧʔτϨϕϧͷRuleͰ΋͋Δ •

    Rule͸RepositoryΛ࣋ͯΔ • scopeName͕GrammarͷϘτϜͷείʔϓʹͳΔ ͔͜͜Β͸(೴಺Ͱ)࣮૷͠ͳ͕Βฉ͍ͯ΄͍͠ 17
  18. { "patterns": [ { "include": "#value" } ], "repository": {

    "array": { }, "comments": { }, "constant": { }, "number": { }, "object": { }, "string": { }, "objectkey": { }, "stringcontent": { }, "value": { "patterns": [ { "include": "#constant" }, { "include": "#number" }, { "include": "#string" }, { "include": "#array" }, { "include": "#object" }, { "include": "#comments" } ] } } } 18
  19. Include Rule • includeύϥϝʔλͰଞͷRuleΛࢀর͢Δϧʔ ϧ • #<name>ͰRepositoryͷத͔Β<name>Λ୳ࡧ • Repository͔Βͷ୳ࡧ͸࠶ؼతʹ਌ϧʔϧ΁Ҡ ৡ͞ΕΔ

    19
  20. Hub Rule • patternsύϥϝʔλͰࢠϧʔϧୡΛ͚࣋ͭͩͷ ϧʔϧ • ແ৚݅Ͱ͋Γ͜ͷϧʔϧʹ͸҉໧ʹϚον͢Δ • GrammarͷϧʔτRule͸ίϨ •

    ઌͷྫͰ͸#value΋ίϨ 20
  21. { "repository": { "constant": { "match": "\\b(?:true|false|null)\\b", "name": "constant.language.json" },

    "number": { "match": "(?x) # turn on extended mode\n" " -? # an optional minus\n" " (?:\n" " 0 # a zero\n" " | # ...or...\n" " [1-9] # a 1-9 character\n" " \\d* # followed by zero or more digits\n" " )\n" " (?:\n" " (?:\n" " \\. # a period\n" " \\d+ # followed by one or more digits\n" " )?\n" " (?:\n" " [eE] # an e character\n" " [+-]? # followed by an option +/-\n" " \\d+ # followed by one or more digits\n" " )? # make exponent optional\n" " )? # make decimal portion optional", "name": "constant.numeric.json" }, } } number.match͸දࣔͷ౎߹্෼ׂ͍ͯ͠·͕࣮͢ࡍʹ͸1ͭͷ௕͍จࣈྻͰ͋Δɻ 21
  22. Match Rule • matchύϥϝʔλͷਖ਼نදݱΛςετͯ͠Ϛο ν͢Δϧʔϧ • ਖ਼نදݱํݴ͸OnigurumaΛ࠾༻ • Ϛονͨ͠ΒnameͰࢦఆͨ͠είʔϓΛ༩͑ Δ

    22
  23. JSONͷ਺஋ͷਖ਼نදݱ (?x) # turn on extended mode -? # an

    optional minus (?: 0 # a zero | # ...or... [1-9] # a 1-9 character \d* # followed by zero or more digits )\n (?: (?: \. # a period \d+ # followed by one or more digits )? (?: [eE] # an e character\n [+-]? # followed by an option +/- \d+ # followed by one or more digits )? # make exponent optional )? # make decimal portion optional ๯಄ͷ(?x)Ͱ֦ுه๏ϞʔυΛ։࢝ͯ͠վߦͱίϝϯτΛ༗ޮԽ 23
  24. ਖ਼نදݱຊମ͸͜Ε https://www.json.org 24

  25. ߦ୯Ґॲཧϧʔϧ TextMate SyntaxͰ͸ɺ͜ΕΒϚονϯάॲཧ͸ର ৅ͷςΩετʹରͯ͠ߦ୯ҐͰॲཧ͞ΕΔ ΋͠ɺվߦΛ·͍ͨͩਖ਼نදݱ͕͋Δ৔߹ɺશ͘ Ϛον͠ͳ͍ είʔϓׂ౰ʹΑΔτʔΫϯ෼ׂ͸ςΩετͷվ ߦ෦෼Ͱඞͣ෼அ͞ΕΔ 25

  26. { "repository": { "array": { "begin": "\\[", "end": "\\]", "name":

    "meta.structure.array.json", "patterns": [ { "include": "#value" }, { "match": ",", "name": "punctuation.separator.array.json" }, { "match": "[^\\s\\]]", "name": "invalid.illegal.expected-array-separator.json" } ] }, } } 26
  27. BeginEnd Rule • beginύϥϝʔλͷਖ਼نදݱʹϚον͔ͯ͠Βɺ endύϥϝʔλͷਖ਼نදݱʹϚον͢Δ·Ͱͷൣ ғΛɺࣗ਎ʹϚον͢Δϧʔϧ • nameύϥϝʔλͷείʔϓΛࣗ਎ʹϚονͨ͠ൣ ғʹ༩͑Δ •

    beginͱendʹڬ·Εͨ෦෼ʹ͍ͭͯɺpatternsύ ϥϝʔλͷࢠϧʔϧୡΛద༻ͤ͞Δ ͜ΕʹΑΓೖΕࢠ͕࣮ݱͰ͖Δ 27
  28. ParserͷϚονϯάಈ࡞ Parser͸ݱࡏͷϧʔϧͱݱࡏͷςΩετҐஔΛ࣋ͭ ݱࡏͷϧʔϧ͔ΒભҠ͠͏Δϧʔϧͷ͏ͪɺ࠷΋ ϚονϯάҐஔ͕ࠨʹདྷΔ΋ͷʹϚον͢Δ ࣮૷ͱͯ͠͸ɺෳ਺ͷਖ਼نදݱΛϚονͤͯ͞Έ ͯɺ݁Ռ͕࠷΋ࠨʹ͋ͬͨ΋ͷΛ࠾༻͢Δ੍ޚͱ ͳΔ ϚονϯάҐஔ͕ಉ͡ͳΒɺϚονϯάϦετͰ ઌʹ͋Δ΋ͷ͕༏ઌ͢Δ 28

  29. JSONจ๏ͰͷϚονϯάϦ ετ rootͷ࣌ • \b(?:true|false|null)\b: root[0]→value[0]→constant.match • (?x)...: root[0]→value[1]→number.match •

    \": root[0]→value[2]→string.begin • \[": root[0]→value[3]→array.begin • \{: root[0]→value[4]→object.begin • /\*\*(?!/): root[0]→value[5]→comments[0] • /\*: root[0]→value[5]→comments[1] • (//).*$\n?: root[0]→value[5]→comments[2] 29
  30. arrayͷ࣌ • \]: array.end • \b(?:true|false|null)\b: array[0]→value[0]→constant.match • (?x)...: array[0]→value[1]→number.match

    • \": array[0]→value[2]→string.begin • \[": array[0]→value[3]→array.begin • \{: array[0]→value[4]→object.begin • /\*\*(?!/): array[0]→value[5]→comments[0] • /\*: array[0]→value[5]→comments[1] • (//).*$\n?: array[0]→value[5]→comments[2] • ,: array[1].match • [^\s\]]: array[2].match 30
  31. ͜ͷϚονϯάϦετΛݟ͍ͯΔͱɺ࠶ؼԼ߱ߏ จղੳύʔαͷɺ࣍ͷτʔΫϯΛઌಡΈͯ͠ಛఆ ͷจ๏ϊʔυʹಥೖ͢Δॲཧͱɺಉ͡Α͏ͳߏ଄ ʹͳ͍ͬͯΔ গʑͷنଇͷσʔλʹΑͬͯɺߏจ͕දݱͰ͖ͯ ͍Δ͜ͱ͕Θ͔Δ 31

  32. ߦ୯Ґ࣮ߦ ΤσΟλ͔Βར༻͢Δʹ͋ͨͬͯɺςΩετ͕ڊ େͳ৔߹ʹɺ෦෼มߋͷͨͼʹશจΛ࠶ॲཧͨ͠ ͘ͳ͍ɻਐḿ཰Λग़ͨ͠ΓɺඇมߋՕॴʹରͯ͠ աڈͷ݁Ռͷ࠶ར༻ΛࢼΈΔͨΊʹɺ͜ͷߏจղ ੳث͸ɺߦ୯ҐͰύʔεॲཧΛதஅɾ࠶։͕Մೳ ʹ࣮૷͍ͨ͠ɻ 32

  33. ࠶ؼͰ࣮૷͢ΔͷͰ͸ͳ͘ɺελοΫΛ࢖ͬͯ ϧʔϓͰ࣮૷͢Δɻ let parser = Parser(string: string, grammar: grammar) while

    !parser.isAtEnd { let tokens: [Token] = try parser.parseLine() } 33
  34. ݴޠຒΊࠐΈ Include Ruleͷincludeύϥϝʔλ͸ผͷGrammar Λࢦఆ͢Δ͜ͱ͕Ͱ͖Δ • <scope>: ͜ͷείʔϓ໊ΛscopeNameʹ࣋ͭ GrammarͷϧʔτRuleΛࢀর 34

  35. Objective-Cͷߏจ͸CͷߏจΛؚΉ { "name": "Objective-C", "scopeName": "source.objc", "patterns": [ { },

    { }, { }, { }, ..., { "include": "source.c" }, { } ] } 35
  36. HTMLͷߏจͷதͰPHPͷߏจΛݺͿ { "name": "PHP", "scopeName": "text.html.php", "repository": { "php-tag": {

    "patterns": [ { "begin": "<\\?(?i:php|=)?(?![^?]*\\?>)", "end": "(\\?)>", "name": "meta.embedded.block.php", "contentName": "source.php", "patterns": [ { "include": "source.php" } ] }, ] } } } 36
  37. جຊฤ ·ͱΊ • Grammar, Repository, Rule • Hub, Include, Match,

    BeginEnd • ݱࡏͷRule • ϚονϦετͷચ͍ग़͠ • ࠷΋ࠨͰϚονͨ͠ਖ਼نදݱ • ߦ୯Ґॲཧ ࢓૊Έͷࠎ૊Έ͸͜Ε͚ͩ 37
  38. TextMate Syntaxͷղઆ ൃలฤ 38

  39. ൃలฤ ·ͩઆ໌͍ͯ͠ͳ͍ύϥϝʔλ΍ػೳ͕ͨ͘͞Μ ͋Δ 39

  40. Ωϟϓνϟάϧʔϓείʔϓ 40

  41. { "captures": { "1": { "name": "support.function.construct.php" }, "2": {

    "name": "punctuation.definition.array.begin.php" }, "3": { "name": "punctuation.definition.array.end.php" } }, "match": "(array)(\\()(\\))", "name": "meta.array.empty.php" } 41
  42. { "array": { "begin": "\\[", "beginCaptures": { "0": { "name":

    "punctuation.definition.array.begin.json" } }, "end": "\\]", "endCaptures": { "0": { "name": "punctuation.definition.array.end.json" } }, "name": "meta.structure.array.json", "patterns": [ ... ] } } 42
  43. Match Ruleͷmatch΍BeginEnd Ruleͷbeginͱ endͷਖ਼نදݱʹରͯ͠ɺΩϟϓνϟάϧʔϓʹ ࢦఆͨ͠είʔϓ໊Λ༩͑Δɻ0൪͸ਖ਼نදݱ Ϛονશମɻ BeginEnd RuleͰ΋captures͕ࢦఆͰ͖ɺ beginCapturesͱendCapturesͷ྆ํʹಉ͡஋Λ ༩͑Δɻ

    capturesͱbeginCapturesͷॏෳ࣌͸ޙऀ͕༏ ઌɻ 43
  44. Ωϟϓνϟάϧʔϓ಺ͷࢠϧʔϧ 44

  45. { "begin": "(?x)\\s*\n" "\t\t\t\t\t ((?:(?:final|abstract|public|private|protected|static)\\s+)*)\n" "\t\t\t\t (function)\n" "\t\t\t\t (?:\\s+|(\\s*&\\s*))\n" "\t\t\t\t

    (?:\n" "\t\t\t\t (__(?:call|construct|destruct|get|set|isset|unset|tostring|" "clone|set_state|sleep|wakeup|autoload|invoke|callStatic))\n" "\t\t\t\t |([a-zA-Z0-9_]+)\n" "\t\t\t\t )\n" "\t\t\t\t \\s*\n" "\t\t\t\t (\\()", "beginCaptures": { "1": { "patterns": [ { "match": "final|abstract|public|private|protected|static", "name": "storage.modifier.php" } ] }, "2": { "name": "storage.type.function.php" }, "3": { "name": "storage.modifier.reference.php" }, "4": { "name": "support.function.magic.php" }, "5": { "name": "entity.name.function.php" }, "6": { "name": "punctuation.definition.parameters.begin.php" } } } 45
  46. ΩϟϓνϟάϧʔϓͷதͰࢠϧʔϧΛ༩͑Δɻ 46

  47. endύϥϝʔλͰͷޙํࢀর 47

  48. { "begin": "(?><<-(\\w+))", "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.ruby" }

    }, "comment": "heredoc with indented terminator", "end": "\\s*\\1$", "endCaptures": { "0": { "name": "punctuation.definition.string.end.ruby" } }, "name": "string.unquoted.heredoc.ruby", "patterns": [ { "include": "#heredoc" }, { "include": "#interpolated_ruby" }, { "include": "#escaped_char" } ] } 48
  49. beginͷΩϟϓνϟάϧʔϓΛendͰޙํࢀরͰ͖ Δ print <<EOS # ࣝผࢠ EOS ·Ͱ͕ϦςϥϧʹͳΔ the string

    next line EOS 49
  50. \G 50

  51. { "begin": "(^[ \\t]+)?(?=//)", "beginCaptures": { "1": { "name": "punctuation.whitespace.comment.leading.php"

    } }, "end": "(?!\\G)", "patterns": [ { "begin": "//", "beginCaptures": { "0": { "name": "punctuation.definition.comment.php" } }, "end": "\\n|(?=\\?>)", "name": "comment.line.double-slash.php" } ] } 51
  52. Ұൠతͳਖ਼نදݱʹ͓͍ͯ͸ɺ܁Γฦ͠ϚονΛ ͢Δ৔߹ͷʮલճͷϚον຤ඌʯͳ͍͠͸ʮݕࡧ ։࢝Ґஔʯɻ begin΍matchͰ࢖ΘΕͨ৔߹͸ʮݕࡧ։࢝Ґ ஔʯɻendͰ࢖ΘΕͨ৔߹͸ʮbeginͷϚον຤ ඌʯɻ ߦ൪߸Λߟྀͯ͠ਖ਼نදݱΤϯδϯʹ\GͷҐஔΛ ༩͑Δɻ 52

  53. contentName 53

  54. { "string-double-quoted": { "begin": "\"", "beginCaptures": { "0": { "name":

    "punctuation.definition.string.begin.php" } }, "contentName": "meta.string-contents.quoted.double.php", "end": "\"", "endCaptures": { "0": { "name": "punctuation.definition.string.end.php" } }, "name": "string.quoted.double.php", "patterns": [ { "include": "#interpolation" } ] } 54
  55. contentName͸beginͱendʹڬ·Εͨ෦෼ʹε ίʔϓΛ༩͑Δɻ name͸beginͱendΛؚΉɻ 55

  56. applyEndPatternLast 56

  57. { "begin": "\\?", "beginCaptures": { "0": { "name": "keyword.operator.ternary.c" }

    }, "end": ":", "applyEndPatternLast": true, "endCaptures": { "0": { "name": "keyword.operator.ternary.c" } }, "patterns": [ { "include": "#access" }, { "include": "#libc" }, { "include": "#c_function_call" }, { "include": "$base" } ] } 57
  58. beginʹϚονͯ͠BeginEnd Ruleͷ಺෦ʹډΔ ͱ͖ɺ௨ৗ͸endϧʔϧ͸࠷ߴ༏ઌ౓͕ͩɺ applyEndPatternLast͕ࢦఆ͞Ε͍ͯΔͱ͖͸end ϧʔϧ͕࠷௿༏ઌ౓ʹͳΔɻ 58

  59. $self 59

  60. { "begin": "\\b(require|require_relative|gem)\\b", "captures": { "1": { "name": "keyword.other.special-method.ruby" }

    }, "end": "$|(?=#|\\})", "name": "meta.require.ruby", "patterns": [ { "include": "$self" } ] } 60
  61. ͦͷRule͕ఆٛ͞ΕͨGrammarͷϧʔτRuleΛ ࢀর͢Δɻ 61

  62. $base 62

  63. { "parens": { "begin": "\\(", "beginCaptures": { "0": { "name":

    "punctuation.section.parens.begin.c" } }, "end": "\\)", "endCaptures": { "0": { "name": "punctuation.section.parens.end.c" } }, "name": "meta.parens.c", "patterns": [ { "include": "$base" } ] } } 63
  64. ݱࡏͷςΩετࣗମͷݴޠͷGrammarͷϧʔτ RuleΛࢀর͢Δɻ௨ৗ͸$selfͱಉ͡ҙຯ͕ͩɺ ݴޠຒΊࠐΈ͕ൃੜ͍ͯ͠Δ৔߹ʹ͸ɺϧʔτͷ ݴޠΛࢀর͢Δ఺͕ҟͳΔɻ Cݴޠ͸C++΍Objective-C͔ΒຒΊࠐ·Εͯ࢖Θ ΕΔͨΊɺࣗݾ࠶ؼ͢Δͱ͜ΖͰ$baseΛ࢖ͬͯ ͍Δɻ 64

  65. <scope name>#<rule name> 65

  66. { "begin": "@\"", "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.objc" }

    }, "end": "\"", "endCaptures": { "0": { "name": "punctuation.definition.string.end.objc" } }, "name": "string.quoted.double.objc", "patterns": [ { "include": "source.c#string_escaped_char" }, { "match": "(?x)%\n" "\t\t\t\t\t\t(\\d+\\$)? # field (argument #)\n" "\t\t\t\t\t\t[#0\\- +']* # flags\n" "\t\t\t\t\t\t((-?\\d+)|\\*(-?\\d+\\$)?)? # minimum field width\n" "\t\t\t\t\t\t(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)? # precision\n" "\t\t\t\t\t\t[@] # conversion type\n" "\t\t\t\t\t", "name": "constant.other.placeholder.objc" }, { "include": "source.c#string_placeholder" } ] } 66
  67. ผݴޠࢀরͱϦϙδτϦࢀরΛͻͱ·ͱΊʹॻ͚ Δɻ ྫͰ͸ɺObjective-Cจࣈྻͷ಺෦ͰCͷจ๏Λࢀ র͍ͯ͠Δɻ 67

  68. disabled 68

  69. { "regular_expressions": { "comment": "Changed disabled to 1 to turn

    off syntax highlighting in “r” strings.", "disabled": 0, "patterns": [ { "include": "source.regexp.python" } ] } } 69
  70. disabled͕ઃఆ͞Ε͍ͯΔRule͸ॻ͔Ε͍ͯͳ͍ ΋ͷͱͯ͠ѻ͏ɻ 70

  71. ఀࢭอূ 71

  72. ·͍ͣϧʔϧΛॻ͘ͱςΩετͷॲཧҐஔ͕ਐ· ͳ͘ͳΓɺύʔα͕ແݶϧʔϓͯ͠͠·͏ͷͰɺ ͦ͏ͨ͠ύλʔϯΛݕग़ͯ͠ఀࢭ͢ΔϩδοΫ͕ ඞཁɻ 72

  73. Injection 73

  74. { "scopeName": "todo-comment.injection", "injectionSelector": "L:comment.line.double-slash", "patterns": [ { "include": "#todo-keyword"

    } ], "repository": { "todo-keyword": { "match": "TODO", "name": "keyword.todo" } } } 74
  75. { "injectionSelector": "text, string, comment", "name": "Hyperlink", "patterns": [ {

    "match": "(?x)\n" "\t\t\t\t( (https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man(-page)?|gopher|txmt|issue)://|mailto:)\n" "\t\t\t\t[-:@a-zA-Z0-9_.,~%+/?=&#;]+(?<![-.,?:#;])\n" "\t\t\t", "name": "markup.underline.link.$2.hyperlink" }, { "match": "(?i)\\bRFC(?: |(?<= RFC))(\\d+)\\b", "name": "markup.underline.link.rfc.$1.hyperlink" } ], "scopeName": "text.hyperlink" } 75
  76. ͋Δߏจఆٛʹରͯ͠ɺผͷߏจΛૠೖ͢Δػ ೳɻૠೖҐஔΛinjectionSelectorͰࢦఆ͢Δɻ ઌͷྫͰ͸ɺطଘจ๏ͷίϝϯτ෦෼ͷTODOΛ ϋΠϥΠτͨ͠ΓɺจࣈྻϦςϥϧ΍ίϝϯτத ͷURLΛϋΠϥΠτ͍ͯ͠Δɻ 76

  77. { "injections": { "text.html.php - (meta.embedded | meta.tag), " "L:text.html.php

    meta.tag, " "L:source.js.embedded.html": { "patterns": [ { }, { }, { } ] } }, "name": "PHP", "patterns": [ { "include": "text.html.basic" } ], "repository": { } } 77
  78. Grammarࣗ਎͕injectionΛ࣋ͭ͜ͱ΋Ͱ͖Δɻ͜ ͷGrammarͷॲཧதʹ͓͍ͯɺ͜ͷinjection͕ద ٓૠೖ͞ΕΔɻ 78

  79. BeginWhile Rule ௐࠪத 79

  80. Embedded Language ௐࠪத 80

  81. ൃలฤ ·ͱΊ ͨ͘͞Μ͋Δ͔ΒҰ࣮ͭͣͭ૷͠Α͏ 81

  82. ࢲͷ࣮૷ https://github.com/omochi/TMSyntax SwiftͰ࣮૷ɻ ࠓ೔ͷ࿩Λ΄΅࣮૷ɻ 82

  83. ਖ਼نදݱͷͨΊʹOnigmoͷSwiftϒϦοδΛ࡞ ੒ɻ https://github.com/omochi/Onigmo-swift-build 83

  84. Onigmoͷ࣮૷ʹෆ౎߹͕͋ΓɺUTF-8͕31bit· Ͱαϙʔτ͢ΔΑ͏ʹύονΛఏग़ https://github.com/k-takata/Onigmo/pull/111 https://qiita.com/omochimetaru/items/ 3dd5a3aa5ff476f47e79 84

  85. σόοΨϏϦςΟͷ޲্ΛૂͬͯJSONύʔαΛ ࣗ࡞ TMSyntaxͰJSONͷߏจఆٛΛಡΈࠐΜͰ͍Δ ࣌ɺ JSONΛύʔε͢ΔͨΊͷߏจఆ͕ٛॻ͔Εͨ JSONΛύʔε͢ΔͨΊͷࣗ࡞ͷJSONύʔαʔ͕ ૸͍ͬͯΔ ! 85

  86. σίʔυͨ͠ܕʹߦ൪߸͕͍ͭͯ͘Δɻ ίϝϯτ͕ॻ͚Δɻ https://github.com/omochi/FineJSON https://github.com/omochi/RichJSONParser 86

  87. ύʔα͸Foundation.NSJSONSerializationΑΓ 2.5ഒ஗͍ɻ ϑΥʔϥϜʹॻ͖ࠐΜ͚ͩͲϨε͔ͭͣ https://forums.swift.org/t/how-to-write-fast-json- parser-in-swift/20281 87

  88. Ϣχοτςετ VSCodeͷςετεΠʔτΛม׵ͯ͠औΓࠐΜͰ ςετɻ First Mate Test Suite શ46݅ʹ߹֨ɻ First Mate͸AtomͷTextMate

    Syntax࣮૷Ͱɺ VSCode͸ͦͷςετεΠʔτΛม׵ͯ͠औΓࠐ ΜͰ͍Δɻ 88
  89. ల๬ iPad޲͚ͷ։ൃऀ޲͚ΤσΟλͱ͔࡞ΕΔ͔΋ʁ 89